diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-01-06 03:04:32 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-01-06 03:04:32 -0500 |
commit | d12418fdeafdc08dd5bbec89d3e07e47ee75da55 (patch) | |
tree | ac94d5bf58360b89fc7439fb52182c17d0674b0a /drivers | |
parent | c2d1cec1c77f7714672c1efeae075424c929e0d5 (diff) | |
parent | 238c6d54830c624f34ac9cf123ac04aebfca5013 (diff) |
Merge branch 'linus' into cpus4096
Diffstat (limited to 'drivers')
101 files changed, 7439 insertions, 3350 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 31d6f535a79d..01dde80597f7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -754,6 +754,11 @@ static struct kobj_type ktype_cpufreq = { | |||
754 | .release = cpufreq_sysfs_release, | 754 | .release = cpufreq_sysfs_release, |
755 | }; | 755 | }; |
756 | 756 | ||
757 | static struct kobj_type ktype_empty_cpufreq = { | ||
758 | .sysfs_ops = &sysfs_ops, | ||
759 | .release = cpufreq_sysfs_release, | ||
760 | }; | ||
761 | |||
757 | 762 | ||
758 | /** | 763 | /** |
759 | * cpufreq_add_dev - add a CPU device | 764 | * cpufreq_add_dev - add a CPU device |
@@ -822,8 +827,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
822 | dprintk("initialization failed\n"); | 827 | dprintk("initialization failed\n"); |
823 | goto err_out; | 828 | goto err_out; |
824 | } | 829 | } |
825 | policy->user_policy.min = policy->cpuinfo.min_freq; | 830 | policy->user_policy.min = policy->min; |
826 | policy->user_policy.max = policy->cpuinfo.max_freq; | 831 | policy->user_policy.max = policy->max; |
827 | 832 | ||
828 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, | 833 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
829 | CPUFREQ_START, policy); | 834 | CPUFREQ_START, policy); |
@@ -876,26 +881,36 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
876 | memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); | 881 | memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); |
877 | 882 | ||
878 | /* prepare interface data */ | 883 | /* prepare interface data */ |
879 | ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, | 884 | if (!cpufreq_driver->hide_interface) { |
880 | "cpufreq"); | 885 | ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, |
881 | if (ret) | 886 | &sys_dev->kobj, "cpufreq"); |
882 | goto err_out_driver_exit; | ||
883 | |||
884 | /* set up files for this cpu device */ | ||
885 | drv_attr = cpufreq_driver->attr; | ||
886 | while ((drv_attr) && (*drv_attr)) { | ||
887 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); | ||
888 | if (ret) | 887 | if (ret) |
889 | goto err_out_driver_exit; | 888 | goto err_out_driver_exit; |
890 | drv_attr++; | 889 | |
891 | } | 890 | /* set up files for this cpu device */ |
892 | if (cpufreq_driver->get) { | 891 | drv_attr = cpufreq_driver->attr; |
893 | ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); | 892 | while ((drv_attr) && (*drv_attr)) { |
894 | if (ret) | 893 | ret = sysfs_create_file(&policy->kobj, |
895 | goto err_out_driver_exit; | 894 | &((*drv_attr)->attr)); |
896 | } | 895 | if (ret) |
897 | if (cpufreq_driver->target) { | 896 | goto err_out_driver_exit; |
898 | ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); | 897 | drv_attr++; |
898 | } | ||
899 | if (cpufreq_driver->get) { | ||
900 | ret = sysfs_create_file(&policy->kobj, | ||
901 | &cpuinfo_cur_freq.attr); | ||
902 | if (ret) | ||
903 | goto err_out_driver_exit; | ||
904 | } | ||
905 | if (cpufreq_driver->target) { | ||
906 | ret = sysfs_create_file(&policy->kobj, | ||
907 | &scaling_cur_freq.attr); | ||
908 | if (ret) | ||
909 | goto err_out_driver_exit; | ||
910 | } | ||
911 | } else { | ||
912 | ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq, | ||
913 | &sys_dev->kobj, "cpufreq"); | ||
899 | if (ret) | 914 | if (ret) |
900 | goto err_out_driver_exit; | 915 | goto err_out_driver_exit; |
901 | } | 916 | } |
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index b4fd8ca701a4..e85c8fe9ffcf 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -85,14 +85,14 @@ config HID_COMPAT | |||
85 | config HID_A4TECH | 85 | config HID_A4TECH |
86 | tristate "A4 tech" if EMBEDDED | 86 | tristate "A4 tech" if EMBEDDED |
87 | depends on USB_HID | 87 | depends on USB_HID |
88 | default y | 88 | default !EMBEDDED |
89 | ---help--- | 89 | ---help--- |
90 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. | 90 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
91 | 91 | ||
92 | config HID_APPLE | 92 | config HID_APPLE |
93 | tristate "Apple" if EMBEDDED | 93 | tristate "Apple" if EMBEDDED |
94 | depends on (USB_HID || BT_HIDP) | 94 | depends on (USB_HID || BT_HIDP) |
95 | default y | 95 | default !EMBEDDED |
96 | ---help--- | 96 | ---help--- |
97 | Support for some Apple devices which less or more break | 97 | Support for some Apple devices which less or more break |
98 | HID specification. | 98 | HID specification. |
@@ -103,64 +103,49 @@ config HID_APPLE | |||
103 | config HID_BELKIN | 103 | config HID_BELKIN |
104 | tristate "Belkin" if EMBEDDED | 104 | tristate "Belkin" if EMBEDDED |
105 | depends on USB_HID | 105 | depends on USB_HID |
106 | default y | 106 | default !EMBEDDED |
107 | ---help--- | 107 | ---help--- |
108 | Support for Belkin Flip KVM and Wireless keyboard. | 108 | Support for Belkin Flip KVM and Wireless keyboard. |
109 | 109 | ||
110 | config HID_BRIGHT | ||
111 | tristate "Bright" if EMBEDDED | ||
112 | depends on USB_HID | ||
113 | default y | ||
114 | ---help--- | ||
115 | Support for Bright ABNT-2 keyboard. | ||
116 | |||
117 | config HID_CHERRY | 110 | config HID_CHERRY |
118 | tristate "Cherry" if EMBEDDED | 111 | tristate "Cherry" if EMBEDDED |
119 | depends on USB_HID | 112 | depends on USB_HID |
120 | default y | 113 | default !EMBEDDED |
121 | ---help--- | 114 | ---help--- |
122 | Support for Cherry Cymotion keyboard. | 115 | Support for Cherry Cymotion keyboard. |
123 | 116 | ||
124 | config HID_CHICONY | 117 | config HID_CHICONY |
125 | tristate "Chicony" if EMBEDDED | 118 | tristate "Chicony" if EMBEDDED |
126 | depends on USB_HID | 119 | depends on USB_HID |
127 | default y | 120 | default !EMBEDDED |
128 | ---help--- | 121 | ---help--- |
129 | Support for Chicony Tactical pad. | 122 | Support for Chicony Tactical pad. |
130 | 123 | ||
131 | config HID_CYPRESS | 124 | config HID_CYPRESS |
132 | tristate "Cypress" if EMBEDDED | 125 | tristate "Cypress" if EMBEDDED |
133 | depends on USB_HID | 126 | depends on USB_HID |
134 | default y | 127 | default !EMBEDDED |
135 | ---help--- | 128 | ---help--- |
136 | Support for cypress mouse and barcode readers. | 129 | Support for cypress mouse and barcode readers. |
137 | 130 | ||
138 | config HID_DELL | ||
139 | tristate "Dell" if EMBEDDED | ||
140 | depends on USB_HID | ||
141 | default y | ||
142 | ---help--- | ||
143 | Support for quirky Dell HID hardware that require | ||
144 | special LED handling (W7658 and SK8115 models) | ||
145 | |||
146 | config HID_EZKEY | 131 | config HID_EZKEY |
147 | tristate "Ezkey" if EMBEDDED | 132 | tristate "Ezkey" if EMBEDDED |
148 | depends on USB_HID | 133 | depends on USB_HID |
149 | default y | 134 | default !EMBEDDED |
150 | ---help--- | 135 | ---help--- |
151 | Support for Ezkey BTC 8193 keyboard. | 136 | Support for Ezkey BTC 8193 keyboard. |
152 | 137 | ||
153 | config HID_GYRATION | 138 | config HID_GYRATION |
154 | tristate "Gyration" if EMBEDDED | 139 | tristate "Gyration" if EMBEDDED |
155 | depends on USB_HID | 140 | depends on USB_HID |
156 | default y | 141 | default !EMBEDDED |
157 | ---help--- | 142 | ---help--- |
158 | Support for Gyration remote control. | 143 | Support for Gyration remote control. |
159 | 144 | ||
160 | config HID_LOGITECH | 145 | config HID_LOGITECH |
161 | tristate "Logitech" if EMBEDDED | 146 | tristate "Logitech" if EMBEDDED |
162 | depends on USB_HID | 147 | depends on USB_HID |
163 | default y | 148 | default !EMBEDDED |
164 | ---help--- | 149 | ---help--- |
165 | Support for Logitech devices that are not fully compliant with HID standard. | 150 | Support for Logitech devices that are not fully compliant with HID standard. |
166 | 151 | ||
@@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF | |||
191 | config HID_MICROSOFT | 176 | config HID_MICROSOFT |
192 | tristate "Microsoft" if EMBEDDED | 177 | tristate "Microsoft" if EMBEDDED |
193 | depends on USB_HID | 178 | depends on USB_HID |
194 | default y | 179 | default !EMBEDDED |
195 | ---help--- | 180 | ---help--- |
196 | Support for Microsoft devices that are not fully compliant with HID standard. | 181 | Support for Microsoft devices that are not fully compliant with HID standard. |
197 | 182 | ||
198 | config HID_MONTEREY | 183 | config HID_MONTEREY |
199 | tristate "Monterey" if EMBEDDED | 184 | tristate "Monterey" if EMBEDDED |
200 | depends on USB_HID | 185 | depends on USB_HID |
201 | default y | 186 | default !EMBEDDED |
202 | ---help--- | 187 | ---help--- |
203 | Support for Monterey Genius KB29E. | 188 | Support for Monterey Genius KB29E. |
204 | 189 | ||
190 | config HID_NTRIG | ||
191 | tristate "NTrig" if EMBEDDED | ||
192 | depends on USB_HID | ||
193 | default !EMBEDDED | ||
194 | ---help--- | ||
195 | Support for N-Trig touch screen. | ||
196 | |||
205 | config HID_PANTHERLORD | 197 | config HID_PANTHERLORD |
206 | tristate "Pantherlord devices support" if EMBEDDED | 198 | tristate "Pantherlord devices support" if EMBEDDED |
207 | depends on USB_HID | 199 | depends on USB_HID |
208 | default y | 200 | default !EMBEDDED |
209 | ---help--- | 201 | ---help--- |
210 | Support for PantherLord/GreenAsia based device support. | 202 | Support for PantherLord/GreenAsia based device support. |
211 | 203 | ||
@@ -220,31 +212,47 @@ config PANTHERLORD_FF | |||
220 | config HID_PETALYNX | 212 | config HID_PETALYNX |
221 | tristate "Petalynx" if EMBEDDED | 213 | tristate "Petalynx" if EMBEDDED |
222 | depends on USB_HID | 214 | depends on USB_HID |
223 | default y | 215 | default !EMBEDDED |
224 | ---help--- | 216 | ---help--- |
225 | Support for Petalynx Maxter remote control. | 217 | Support for Petalynx Maxter remote control. |
226 | 218 | ||
227 | config HID_SAMSUNG | 219 | config HID_SAMSUNG |
228 | tristate "Samsung" if EMBEDDED | 220 | tristate "Samsung" if EMBEDDED |
229 | depends on USB_HID | 221 | depends on USB_HID |
230 | default y | 222 | default !EMBEDDED |
231 | ---help--- | 223 | ---help--- |
232 | Support for Samsung InfraRed remote control. | 224 | Support for Samsung InfraRed remote control. |
233 | 225 | ||
234 | config HID_SONY | 226 | config HID_SONY |
235 | tristate "Sony" if EMBEDDED | 227 | tristate "Sony" if EMBEDDED |
236 | depends on USB_HID | 228 | depends on USB_HID |
237 | default y | 229 | default !EMBEDDED |
238 | ---help--- | 230 | ---help--- |
239 | Support for Sony PS3 controller. | 231 | Support for Sony PS3 controller. |
240 | 232 | ||
241 | config HID_SUNPLUS | 233 | config HID_SUNPLUS |
242 | tristate "Sunplus" if EMBEDDED | 234 | tristate "Sunplus" if EMBEDDED |
243 | depends on USB_HID | 235 | depends on USB_HID |
244 | default y | 236 | default !EMBEDDED |
245 | ---help--- | 237 | ---help--- |
246 | Support for Sunplus wireless desktop. | 238 | Support for Sunplus wireless desktop. |
247 | 239 | ||
240 | config GREENASIA_FF | ||
241 | tristate "GreenAsia (Product ID 0x12) force feedback support" | ||
242 | depends on USB_HID | ||
243 | select INPUT_FF_MEMLESS | ||
244 | ---help--- | ||
245 | Say Y here if you have a GreenAsia (Product ID 0x12) based game controller | ||
246 | (like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter | ||
247 | and want to enable force feedback support for it. | ||
248 | |||
249 | config HID_TOPSEED | ||
250 | tristate "TopSeed Cyberlink remote control support" if EMBEDDED | ||
251 | depends on USB_HID | ||
252 | default !EMBEDDED | ||
253 | ---help--- | ||
254 | Say Y if you have a TopSeed Cyberlink remote control. | ||
255 | |||
248 | config THRUSTMASTER_FF | 256 | config THRUSTMASTER_FF |
249 | tristate "ThrustMaster devices support" | 257 | tristate "ThrustMaster devices support" |
250 | depends on USB_HID | 258 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b09e43e7413e..fbd021f153f1 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -23,22 +23,23 @@ endif | |||
23 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 23 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
24 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 24 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
25 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o | 25 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o |
26 | obj-$(CONFIG_HID_BRIGHT) += hid-bright.o | ||
27 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o | 26 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
28 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | 27 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
29 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 28 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
30 | obj-$(CONFIG_HID_DELL) += hid-dell.o | ||
31 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 29 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
32 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 30 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
33 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 31 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
34 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 32 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
35 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 33 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
34 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o | ||
36 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | 35 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o |
37 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 36 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
38 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 37 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
39 | obj-$(CONFIG_HID_SONY) += hid-sony.o | 38 | obj-$(CONFIG_HID_SONY) += hid-sony.o |
40 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o | 39 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o |
40 | obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o | ||
41 | obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o | 41 | obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o |
42 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | ||
42 | obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o | 43 | obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o |
43 | 44 | ||
44 | obj-$(CONFIG_USB_HID) += usbhid/ | 45 | obj-$(CONFIG_USB_HID) += usbhid/ |
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c deleted file mode 100644 index 38517a117dfd..000000000000 --- a/drivers/hid/hid-bright.c +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for some bright "special" devices | ||
3 | * | ||
4 | * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com> | ||
5 | * | ||
6 | * Based on hid-dell driver | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation; either version 2 of the License, or (at your option) | ||
13 | * any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/device.h> | ||
17 | #include <linux/hid.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include "hid-ids.h" | ||
21 | |||
22 | static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
23 | { | ||
24 | int ret; | ||
25 | |||
26 | ret = hid_parse(hdev); | ||
27 | if (ret) { | ||
28 | dev_err(&hdev->dev, "parse failed\n"); | ||
29 | goto err_free; | ||
30 | } | ||
31 | |||
32 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
33 | if (ret) { | ||
34 | dev_err(&hdev->dev, "hw start failed\n"); | ||
35 | goto err_free; | ||
36 | } | ||
37 | |||
38 | usbhid_set_leds(hdev); | ||
39 | |||
40 | return 0; | ||
41 | err_free: | ||
42 | return ret; | ||
43 | } | ||
44 | |||
45 | static const struct hid_device_id bright_devices[] = { | ||
46 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | ||
47 | { } | ||
48 | }; | ||
49 | MODULE_DEVICE_TABLE(hid, bright_devices); | ||
50 | |||
51 | static struct hid_driver bright_driver = { | ||
52 | .name = "bright", | ||
53 | .id_table = bright_devices, | ||
54 | .probe = bright_probe, | ||
55 | }; | ||
56 | |||
57 | static int bright_init(void) | ||
58 | { | ||
59 | return hid_register_driver(&bright_driver); | ||
60 | } | ||
61 | |||
62 | static void bright_exit(void) | ||
63 | { | ||
64 | hid_unregister_driver(&bright_driver); | ||
65 | } | ||
66 | |||
67 | module_init(bright_init); | ||
68 | module_exit(bright_exit); | ||
69 | MODULE_LICENSE("GPL"); | ||
70 | |||
71 | HID_COMPAT_LOAD_DRIVER(bright); | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 40df3e1b4bd1..5d7640e49dc5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1256,19 +1256,16 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
1259 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | ||
1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1259 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
1261 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1261 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
1263 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
1264 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1263 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1265 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | ||
1266 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | ||
1267 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1264 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, | 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
1271 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, |
1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | ||
1272 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1273 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1274 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
@@ -1279,7 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, | 1276 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, |
1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, | 1277 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, |
1281 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, | 1278 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, |
1282 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) }, | ||
1283 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, | 1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, |
1284 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, | 1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, |
1285 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, | 1281 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, |
@@ -1297,23 +1293,105 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, |
1298 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, |
1299 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, | ||
1300 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1301 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
1302 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
1303 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, | 1300 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, |
1304 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
1302 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | ||
1305 | 1303 | ||
1306 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, | 1304 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, |
1307 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, | 1305 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, |
1308 | { } | 1306 | { } |
1309 | }; | 1307 | }; |
1310 | 1308 | ||
1309 | struct hid_dynid { | ||
1310 | struct list_head list; | ||
1311 | struct hid_device_id id; | ||
1312 | }; | ||
1313 | |||
1314 | /** | ||
1315 | * store_new_id - add a new HID device ID to this driver and re-probe devices | ||
1316 | * @driver: target device driver | ||
1317 | * @buf: buffer for scanning device ID data | ||
1318 | * @count: input size | ||
1319 | * | ||
1320 | * Adds a new dynamic hid device ID to this driver, | ||
1321 | * and causes the driver to probe for all devices again. | ||
1322 | */ | ||
1323 | static ssize_t store_new_id(struct device_driver *drv, const char *buf, | ||
1324 | size_t count) | ||
1325 | { | ||
1326 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | ||
1327 | struct hid_dynid *dynid; | ||
1328 | __u32 bus, vendor, product; | ||
1329 | unsigned long driver_data = 0; | ||
1330 | int ret; | ||
1331 | |||
1332 | ret = sscanf(buf, "%x %x %x %lx", | ||
1333 | &bus, &vendor, &product, &driver_data); | ||
1334 | if (ret < 3) | ||
1335 | return -EINVAL; | ||
1336 | |||
1337 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); | ||
1338 | if (!dynid) | ||
1339 | return -ENOMEM; | ||
1340 | |||
1341 | dynid->id.bus = bus; | ||
1342 | dynid->id.vendor = vendor; | ||
1343 | dynid->id.product = product; | ||
1344 | dynid->id.driver_data = driver_data; | ||
1345 | |||
1346 | spin_lock(&hdrv->dyn_lock); | ||
1347 | list_add_tail(&dynid->list, &hdrv->dyn_list); | ||
1348 | spin_unlock(&hdrv->dyn_lock); | ||
1349 | |||
1350 | ret = 0; | ||
1351 | if (get_driver(&hdrv->driver)) { | ||
1352 | ret = driver_attach(&hdrv->driver); | ||
1353 | put_driver(&hdrv->driver); | ||
1354 | } | ||
1355 | |||
1356 | return ret ? : count; | ||
1357 | } | ||
1358 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | ||
1359 | |||
1360 | static void hid_free_dynids(struct hid_driver *hdrv) | ||
1361 | { | ||
1362 | struct hid_dynid *dynid, *n; | ||
1363 | |||
1364 | spin_lock(&hdrv->dyn_lock); | ||
1365 | list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) { | ||
1366 | list_del(&dynid->list); | ||
1367 | kfree(dynid); | ||
1368 | } | ||
1369 | spin_unlock(&hdrv->dyn_lock); | ||
1370 | } | ||
1371 | |||
1372 | static const struct hid_device_id *hid_match_device(struct hid_device *hdev, | ||
1373 | struct hid_driver *hdrv) | ||
1374 | { | ||
1375 | struct hid_dynid *dynid; | ||
1376 | |||
1377 | spin_lock(&hdrv->dyn_lock); | ||
1378 | list_for_each_entry(dynid, &hdrv->dyn_list, list) { | ||
1379 | if (hid_match_one_id(hdev, &dynid->id)) { | ||
1380 | spin_unlock(&hdrv->dyn_lock); | ||
1381 | return &dynid->id; | ||
1382 | } | ||
1383 | } | ||
1384 | spin_unlock(&hdrv->dyn_lock); | ||
1385 | |||
1386 | return hid_match_id(hdev, hdrv->id_table); | ||
1387 | } | ||
1388 | |||
1311 | static int hid_bus_match(struct device *dev, struct device_driver *drv) | 1389 | static int hid_bus_match(struct device *dev, struct device_driver *drv) |
1312 | { | 1390 | { |
1313 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | 1391 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); |
1314 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | 1392 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
1315 | 1393 | ||
1316 | if (!hid_match_id(hdev, hdrv->id_table)) | 1394 | if (!hid_match_device(hdev, hdrv)) |
1317 | return 0; | 1395 | return 0; |
1318 | 1396 | ||
1319 | /* generic wants all non-blacklisted */ | 1397 | /* generic wants all non-blacklisted */ |
@@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev) | |||
1332 | int ret = 0; | 1410 | int ret = 0; |
1333 | 1411 | ||
1334 | if (!hdev->driver) { | 1412 | if (!hdev->driver) { |
1335 | id = hid_match_id(hdev, hdrv->id_table); | 1413 | id = hid_match_device(hdev, hdrv); |
1336 | if (id == NULL) | 1414 | if (id == NULL) |
1337 | return -ENODEV; | 1415 | return -ENODEV; |
1338 | 1416 | ||
@@ -1420,6 +1498,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1420 | { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, | 1498 | { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, |
1421 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, | 1499 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, |
1422 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, | 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, |
1501 | { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, | ||
1423 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, | 1502 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, |
1424 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, |
1425 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
@@ -1577,6 +1656,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
1577 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1656 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
1578 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1657 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
1579 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1658 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
1659 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
1660 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
1661 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
1580 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1662 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1581 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1663 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1582 | { } | 1664 | { } |
@@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev) | |||
1618 | if (hid_ignore(hdev)) | 1700 | if (hid_ignore(hdev)) |
1619 | return -ENODEV; | 1701 | return -ENODEV; |
1620 | 1702 | ||
1621 | /* XXX hack, any other cleaner solution < 20 bus_id bytes? */ | 1703 | /* XXX hack, any other cleaner solution after the driver core |
1622 | sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus, | 1704 | * is converted to allow more than 20 bytes as the device name? */ |
1623 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | 1705 | dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, |
1706 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | ||
1624 | 1707 | ||
1625 | ret = device_add(&hdev->dev); | 1708 | ret = device_add(&hdev->dev); |
1626 | if (!ret) | 1709 | if (!ret) |
@@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device); | |||
1695 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, | 1778 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, |
1696 | const char *mod_name) | 1779 | const char *mod_name) |
1697 | { | 1780 | { |
1781 | int ret; | ||
1782 | |||
1698 | hdrv->driver.name = hdrv->name; | 1783 | hdrv->driver.name = hdrv->name; |
1699 | hdrv->driver.bus = &hid_bus_type; | 1784 | hdrv->driver.bus = &hid_bus_type; |
1700 | hdrv->driver.owner = owner; | 1785 | hdrv->driver.owner = owner; |
1701 | hdrv->driver.mod_name = mod_name; | 1786 | hdrv->driver.mod_name = mod_name; |
1702 | 1787 | ||
1703 | return driver_register(&hdrv->driver); | 1788 | INIT_LIST_HEAD(&hdrv->dyn_list); |
1789 | spin_lock_init(&hdrv->dyn_lock); | ||
1790 | |||
1791 | ret = driver_register(&hdrv->driver); | ||
1792 | if (ret) | ||
1793 | return ret; | ||
1794 | |||
1795 | ret = driver_create_file(&hdrv->driver, &driver_attr_new_id); | ||
1796 | if (ret) | ||
1797 | driver_unregister(&hdrv->driver); | ||
1798 | |||
1799 | return ret; | ||
1704 | } | 1800 | } |
1705 | EXPORT_SYMBOL_GPL(__hid_register_driver); | 1801 | EXPORT_SYMBOL_GPL(__hid_register_driver); |
1706 | 1802 | ||
1707 | void hid_unregister_driver(struct hid_driver *hdrv) | 1803 | void hid_unregister_driver(struct hid_driver *hdrv) |
1708 | { | 1804 | { |
1805 | driver_remove_file(&hdrv->driver, &driver_attr_new_id); | ||
1709 | driver_unregister(&hdrv->driver); | 1806 | driver_unregister(&hdrv->driver); |
1807 | hid_free_dynids(hdrv); | ||
1710 | } | 1808 | } |
1711 | EXPORT_SYMBOL_GPL(hid_unregister_driver); | 1809 | EXPORT_SYMBOL_GPL(hid_unregister_driver); |
1712 | 1810 | ||
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c deleted file mode 100644 index f5474300b83a..000000000000 --- a/drivers/hid/hid-dell.c +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for some dell "special" devices | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
8 | * Copyright (c) 2007 Paul Walmsley | ||
9 | * Copyright (c) 2008 Jiri Slaby | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the Free | ||
15 | * Software Foundation; either version 2 of the License, or (at your option) | ||
16 | * any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/hid.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include "hid-ids.h" | ||
24 | |||
25 | static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
26 | { | ||
27 | int ret; | ||
28 | |||
29 | ret = hid_parse(hdev); | ||
30 | if (ret) { | ||
31 | dev_err(&hdev->dev, "parse failed\n"); | ||
32 | goto err_free; | ||
33 | } | ||
34 | |||
35 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
36 | if (ret) { | ||
37 | dev_err(&hdev->dev, "hw start failed\n"); | ||
38 | goto err_free; | ||
39 | } | ||
40 | |||
41 | usbhid_set_leds(hdev); | ||
42 | |||
43 | return 0; | ||
44 | err_free: | ||
45 | return ret; | ||
46 | } | ||
47 | |||
48 | static const struct hid_device_id dell_devices[] = { | ||
49 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | ||
50 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | ||
51 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
52 | { } | ||
53 | }; | ||
54 | MODULE_DEVICE_TABLE(hid, dell_devices); | ||
55 | |||
56 | static struct hid_driver dell_driver = { | ||
57 | .name = "dell", | ||
58 | .id_table = dell_devices, | ||
59 | .probe = dell_probe, | ||
60 | }; | ||
61 | |||
62 | static int dell_init(void) | ||
63 | { | ||
64 | return hid_register_driver(&dell_driver); | ||
65 | } | ||
66 | |||
67 | static void dell_exit(void) | ||
68 | { | ||
69 | hid_unregister_driver(&dell_driver); | ||
70 | } | ||
71 | |||
72 | module_init(dell_init); | ||
73 | module_exit(dell_exit); | ||
74 | MODULE_LICENSE("GPL"); | ||
75 | |||
76 | HID_COMPAT_LOAD_DRIVER(dell); | ||
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c index e148f86fb58e..b4cc0f743d63 100644 --- a/drivers/hid/hid-dummy.c +++ b/drivers/hid/hid-dummy.c | |||
@@ -43,6 +43,9 @@ static int __init hid_dummy_init(void) | |||
43 | #ifdef CONFIG_HID_MONTEREY_MODULE | 43 | #ifdef CONFIG_HID_MONTEREY_MODULE |
44 | HID_COMPAT_CALL_DRIVER(monterey); | 44 | HID_COMPAT_CALL_DRIVER(monterey); |
45 | #endif | 45 | #endif |
46 | #ifdef CONFIG_HID_NTRIG_MODULE | ||
47 | HID_COMPAT_CALL_DRIVER(ntrig); | ||
48 | #endif | ||
46 | #ifdef CONFIG_HID_PANTHERLORD_MODULE | 49 | #ifdef CONFIG_HID_PANTHERLORD_MODULE |
47 | HID_COMPAT_CALL_DRIVER(pantherlord); | 50 | HID_COMPAT_CALL_DRIVER(pantherlord); |
48 | #endif | 51 | #endif |
@@ -58,6 +61,9 @@ static int __init hid_dummy_init(void) | |||
58 | #ifdef CONFIG_HID_SUNPLUS_MODULE | 61 | #ifdef CONFIG_HID_SUNPLUS_MODULE |
59 | HID_COMPAT_CALL_DRIVER(sunplus); | 62 | HID_COMPAT_CALL_DRIVER(sunplus); |
60 | #endif | 63 | #endif |
64 | #ifdef CONFIG_GREENASIA_FF_MODULE | ||
65 | HID_COMPAT_CALL_DRIVER(greenasia); | ||
66 | #endif | ||
61 | #ifdef CONFIG_THRUSTMASTER_FF_MODULE | 67 | #ifdef CONFIG_THRUSTMASTER_FF_MODULE |
62 | HID_COMPAT_CALL_DRIVER(thrustmaster); | 68 | HID_COMPAT_CALL_DRIVER(thrustmaster); |
63 | #endif | 69 | #endif |
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c new file mode 100644 index 000000000000..71211f6a4f02 --- /dev/null +++ b/drivers/hid/hid-gaff.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Force feedback support for GreenAsia (Product ID 0x12) based devices | ||
3 | * | ||
4 | * The devices are distributed under various names and the same USB device ID | ||
5 | * can be used in many game controllers. | ||
6 | * | ||
7 | * | ||
8 | * 0e8f:0012 "GreenAsia Inc. USB Joystick " | ||
9 | * - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635. | ||
10 | * | ||
11 | * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info> | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
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/input.h> | ||
31 | #include <linux/usb.h> | ||
32 | #include <linux/hid.h> | ||
33 | #include "hid-ids.h" | ||
34 | #include "usbhid/usbhid.h" | ||
35 | |||
36 | struct gaff_device { | ||
37 | struct hid_report *report; | ||
38 | }; | ||
39 | |||
40 | static int hid_gaff_play(struct input_dev *dev, void *data, | ||
41 | struct ff_effect *effect) | ||
42 | { | ||
43 | struct hid_device *hid = input_get_drvdata(dev); | ||
44 | struct gaff_device *gaff = data; | ||
45 | int left, right; | ||
46 | |||
47 | left = effect->u.rumble.strong_magnitude; | ||
48 | right = effect->u.rumble.weak_magnitude; | ||
49 | |||
50 | dbg_hid("called with 0x%04x 0x%04x", left, right); | ||
51 | |||
52 | left = left * 0xfe / 0xffff; | ||
53 | right = right * 0xfe / 0xffff; | ||
54 | |||
55 | gaff->report->field[0]->value[0] = 0x51; | ||
56 | gaff->report->field[0]->value[1] = 0x0; | ||
57 | gaff->report->field[0]->value[2] = right; | ||
58 | gaff->report->field[0]->value[3] = 0; | ||
59 | gaff->report->field[0]->value[4] = left; | ||
60 | gaff->report->field[0]->value[5] = 0; | ||
61 | dbg_hid("running with 0x%02x 0x%02x", left, right); | ||
62 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
63 | |||
64 | gaff->report->field[0]->value[0] = 0xfa; | ||
65 | gaff->report->field[0]->value[1] = 0xfe; | ||
66 | gaff->report->field[0]->value[2] = 0x0; | ||
67 | gaff->report->field[0]->value[4] = 0x0; | ||
68 | |||
69 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int gaff_init(struct hid_device *hid) | ||
75 | { | ||
76 | struct gaff_device *gaff; | ||
77 | struct hid_report *report; | ||
78 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
79 | struct hid_input, list); | ||
80 | struct list_head *report_list = | ||
81 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
82 | struct list_head *report_ptr = report_list; | ||
83 | struct input_dev *dev = hidinput->input; | ||
84 | int error; | ||
85 | |||
86 | if (list_empty(report_list)) { | ||
87 | dev_err(&hid->dev, "no output reports found\n"); | ||
88 | return -ENODEV; | ||
89 | } | ||
90 | |||
91 | report_ptr = report_ptr->next; | ||
92 | |||
93 | report = list_entry(report_ptr, struct hid_report, list); | ||
94 | if (report->maxfield < 1) { | ||
95 | dev_err(&hid->dev, "no fields in the report\n"); | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | if (report->field[0]->report_count < 6) { | ||
100 | dev_err(&hid->dev, "not enough values in the field\n"); | ||
101 | return -ENODEV; | ||
102 | } | ||
103 | |||
104 | gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL); | ||
105 | if (!gaff) | ||
106 | return -ENOMEM; | ||
107 | |||
108 | set_bit(FF_RUMBLE, dev->ffbit); | ||
109 | |||
110 | error = input_ff_create_memless(dev, gaff, hid_gaff_play); | ||
111 | if (error) { | ||
112 | kfree(gaff); | ||
113 | return error; | ||
114 | } | ||
115 | |||
116 | gaff->report = report; | ||
117 | gaff->report->field[0]->value[0] = 0x51; | ||
118 | gaff->report->field[0]->value[1] = 0x00; | ||
119 | gaff->report->field[0]->value[2] = 0x00; | ||
120 | gaff->report->field[0]->value[3] = 0x00; | ||
121 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
122 | |||
123 | gaff->report->field[0]->value[0] = 0xfa; | ||
124 | gaff->report->field[0]->value[1] = 0xfe; | ||
125 | |||
126 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
127 | |||
128 | dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12" | ||
129 | " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
135 | { | ||
136 | int ret; | ||
137 | |||
138 | dev_dbg(&hdev->dev, "Greenasia HID hardware probe..."); | ||
139 | |||
140 | ret = hid_parse(hdev); | ||
141 | if (ret) { | ||
142 | dev_err(&hdev->dev, "parse failed\n"); | ||
143 | goto err; | ||
144 | } | ||
145 | |||
146 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | ||
147 | if (ret) { | ||
148 | dev_err(&hdev->dev, "hw start failed\n"); | ||
149 | goto err; | ||
150 | } | ||
151 | |||
152 | gaff_init(hdev); | ||
153 | |||
154 | return 0; | ||
155 | err: | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | static const struct hid_device_id ga_devices[] = { | ||
160 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), }, | ||
161 | { } | ||
162 | }; | ||
163 | MODULE_DEVICE_TABLE(hid, ga_devices); | ||
164 | |||
165 | static struct hid_driver ga_driver = { | ||
166 | .name = "greenasia", | ||
167 | .id_table = ga_devices, | ||
168 | .probe = ga_probe, | ||
169 | }; | ||
170 | |||
171 | static int __init ga_init(void) | ||
172 | { | ||
173 | return hid_register_driver(&ga_driver); | ||
174 | } | ||
175 | |||
176 | static void __exit ga_exit(void) | ||
177 | { | ||
178 | hid_unregister_driver(&ga_driver); | ||
179 | } | ||
180 | |||
181 | module_init(ga_init); | ||
182 | module_exit(ga_exit); | ||
183 | MODULE_LICENSE("GPL"); | ||
184 | |||
185 | HID_COMPAT_LOAD_DRIVER(greenasia); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 39289699c32f..acc1abc834a4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -107,9 +107,6 @@ | |||
107 | #define USB_VENDOR_ID_BELKIN 0x050d | 107 | #define USB_VENDOR_ID_BELKIN 0x050d |
108 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 | 108 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 |
109 | 109 | ||
110 | #define USB_VENDOR_ID_BRIGHT 0x1241 | ||
111 | #define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503 | ||
112 | |||
113 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | 110 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 |
114 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | 111 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 |
115 | 112 | ||
@@ -141,9 +138,8 @@ | |||
141 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 | 138 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 |
142 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 | 139 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 |
143 | 140 | ||
144 | #define USB_VENDOR_ID_DELL 0x413c | 141 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 |
145 | #define USB_DEVICE_ID_DELL_W7658 0x2005 | 142 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a |
146 | #define USB_DEVICE_ID_DELL_SK8115 0x2105 | ||
147 | 143 | ||
148 | #define USB_VENDOR_ID_DELORME 0x1163 | 144 | #define USB_VENDOR_ID_DELORME 0x1163 |
149 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | 145 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 |
@@ -167,9 +163,6 @@ | |||
167 | 163 | ||
168 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc | 164 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc |
169 | 165 | ||
170 | #define USB_VENDOR_ID_GENERIC_13BA 0x13ba | ||
171 | #define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017 | ||
172 | |||
173 | #define USB_VENDOR_ID_GLAB 0x06c2 | 166 | #define USB_VENDOR_ID_GLAB 0x06c2 |
174 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 167 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
175 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | 168 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 |
@@ -292,7 +285,6 @@ | |||
292 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 | 285 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 |
293 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 | 286 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 |
294 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a | 287 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a |
295 | #define USB_DEVICE_ID_LOGITECH_KBD 0xc311 | ||
296 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c | 288 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c |
297 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 | 289 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 |
298 | #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 | 290 | #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 |
@@ -339,6 +331,9 @@ | |||
339 | #define USB_VENDOR_ID_NEC 0x073e | 331 | #define USB_VENDOR_ID_NEC 0x073e |
340 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | 332 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 |
341 | 333 | ||
334 | #define USB_VENDOR_ID_NTRIG 0x1b96 | ||
335 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 | ||
336 | |||
342 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | 337 | #define USB_VENDOR_ID_ONTRAK 0x0a07 |
343 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | 338 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 |
344 | 339 | ||
@@ -383,9 +378,15 @@ | |||
383 | #define USB_VENDOR_ID_TOPMAX 0x0663 | 378 | #define USB_VENDOR_ID_TOPMAX 0x0663 |
384 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | 379 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 |
385 | 380 | ||
381 | #define USB_VENDOR_ID_TOPSEED 0x0766 | ||
382 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 | ||
383 | |||
386 | #define USB_VENDOR_ID_TURBOX 0x062a | 384 | #define USB_VENDOR_ID_TURBOX 0x062a |
387 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | 385 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 |
388 | 386 | ||
387 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | ||
388 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | ||
389 | |||
389 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 390 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
390 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 391 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
391 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | 392 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 |
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 2bae340eafe2..83e07c9f4144 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #define LG_RDESC 0x001 | 26 | #define LG_RDESC 0x001 |
27 | #define LG_BAD_RELATIVE_KEYS 0x002 | 27 | #define LG_BAD_RELATIVE_KEYS 0x002 |
28 | #define LG_DUPLICATE_USAGES 0x004 | 28 | #define LG_DUPLICATE_USAGES 0x004 |
29 | #define LG_RESET_LEDS 0x008 | ||
30 | #define LG_EXPANDED_KEYMAP 0x010 | 29 | #define LG_EXPANDED_KEYMAP 0x010 |
31 | #define LG_IGNORE_DOUBLED_WHEEL 0x020 | 30 | #define LG_IGNORE_DOUBLED_WHEEL 0x020 |
32 | #define LG_WIRELESS 0x040 | 31 | #define LG_WIRELESS 0x040 |
@@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
248 | goto err_free; | 247 | goto err_free; |
249 | } | 248 | } |
250 | 249 | ||
251 | if (quirks & LG_RESET_LEDS) | ||
252 | usbhid_set_leds(hdev); | ||
253 | |||
254 | if (quirks & LG_FF) | 250 | if (quirks & LG_FF) |
255 | lgff_init(hdev); | 251 | lgff_init(hdev); |
256 | if (quirks & LG_FF2) | 252 | if (quirks & LG_FF2) |
@@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = { | |||
279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), | 275 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), |
280 | .driver_data = LG_DUPLICATE_USAGES }, | 276 | .driver_data = LG_DUPLICATE_USAGES }, |
281 | 277 | ||
282 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD), | ||
283 | .driver_data = LG_RESET_LEDS }, | ||
284 | |||
285 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), | 278 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), |
286 | .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, | 279 | .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, |
287 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), | 280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), |
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c new file mode 100644 index 000000000000..db44fbd7bdf6 --- /dev/null +++ b/drivers/hid/hid-ntrig.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * HID driver for some ntrig "special" devices | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
8 | * Copyright (c) 2007 Paul Walmsley | ||
9 | * Copyright (c) 2008 Jiri Slaby | ||
10 | * Copyright (c) 2008 Rafi Rubin | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the Free | ||
17 | * Software Foundation; either version 2 of the License, or (at your option) | ||
18 | * any later version. | ||
19 | */ | ||
20 | |||
21 | #include <linux/device.h> | ||
22 | #include <linux/hid.h> | ||
23 | #include <linux/module.h> | ||
24 | |||
25 | #include "hid-ids.h" | ||
26 | |||
27 | #define NTRIG_DUPLICATE_USAGES 0x001 | ||
28 | |||
29 | #define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
30 | EV_KEY, (c)) | ||
31 | |||
32 | static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
33 | struct hid_field *field, struct hid_usage *usage, | ||
34 | unsigned long **bit, int *max) | ||
35 | { | ||
36 | if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER && | ||
37 | (usage->hid & 0xff) == 0x47) { | ||
38 | nt_map_key_clear(BTN_TOOL_DOUBLETAP); | ||
39 | return 1; | ||
40 | } | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
45 | struct hid_field *field, struct hid_usage *usage, | ||
46 | unsigned long **bit, int *max) | ||
47 | { | ||
48 | if (usage->type == EV_KEY || usage->type == EV_REL | ||
49 | || usage->type == EV_ABS) | ||
50 | clear_bit(usage->code, *bit); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | static const struct hid_device_id ntrig_devices[] = { | ||
55 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN), | ||
56 | .driver_data = NTRIG_DUPLICATE_USAGES }, | ||
57 | { } | ||
58 | }; | ||
59 | MODULE_DEVICE_TABLE(hid, ntrig_devices); | ||
60 | |||
61 | static struct hid_driver ntrig_driver = { | ||
62 | .name = "ntrig", | ||
63 | .id_table = ntrig_devices, | ||
64 | .input_mapping = ntrig_input_mapping, | ||
65 | .input_mapped = ntrig_input_mapped, | ||
66 | }; | ||
67 | |||
68 | static int ntrig_init(void) | ||
69 | { | ||
70 | return hid_register_driver(&ntrig_driver); | ||
71 | } | ||
72 | |||
73 | static void ntrig_exit(void) | ||
74 | { | ||
75 | hid_unregister_driver(&ntrig_driver); | ||
76 | } | ||
77 | |||
78 | module_init(ntrig_init); | ||
79 | module_exit(ntrig_exit); | ||
80 | MODULE_LICENSE("GPL"); | ||
81 | |||
82 | HID_COMPAT_LOAD_DRIVER(ntrig); | ||
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 86e563b8d644..dd5a3979a4de 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | ret = sony_set_operational(hdev); | 104 | ret = sony_set_operational(hdev); |
105 | if (ret) | 105 | if (ret < 0) |
106 | goto err_stop; | 106 | goto err_stop; |
107 | 107 | ||
108 | return 0; | 108 | return 0; |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c new file mode 100644 index 000000000000..cca64a0564a9 --- /dev/null +++ b/drivers/hid/hid-topseed.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * HID driver for TopSeed Cyberlink remote | ||
3 | * | ||
4 | * Copyright (c) 2008 Lev Babiev | ||
5 | * based on hid-cherry driver | ||
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/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | |||
19 | #include "hid-ids.h" | ||
20 | |||
21 | #define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
22 | EV_KEY, (c)) | ||
23 | static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
24 | struct hid_field *field, struct hid_usage *usage, | ||
25 | unsigned long **bit, int *max) | ||
26 | { | ||
27 | if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000) | ||
28 | return 0; | ||
29 | |||
30 | switch (usage->hid & HID_USAGE) { | ||
31 | case 0x00d: ts_map_key_clear(KEY_HOME); break; | ||
32 | case 0x024: ts_map_key_clear(KEY_MENU); break; | ||
33 | case 0x025: ts_map_key_clear(KEY_TV); break; | ||
34 | case 0x048: ts_map_key_clear(KEY_RED); break; | ||
35 | case 0x047: ts_map_key_clear(KEY_GREEN); break; | ||
36 | case 0x049: ts_map_key_clear(KEY_YELLOW); break; | ||
37 | case 0x04a: ts_map_key_clear(KEY_BLUE); break; | ||
38 | case 0x04b: ts_map_key_clear(KEY_ANGLE); break; | ||
39 | case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break; | ||
40 | case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break; | ||
41 | case 0x031: ts_map_key_clear(KEY_AUDIO); break; | ||
42 | case 0x032: ts_map_key_clear(KEY_TEXT); break; | ||
43 | case 0x033: ts_map_key_clear(KEY_CHANNEL); break; | ||
44 | default: | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | static const struct hid_device_id ts_devices[] = { | ||
52 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | ||
53 | { } | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(hid, ts_devices); | ||
56 | |||
57 | static struct hid_driver ts_driver = { | ||
58 | .name = "topseed", | ||
59 | .id_table = ts_devices, | ||
60 | .input_mapping = ts_input_mapping, | ||
61 | }; | ||
62 | |||
63 | static int ts_init(void) | ||
64 | { | ||
65 | return hid_register_driver(&ts_driver); | ||
66 | } | ||
67 | |||
68 | static void ts_exit(void) | ||
69 | { | ||
70 | hid_unregister_driver(&ts_driver); | ||
71 | } | ||
72 | |||
73 | module_init(ts_init); | ||
74 | module_exit(ts_exit); | ||
75 | MODULE_LICENSE("GPL"); | ||
76 | |||
77 | HID_COMPAT_LOAD_DRIVER(topseed); | ||
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 7685ae6808c4..732449628971 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
208 | 208 | ||
209 | list_del(&list->node); | 209 | list_del(&list->node); |
210 | dev = hidraw_table[minor]; | 210 | dev = hidraw_table[minor]; |
211 | if (!dev->open--) { | 211 | if (!--dev->open) { |
212 | if (list->hidraw->exist) | 212 | if (list->hidraw->exist) |
213 | dev->hid->ll_driver->close(dev->hid); | 213 | dev->hid->ll_driver->close(dev->hid); |
214 | else | 214 | else |
@@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
265 | break; | 265 | break; |
266 | } | 266 | } |
267 | default: | 267 | default: |
268 | { | ||
269 | struct hid_device *hid = dev->hid; | ||
270 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | ||
271 | return -EINVAL; | ||
272 | |||
273 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { | ||
274 | int len; | ||
275 | if (!hid->name) | ||
276 | return 0; | ||
277 | len = strlen(hid->name) + 1; | ||
278 | if (len > _IOC_SIZE(cmd)) | ||
279 | len = _IOC_SIZE(cmd); | ||
280 | return copy_to_user(user_arg, hid->name, len) ? | ||
281 | -EFAULT : len; | ||
282 | } | ||
283 | |||
284 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { | ||
285 | int len; | ||
286 | if (!hid->phys) | ||
287 | return 0; | ||
288 | len = strlen(hid->phys) + 1; | ||
289 | if (len > _IOC_SIZE(cmd)) | ||
290 | len = _IOC_SIZE(cmd); | ||
291 | return copy_to_user(user_arg, hid->phys, len) ? | ||
292 | -EFAULT : len; | ||
293 | } | ||
294 | } | ||
295 | |||
268 | ret = -ENOTTY; | 296 | ret = -ENOTTY; |
269 | } | 297 | } |
270 | unlock_kernel(); | 298 | unlock_kernel(); |
@@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid) | |||
329 | goto out; | 357 | goto out; |
330 | } | 358 | } |
331 | 359 | ||
332 | dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor), | 360 | dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor), |
333 | NULL, "%s%d", "hidraw", minor); | 361 | NULL, "%s%d", "hidraw", minor); |
334 | 362 | ||
335 | if (IS_ERR(dev->dev)) { | 363 | if (IS_ERR(dev->dev)) { |
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 5d9aa95fc3ef..4edb3bef94a6 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig | |||
@@ -45,7 +45,7 @@ config USB_HIDDEV | |||
45 | If unsure, say Y. | 45 | If unsure, say Y. |
46 | 46 | ||
47 | menu "USB HID Boot Protocol drivers" | 47 | menu "USB HID Boot Protocol drivers" |
48 | depends on USB!=n && USB_HID!=y | 48 | depends on USB!=n && USB_HID!=y && EMBEDDED |
49 | 49 | ||
50 | config USB_KBD | 50 | config USB_KBD |
51 | tristate "USB HIDBP Keyboard (simple Boot) support" | 51 | tristate "USB HIDBP Keyboard (simple Boot) support" |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 606369ea24ca..03cb494af1c5 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 1999 Andreas Gal | 4 | * Copyright (c) 1999 Andreas Gal |
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
7 | * Copyright (c) 2006-2007 Jiri Kosina | 7 | * Copyright (c) 2006-2008 Jiri Kosina |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, | |||
641 | unsigned int size; | 641 | unsigned int size; |
642 | 642 | ||
643 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { | 643 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { |
644 | size = ((report->size - 1) >> 3) + 1; | 644 | size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered; |
645 | if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) | ||
646 | size++; | ||
647 | if (*max < size) | 645 | if (*max < size) |
648 | *max = size; | 646 | *max = size; |
649 | } | 647 | } |
@@ -653,13 +651,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | |||
653 | { | 651 | { |
654 | struct usbhid_device *usbhid = hid->driver_data; | 652 | struct usbhid_device *usbhid = hid->driver_data; |
655 | 653 | ||
656 | if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) | 654 | usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, |
657 | return -1; | 655 | &usbhid->inbuf_dma); |
658 | if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) | 656 | usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, |
659 | return -1; | 657 | &usbhid->outbuf_dma); |
660 | if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) | 658 | usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL, |
661 | return -1; | 659 | &usbhid->cr_dma); |
662 | if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) | 660 | usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, |
661 | &usbhid->ctrlbuf_dma); | ||
662 | if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr || | ||
663 | !usbhid->ctrlbuf) | ||
663 | return -1; | 664 | return -1; |
664 | 665 | ||
665 | return 0; | 666 | return 0; |
@@ -807,7 +808,7 @@ static int usbhid_start(struct hid_device *hid) | |||
807 | int interval; | 808 | int interval; |
808 | 809 | ||
809 | endpoint = &interface->endpoint[n].desc; | 810 | endpoint = &interface->endpoint[n].desc; |
810 | if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ | 811 | if (!usb_endpoint_xfer_int(endpoint)) |
811 | continue; | 812 | continue; |
812 | 813 | ||
813 | interval = endpoint->bInterval; | 814 | interval = endpoint->bInterval; |
@@ -876,6 +877,15 @@ static int usbhid_start(struct hid_device *hid) | |||
876 | 877 | ||
877 | set_bit(HID_STARTED, &usbhid->iofl); | 878 | set_bit(HID_STARTED, &usbhid->iofl); |
878 | 879 | ||
880 | /* Some keyboards don't work until their LEDs have been set. | ||
881 | * Since BIOSes do set the LEDs, it must be safe for any device | ||
882 | * that supports the keyboard boot protocol. | ||
883 | */ | ||
884 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && | ||
885 | interface->desc.bInterfaceProtocol == | ||
886 | USB_INTERFACE_PROTOCOL_KEYBOARD) | ||
887 | usbhid_set_leds(hid); | ||
888 | |||
879 | return 0; | 889 | return 0; |
880 | 890 | ||
881 | fail: | 891 | fail: |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 47ebe045f9b5..4391717d2519 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -54,6 +54,7 @@ static const struct hid_blacklist { | |||
54 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 54 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
55 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 55 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
56 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 56 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
57 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | ||
57 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 58 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
58 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 59 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
59 | 60 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 83e851a5ed30..6a98f9f572b0 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -49,6 +49,7 @@ | |||
49 | struct hiddev { | 49 | struct hiddev { |
50 | int exist; | 50 | int exist; |
51 | int open; | 51 | int open; |
52 | struct mutex existancelock; | ||
52 | wait_queue_head_t wait; | 53 | wait_queue_head_t wait; |
53 | struct hid_device *hid; | 54 | struct hid_device *hid; |
54 | struct list_head list; | 55 | struct list_head list; |
@@ -63,6 +64,7 @@ struct hiddev_list { | |||
63 | struct fasync_struct *fasync; | 64 | struct fasync_struct *fasync; |
64 | struct hiddev *hiddev; | 65 | struct hiddev *hiddev; |
65 | struct list_head node; | 66 | struct list_head node; |
67 | struct mutex thread_lock; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | 70 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; |
@@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
264 | static int hiddev_open(struct inode *inode, struct file *file) | 266 | static int hiddev_open(struct inode *inode, struct file *file) |
265 | { | 267 | { |
266 | struct hiddev_list *list; | 268 | struct hiddev_list *list; |
267 | unsigned long flags; | 269 | int res; |
268 | 270 | ||
269 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | 271 | int i = iminor(inode) - HIDDEV_MINOR_BASE; |
270 | 272 | ||
271 | if (i >= HIDDEV_MINORS || !hiddev_table[i]) | 273 | if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i]) |
272 | return -ENODEV; | 274 | return -ENODEV; |
273 | 275 | ||
274 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | 276 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) |
275 | return -ENOMEM; | 277 | return -ENOMEM; |
278 | mutex_init(&list->thread_lock); | ||
276 | 279 | ||
277 | list->hiddev = hiddev_table[i]; | 280 | list->hiddev = hiddev_table[i]; |
278 | 281 | ||
279 | spin_lock_irqsave(&list->hiddev->list_lock, flags); | ||
280 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
281 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); | ||
282 | 282 | ||
283 | file->private_data = list; | 283 | file->private_data = list; |
284 | 284 | ||
285 | if (!list->hiddev->open++) | 285 | /* |
286 | if (list->hiddev->exist) | 286 | * no need for locking because the USB major number |
287 | usbhid_open(hiddev_table[i]->hid); | 287 | * is shared which usbcore guards against disconnect |
288 | */ | ||
289 | if (list->hiddev->exist) { | ||
290 | if (!list->hiddev->open++) { | ||
291 | res = usbhid_open(hiddev_table[i]->hid); | ||
292 | if (res < 0) { | ||
293 | res = -EIO; | ||
294 | goto bail; | ||
295 | } | ||
296 | } | ||
297 | } else { | ||
298 | res = -ENODEV; | ||
299 | goto bail; | ||
300 | } | ||
301 | |||
302 | spin_lock_irq(&list->hiddev->list_lock); | ||
303 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
304 | spin_unlock_irq(&list->hiddev->list_lock); | ||
288 | 305 | ||
289 | return 0; | 306 | return 0; |
307 | bail: | ||
308 | file->private_data = NULL; | ||
309 | kfree(list->hiddev); | ||
310 | return res; | ||
290 | } | 311 | } |
291 | 312 | ||
292 | /* | 313 | /* |
@@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
305 | DECLARE_WAITQUEUE(wait, current); | 326 | DECLARE_WAITQUEUE(wait, current); |
306 | struct hiddev_list *list = file->private_data; | 327 | struct hiddev_list *list = file->private_data; |
307 | int event_size; | 328 | int event_size; |
308 | int retval = 0; | 329 | int retval; |
309 | 330 | ||
310 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? | 331 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? |
311 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); | 332 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); |
@@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
313 | if (count < event_size) | 334 | if (count < event_size) |
314 | return 0; | 335 | return 0; |
315 | 336 | ||
337 | /* lock against other threads */ | ||
338 | retval = mutex_lock_interruptible(&list->thread_lock); | ||
339 | if (retval) | ||
340 | return -ERESTARTSYS; | ||
341 | |||
316 | while (retval == 0) { | 342 | while (retval == 0) { |
317 | if (list->head == list->tail) { | 343 | if (list->head == list->tail) { |
318 | add_wait_queue(&list->hiddev->wait, &wait); | 344 | prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE); |
319 | set_current_state(TASK_INTERRUPTIBLE); | ||
320 | 345 | ||
321 | while (list->head == list->tail) { | 346 | while (list->head == list->tail) { |
322 | if (file->f_flags & O_NONBLOCK) { | 347 | if (file->f_flags & O_NONBLOCK) { |
@@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
332 | break; | 357 | break; |
333 | } | 358 | } |
334 | 359 | ||
360 | /* let O_NONBLOCK tasks run */ | ||
361 | mutex_unlock(&list->thread_lock); | ||
335 | schedule(); | 362 | schedule(); |
363 | if (mutex_lock_interruptible(&list->thread_lock)) | ||
364 | return -EINTR; | ||
336 | set_current_state(TASK_INTERRUPTIBLE); | 365 | set_current_state(TASK_INTERRUPTIBLE); |
337 | } | 366 | } |
367 | finish_wait(&list->hiddev->wait, &wait); | ||
338 | 368 | ||
339 | set_current_state(TASK_RUNNING); | ||
340 | remove_wait_queue(&list->hiddev->wait, &wait); | ||
341 | } | 369 | } |
342 | 370 | ||
343 | if (retval) | 371 | if (retval) { |
372 | mutex_unlock(&list->thread_lock); | ||
344 | return retval; | 373 | return retval; |
374 | } | ||
345 | 375 | ||
346 | 376 | ||
347 | while (list->head != list->tail && | 377 | while (list->head != list->tail && |
348 | retval + event_size <= count) { | 378 | retval + event_size <= count) { |
349 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | 379 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { |
350 | if (list->buffer[list->tail].field_index != | 380 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) { |
351 | HID_FIELD_INDEX_NONE) { | ||
352 | struct hiddev_event event; | 381 | struct hiddev_event event; |
382 | |||
353 | event.hid = list->buffer[list->tail].usage_code; | 383 | event.hid = list->buffer[list->tail].usage_code; |
354 | event.value = list->buffer[list->tail].value; | 384 | event.value = list->buffer[list->tail].value; |
355 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) | 385 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) { |
386 | mutex_unlock(&list->thread_lock); | ||
356 | return -EFAULT; | 387 | return -EFAULT; |
388 | } | ||
357 | retval += sizeof(struct hiddev_event); | 389 | retval += sizeof(struct hiddev_event); |
358 | } | 390 | } |
359 | } else { | 391 | } else { |
360 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || | 392 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || |
361 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | 393 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { |
362 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) | 394 | |
395 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) { | ||
396 | mutex_unlock(&list->thread_lock); | ||
363 | return -EFAULT; | 397 | return -EFAULT; |
398 | } | ||
364 | retval += sizeof(struct hiddev_usage_ref); | 399 | retval += sizeof(struct hiddev_usage_ref); |
365 | } | 400 | } |
366 | } | 401 | } |
@@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
368 | } | 403 | } |
369 | 404 | ||
370 | } | 405 | } |
406 | mutex_unlock(&list->thread_lock); | ||
371 | 407 | ||
372 | return retval; | 408 | return retval; |
373 | } | 409 | } |
@@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
555 | struct hid_field *field; | 591 | struct hid_field *field; |
556 | struct usbhid_device *usbhid = hid->driver_data; | 592 | struct usbhid_device *usbhid = hid->driver_data; |
557 | void __user *user_arg = (void __user *)arg; | 593 | void __user *user_arg = (void __user *)arg; |
558 | int i; | 594 | int i, r; |
559 | 595 | ||
560 | /* Called without BKL by compat methods so no BKL taken */ | 596 | /* Called without BKL by compat methods so no BKL taken */ |
561 | 597 | ||
@@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
619 | } | 655 | } |
620 | 656 | ||
621 | case HIDIOCGSTRING: | 657 | case HIDIOCGSTRING: |
622 | return hiddev_ioctl_string(hiddev, cmd, user_arg); | 658 | mutex_lock(&hiddev->existancelock); |
659 | if (!hiddev->exist) | ||
660 | r = hiddev_ioctl_string(hiddev, cmd, user_arg); | ||
661 | else | ||
662 | r = -ENODEV; | ||
663 | mutex_unlock(&hiddev->existancelock); | ||
664 | return r; | ||
623 | 665 | ||
624 | case HIDIOCINITREPORT: | 666 | case HIDIOCINITREPORT: |
667 | mutex_lock(&hiddev->existancelock); | ||
668 | if (!hiddev->exist) { | ||
669 | mutex_unlock(&hiddev->existancelock); | ||
670 | return -ENODEV; | ||
671 | } | ||
625 | usbhid_init_reports(hid); | 672 | usbhid_init_reports(hid); |
673 | mutex_unlock(&hiddev->existancelock); | ||
626 | 674 | ||
627 | return 0; | 675 | return 0; |
628 | 676 | ||
@@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
636 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 684 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) |
637 | return -EINVAL; | 685 | return -EINVAL; |
638 | 686 | ||
639 | usbhid_submit_report(hid, report, USB_DIR_IN); | 687 | mutex_lock(&hiddev->existancelock); |
640 | usbhid_wait_io(hid); | 688 | if (hiddev->exist) { |
689 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
690 | usbhid_wait_io(hid); | ||
691 | } | ||
692 | mutex_unlock(&hiddev->existancelock); | ||
641 | 693 | ||
642 | return 0; | 694 | return 0; |
643 | 695 | ||
@@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
651 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 703 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) |
652 | return -EINVAL; | 704 | return -EINVAL; |
653 | 705 | ||
654 | usbhid_submit_report(hid, report, USB_DIR_OUT); | 706 | mutex_lock(&hiddev->existancelock); |
655 | usbhid_wait_io(hid); | 707 | if (hiddev->exist) { |
708 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
709 | usbhid_wait_io(hid); | ||
710 | } | ||
711 | mutex_unlock(&hiddev->existancelock); | ||
656 | 712 | ||
657 | return 0; | 713 | return 0; |
658 | 714 | ||
@@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
710 | case HIDIOCGUSAGES: | 766 | case HIDIOCGUSAGES: |
711 | case HIDIOCSUSAGES: | 767 | case HIDIOCSUSAGES: |
712 | case HIDIOCGCOLLECTIONINDEX: | 768 | case HIDIOCGCOLLECTIONINDEX: |
713 | return hiddev_ioctl_usage(hiddev, cmd, user_arg); | 769 | mutex_lock(&hiddev->existancelock); |
770 | if (hiddev->exist) | ||
771 | r = hiddev_ioctl_usage(hiddev, cmd, user_arg); | ||
772 | else | ||
773 | r = -ENODEV; | ||
774 | mutex_unlock(&hiddev->existancelock); | ||
775 | return r; | ||
714 | 776 | ||
715 | case HIDIOCGCOLLECTIONINFO: | 777 | case HIDIOCGCOLLECTIONINFO: |
716 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | 778 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) |
@@ -808,23 +870,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
808 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) | 870 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) |
809 | return -1; | 871 | return -1; |
810 | 872 | ||
811 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | ||
812 | if (retval) { | ||
813 | err_hid("Not able to get a minor for this device."); | ||
814 | kfree(hiddev); | ||
815 | return -1; | ||
816 | } | ||
817 | |||
818 | init_waitqueue_head(&hiddev->wait); | 873 | init_waitqueue_head(&hiddev->wait); |
819 | INIT_LIST_HEAD(&hiddev->list); | 874 | INIT_LIST_HEAD(&hiddev->list); |
820 | spin_lock_init(&hiddev->list_lock); | 875 | spin_lock_init(&hiddev->list_lock); |
876 | mutex_init(&hiddev->existancelock); | ||
821 | hiddev->hid = hid; | 877 | hiddev->hid = hid; |
822 | hiddev->exist = 1; | 878 | hiddev->exist = 1; |
823 | 879 | ||
824 | hid->minor = usbhid->intf->minor; | 880 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
825 | hid->hiddev = hiddev; | 881 | if (retval) { |
826 | 882 | err_hid("Not able to get a minor for this device."); | |
827 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | 883 | kfree(hiddev); |
884 | return -1; | ||
885 | } else { | ||
886 | hid->minor = usbhid->intf->minor; | ||
887 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
888 | } | ||
828 | 889 | ||
829 | return 0; | 890 | return 0; |
830 | } | 891 | } |
@@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid) | |||
839 | struct hiddev *hiddev = hid->hiddev; | 900 | struct hiddev *hiddev = hid->hiddev; |
840 | struct usbhid_device *usbhid = hid->driver_data; | 901 | struct usbhid_device *usbhid = hid->driver_data; |
841 | 902 | ||
903 | mutex_lock(&hiddev->existancelock); | ||
842 | hiddev->exist = 0; | 904 | hiddev->exist = 0; |
905 | mutex_unlock(&hiddev->existancelock); | ||
843 | 906 | ||
844 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | 907 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; |
845 | usb_deregister_dev(usbhid->intf, &hiddev_class); | 908 | usb_deregister_dev(usbhid->intf, &hiddev_class); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 332abcdf9956..9eb30564be9c 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid); | |||
40 | void usbhid_init_reports(struct hid_device *hid); | 40 | void usbhid_init_reports(struct hid_device *hid); |
41 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); | 41 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); |
42 | 42 | ||
43 | /* iofl flags */ | ||
44 | #define HID_CTRL_RUNNING 1 | ||
45 | #define HID_OUT_RUNNING 2 | ||
46 | #define HID_IN_RUNNING 3 | ||
47 | #define HID_RESET_PENDING 4 | ||
48 | #define HID_SUSPENDED 5 | ||
49 | #define HID_CLEAR_HALT 6 | ||
50 | #define HID_DISCONNECTED 7 | ||
51 | #define HID_STARTED 8 | ||
52 | |||
43 | /* | 53 | /* |
44 | * USB-specific HID struct, to be pointed to | 54 | * USB-specific HID struct, to be pointed to |
45 | * from struct hid_device->driver_data | 55 | * from struct hid_device->driver_data |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 608038d64f81..be8ee2cac8bb 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -2,13 +2,16 @@ | |||
2 | * TI OMAP I2C master mode driver | 2 | * TI OMAP I2C master mode driver |
3 | * | 3 | * |
4 | * Copyright (C) 2003 MontaVista Software, Inc. | 4 | * Copyright (C) 2003 MontaVista Software, Inc. |
5 | * Copyright (C) 2004 Texas Instruments. | ||
6 | * | ||
7 | * Updated to work with multiple I2C interfaces on 24xx by | ||
8 | * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com> | ||
9 | * Copyright (C) 2005 Nokia Corporation | 5 | * Copyright (C) 2005 Nokia Corporation |
6 | * Copyright (C) 2004 - 2007 Texas Instruments. | ||
10 | * | 7 | * |
11 | * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com> | 8 | * Originally written by MontaVista Software, Inc. |
9 | * Additional contributions by: | ||
10 | * Tony Lindgren <tony@atomide.com> | ||
11 | * Imre Deak <imre.deak@nokia.com> | ||
12 | * Juha Yrjölä <juha.yrjola@solidboot.com> | ||
13 | * Syed Khasim <x0khasim@ti.com> | ||
14 | * Nishant Menon <nm@ti.com> | ||
12 | * | 15 | * |
13 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -33,8 +36,14 @@ | |||
33 | #include <linux/completion.h> | 36 | #include <linux/completion.h> |
34 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
35 | #include <linux/clk.h> | 38 | #include <linux/clk.h> |
39 | #include <linux/io.h> | ||
40 | |||
41 | /* I2C controller revisions */ | ||
42 | #define OMAP_I2C_REV_2 0x20 | ||
36 | 43 | ||
37 | #include <asm/io.h> | 44 | /* I2C controller revisions present on specific hardware */ |
45 | #define OMAP_I2C_REV_ON_2430 0x36 | ||
46 | #define OMAP_I2C_REV_ON_3430 0x3C | ||
38 | 47 | ||
39 | /* timeout waiting for the controller to respond */ | 48 | /* timeout waiting for the controller to respond */ |
40 | #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) | 49 | #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) |
@@ -43,6 +52,8 @@ | |||
43 | #define OMAP_I2C_IE_REG 0x04 | 52 | #define OMAP_I2C_IE_REG 0x04 |
44 | #define OMAP_I2C_STAT_REG 0x08 | 53 | #define OMAP_I2C_STAT_REG 0x08 |
45 | #define OMAP_I2C_IV_REG 0x0c | 54 | #define OMAP_I2C_IV_REG 0x0c |
55 | /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ | ||
56 | #define OMAP_I2C_WE_REG 0x0c | ||
46 | #define OMAP_I2C_SYSS_REG 0x10 | 57 | #define OMAP_I2C_SYSS_REG 0x10 |
47 | #define OMAP_I2C_BUF_REG 0x14 | 58 | #define OMAP_I2C_BUF_REG 0x14 |
48 | #define OMAP_I2C_CNT_REG 0x18 | 59 | #define OMAP_I2C_CNT_REG 0x18 |
@@ -55,8 +66,11 @@ | |||
55 | #define OMAP_I2C_SCLL_REG 0x34 | 66 | #define OMAP_I2C_SCLL_REG 0x34 |
56 | #define OMAP_I2C_SCLH_REG 0x38 | 67 | #define OMAP_I2C_SCLH_REG 0x38 |
57 | #define OMAP_I2C_SYSTEST_REG 0x3c | 68 | #define OMAP_I2C_SYSTEST_REG 0x3c |
69 | #define OMAP_I2C_BUFSTAT_REG 0x40 | ||
58 | 70 | ||
59 | /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ | 71 | /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ |
72 | #define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ | ||
73 | #define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */ | ||
60 | #define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */ | 74 | #define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */ |
61 | #define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */ | 75 | #define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */ |
62 | #define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */ | 76 | #define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */ |
@@ -64,7 +78,8 @@ | |||
64 | #define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */ | 78 | #define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */ |
65 | 79 | ||
66 | /* I2C Status Register (OMAP_I2C_STAT): */ | 80 | /* I2C Status Register (OMAP_I2C_STAT): */ |
67 | #define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */ | 81 | #define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */ |
82 | #define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */ | ||
68 | #define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */ | 83 | #define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */ |
69 | #define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */ | 84 | #define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */ |
70 | #define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ | 85 | #define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ |
@@ -76,13 +91,34 @@ | |||
76 | #define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */ | 91 | #define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */ |
77 | #define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */ | 92 | #define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */ |
78 | 93 | ||
94 | /* I2C WE wakeup enable register */ | ||
95 | #define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */ | ||
96 | #define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */ | ||
97 | #define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/ | ||
98 | #define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */ | ||
99 | #define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */ | ||
100 | #define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */ | ||
101 | #define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */ | ||
102 | #define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */ | ||
103 | #define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */ | ||
104 | #define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */ | ||
105 | |||
106 | #define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \ | ||
107 | OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \ | ||
108 | OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \ | ||
109 | OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \ | ||
110 | OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE) | ||
111 | |||
79 | /* I2C Buffer Configuration Register (OMAP_I2C_BUF): */ | 112 | /* I2C Buffer Configuration Register (OMAP_I2C_BUF): */ |
80 | #define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */ | 113 | #define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */ |
114 | #define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */ | ||
81 | #define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */ | 115 | #define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */ |
116 | #define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */ | ||
82 | 117 | ||
83 | /* I2C Configuration Register (OMAP_I2C_CON): */ | 118 | /* I2C Configuration Register (OMAP_I2C_CON): */ |
84 | #define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */ | 119 | #define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */ |
85 | #define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */ | 120 | #define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */ |
121 | #define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */ | ||
86 | #define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */ | 122 | #define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */ |
87 | #define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */ | 123 | #define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */ |
88 | #define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */ | 124 | #define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */ |
@@ -91,6 +127,10 @@ | |||
91 | #define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */ | 127 | #define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */ |
92 | #define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */ | 128 | #define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */ |
93 | 129 | ||
130 | /* I2C SCL time value when Master */ | ||
131 | #define OMAP_I2C_SCLL_HSSCLL 8 | ||
132 | #define OMAP_I2C_SCLH_HSSCLH 8 | ||
133 | |||
94 | /* I2C System Test Register (OMAP_I2C_SYSTEST): */ | 134 | /* I2C System Test Register (OMAP_I2C_SYSTEST): */ |
95 | #ifdef DEBUG | 135 | #ifdef DEBUG |
96 | #define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ | 136 | #define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ |
@@ -103,17 +143,19 @@ | |||
103 | #define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ | 143 | #define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ |
104 | #endif | 144 | #endif |
105 | 145 | ||
106 | /* I2C System Status register (OMAP_I2C_SYSS): */ | 146 | /* OCP_SYSSTATUS bit definitions */ |
107 | #define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */ | 147 | #define SYSS_RESETDONE_MASK (1 << 0) |
148 | |||
149 | /* OCP_SYSCONFIG bit definitions */ | ||
150 | #define SYSC_CLOCKACTIVITY_MASK (0x3 << 8) | ||
151 | #define SYSC_SIDLEMODE_MASK (0x3 << 3) | ||
152 | #define SYSC_ENAWAKEUP_MASK (1 << 2) | ||
153 | #define SYSC_SOFTRESET_MASK (1 << 1) | ||
154 | #define SYSC_AUTOIDLE_MASK (1 << 0) | ||
108 | 155 | ||
109 | /* I2C System Configuration Register (OMAP_I2C_SYSC): */ | 156 | #define SYSC_IDLEMODE_SMART 0x2 |
110 | #define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */ | 157 | #define SYSC_CLOCKACTIVITY_FCLK 0x2 |
111 | 158 | ||
112 | /* REVISIT: Use platform_data instead of module parameters */ | ||
113 | /* Fast Mode = 400 kHz, Standard = 100 kHz */ | ||
114 | static int clock = 100; /* Default: 100 kHz */ | ||
115 | module_param(clock, int, 0); | ||
116 | MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)"); | ||
117 | 159 | ||
118 | struct omap_i2c_dev { | 160 | struct omap_i2c_dev { |
119 | struct device *dev; | 161 | struct device *dev; |
@@ -123,11 +165,17 @@ struct omap_i2c_dev { | |||
123 | struct clk *fclk; /* Functional clock */ | 165 | struct clk *fclk; /* Functional clock */ |
124 | struct completion cmd_complete; | 166 | struct completion cmd_complete; |
125 | struct resource *ioarea; | 167 | struct resource *ioarea; |
168 | u32 speed; /* Speed of bus in Khz */ | ||
126 | u16 cmd_err; | 169 | u16 cmd_err; |
127 | u8 *buf; | 170 | u8 *buf; |
128 | size_t buf_len; | 171 | size_t buf_len; |
129 | struct i2c_adapter adapter; | 172 | struct i2c_adapter adapter; |
130 | unsigned rev1:1; | 173 | u8 fifo_size; /* use as flag and value |
174 | * fifo_size==0 implies no fifo | ||
175 | * if set, should be trsh+1 | ||
176 | */ | ||
177 | u8 rev; | ||
178 | unsigned b_hw:1; /* bad h/w fixes */ | ||
131 | unsigned idle:1; | 179 | unsigned idle:1; |
132 | u16 iestate; /* Saved interrupt register */ | 180 | u16 iestate; /* Saved interrupt register */ |
133 | }; | 181 | }; |
@@ -143,9 +191,9 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) | |||
143 | return __raw_readw(i2c_dev->base + reg); | 191 | return __raw_readw(i2c_dev->base + reg); |
144 | } | 192 | } |
145 | 193 | ||
146 | static int omap_i2c_get_clocks(struct omap_i2c_dev *dev) | 194 | static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) |
147 | { | 195 | { |
148 | if (cpu_is_omap16xx() || cpu_is_omap24xx()) { | 196 | if (cpu_is_omap16xx() || cpu_class_is_omap2()) { |
149 | dev->iclk = clk_get(dev->dev, "i2c_ick"); | 197 | dev->iclk = clk_get(dev->dev, "i2c_ick"); |
150 | if (IS_ERR(dev->iclk)) { | 198 | if (IS_ERR(dev->iclk)) { |
151 | dev->iclk = NULL; | 199 | dev->iclk = NULL; |
@@ -178,25 +226,33 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev) | |||
178 | 226 | ||
179 | static void omap_i2c_unidle(struct omap_i2c_dev *dev) | 227 | static void omap_i2c_unidle(struct omap_i2c_dev *dev) |
180 | { | 228 | { |
229 | WARN_ON(!dev->idle); | ||
230 | |||
181 | if (dev->iclk != NULL) | 231 | if (dev->iclk != NULL) |
182 | clk_enable(dev->iclk); | 232 | clk_enable(dev->iclk); |
183 | clk_enable(dev->fclk); | 233 | clk_enable(dev->fclk); |
234 | dev->idle = 0; | ||
184 | if (dev->iestate) | 235 | if (dev->iestate) |
185 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); | 236 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); |
186 | dev->idle = 0; | ||
187 | } | 237 | } |
188 | 238 | ||
189 | static void omap_i2c_idle(struct omap_i2c_dev *dev) | 239 | static void omap_i2c_idle(struct omap_i2c_dev *dev) |
190 | { | 240 | { |
191 | u16 iv; | 241 | u16 iv; |
192 | 242 | ||
193 | dev->idle = 1; | 243 | WARN_ON(dev->idle); |
244 | |||
194 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | 245 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); |
195 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); | 246 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); |
196 | if (dev->rev1) | 247 | if (dev->rev < OMAP_I2C_REV_2) { |
197 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ | 248 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ |
198 | else | 249 | } else { |
199 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); | 250 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); |
251 | |||
252 | /* Flush posted write before the dev->idle store occurs */ | ||
253 | omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); | ||
254 | } | ||
255 | dev->idle = 1; | ||
200 | clk_disable(dev->fclk); | 256 | clk_disable(dev->fclk); |
201 | if (dev->iclk != NULL) | 257 | if (dev->iclk != NULL) |
202 | clk_disable(dev->iclk); | 258 | clk_disable(dev->iclk); |
@@ -204,18 +260,20 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) | |||
204 | 260 | ||
205 | static int omap_i2c_init(struct omap_i2c_dev *dev) | 261 | static int omap_i2c_init(struct omap_i2c_dev *dev) |
206 | { | 262 | { |
207 | u16 psc = 0; | 263 | u16 psc = 0, scll = 0, sclh = 0; |
264 | u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; | ||
208 | unsigned long fclk_rate = 12000000; | 265 | unsigned long fclk_rate = 12000000; |
209 | unsigned long timeout; | 266 | unsigned long timeout; |
267 | unsigned long internal_clk = 0; | ||
210 | 268 | ||
211 | if (!dev->rev1) { | 269 | if (dev->rev >= OMAP_I2C_REV_2) { |
212 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST); | 270 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); |
213 | /* For some reason we need to set the EN bit before the | 271 | /* For some reason we need to set the EN bit before the |
214 | * reset done bit gets set. */ | 272 | * reset done bit gets set. */ |
215 | timeout = jiffies + OMAP_I2C_TIMEOUT; | 273 | timeout = jiffies + OMAP_I2C_TIMEOUT; |
216 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 274 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); |
217 | while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & | 275 | while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & |
218 | OMAP_I2C_SYSS_RDONE)) { | 276 | SYSS_RESETDONE_MASK)) { |
219 | if (time_after(jiffies, timeout)) { | 277 | if (time_after(jiffies, timeout)) { |
220 | dev_warn(dev->dev, "timeout waiting " | 278 | dev_warn(dev->dev, "timeout waiting " |
221 | "for controller reset\n"); | 279 | "for controller reset\n"); |
@@ -223,6 +281,33 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
223 | } | 281 | } |
224 | msleep(1); | 282 | msleep(1); |
225 | } | 283 | } |
284 | |||
285 | /* SYSC register is cleared by the reset; rewrite it */ | ||
286 | if (dev->rev == OMAP_I2C_REV_ON_2430) { | ||
287 | |||
288 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, | ||
289 | SYSC_AUTOIDLE_MASK); | ||
290 | |||
291 | } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { | ||
292 | u32 v; | ||
293 | |||
294 | v = SYSC_AUTOIDLE_MASK; | ||
295 | v |= SYSC_ENAWAKEUP_MASK; | ||
296 | v |= (SYSC_IDLEMODE_SMART << | ||
297 | __ffs(SYSC_SIDLEMODE_MASK)); | ||
298 | v |= (SYSC_CLOCKACTIVITY_FCLK << | ||
299 | __ffs(SYSC_CLOCKACTIVITY_MASK)); | ||
300 | |||
301 | omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v); | ||
302 | /* | ||
303 | * Enabling all wakup sources to stop I2C freezing on | ||
304 | * WFI instruction. | ||
305 | * REVISIT: Some wkup sources might not be needed. | ||
306 | */ | ||
307 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, | ||
308 | OMAP_I2C_WE_ALL); | ||
309 | |||
310 | } | ||
226 | } | 311 | } |
227 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 312 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
228 | 313 | ||
@@ -249,27 +334,65 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
249 | psc = fclk_rate / 12000000; | 334 | psc = fclk_rate / 12000000; |
250 | } | 335 | } |
251 | 336 | ||
337 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | ||
338 | |||
339 | /* HSI2C controller internal clk rate should be 19.2 Mhz */ | ||
340 | internal_clk = 19200; | ||
341 | fclk_rate = clk_get_rate(dev->fclk) / 1000; | ||
342 | |||
343 | /* Compute prescaler divisor */ | ||
344 | psc = fclk_rate / internal_clk; | ||
345 | psc = psc - 1; | ||
346 | |||
347 | /* If configured for High Speed */ | ||
348 | if (dev->speed > 400) { | ||
349 | /* For first phase of HS mode */ | ||
350 | fsscll = internal_clk / (400 * 2) - 6; | ||
351 | fssclh = internal_clk / (400 * 2) - 6; | ||
352 | |||
353 | /* For second phase of HS mode */ | ||
354 | hsscll = fclk_rate / (dev->speed * 2) - 6; | ||
355 | hssclh = fclk_rate / (dev->speed * 2) - 6; | ||
356 | } else { | ||
357 | /* To handle F/S modes */ | ||
358 | fsscll = internal_clk / (dev->speed * 2) - 6; | ||
359 | fssclh = internal_clk / (dev->speed * 2) - 6; | ||
360 | } | ||
361 | scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; | ||
362 | sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; | ||
363 | } else { | ||
364 | /* Program desired operating rate */ | ||
365 | fclk_rate /= (psc + 1) * 1000; | ||
366 | if (psc > 2) | ||
367 | psc = 2; | ||
368 | scll = fclk_rate / (dev->speed * 2) - 7 + psc; | ||
369 | sclh = fclk_rate / (dev->speed * 2) - 7 + psc; | ||
370 | } | ||
371 | |||
252 | /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ | 372 | /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ |
253 | omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); | 373 | omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); |
254 | 374 | ||
255 | /* Program desired operating rate */ | 375 | /* SCL low and high time values */ |
256 | fclk_rate /= (psc + 1) * 1000; | 376 | omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); |
257 | if (psc > 2) | 377 | omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); |
258 | psc = 2; | ||
259 | 378 | ||
260 | omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, | 379 | if (dev->fifo_size) |
261 | fclk_rate / (clock * 2) - 7 + psc); | 380 | /* Note: setup required fifo size - 1 */ |
262 | omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, | 381 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, |
263 | fclk_rate / (clock * 2) - 7 + psc); | 382 | (dev->fifo_size - 1) << 8 | /* RTRSH */ |
383 | OMAP_I2C_BUF_RXFIF_CLR | | ||
384 | (dev->fifo_size - 1) | /* XTRSH */ | ||
385 | OMAP_I2C_BUF_TXFIF_CLR); | ||
264 | 386 | ||
265 | /* Take the I2C module out of reset: */ | 387 | /* Take the I2C module out of reset: */ |
266 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); | 388 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); |
267 | 389 | ||
268 | /* Enable interrupts */ | 390 | /* Enable interrupts */ |
269 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, | 391 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, |
270 | (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | | 392 | (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | |
271 | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | | 393 | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | |
272 | OMAP_I2C_IE_AL)); | 394 | OMAP_I2C_IE_AL) | ((dev->fifo_size) ? |
395 | (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0)); | ||
273 | return 0; | 396 | return 0; |
274 | } | 397 | } |
275 | 398 | ||
@@ -316,20 +439,59 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, | |||
316 | 439 | ||
317 | omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); | 440 | omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); |
318 | 441 | ||
442 | /* Clear the FIFO Buffers */ | ||
443 | w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG); | ||
444 | w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR; | ||
445 | omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w); | ||
446 | |||
319 | init_completion(&dev->cmd_complete); | 447 | init_completion(&dev->cmd_complete); |
320 | dev->cmd_err = 0; | 448 | dev->cmd_err = 0; |
321 | 449 | ||
322 | w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; | 450 | w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; |
451 | |||
452 | /* High speed configuration */ | ||
453 | if (dev->speed > 400) | ||
454 | w |= OMAP_I2C_CON_OPMODE_HS; | ||
455 | |||
323 | if (msg->flags & I2C_M_TEN) | 456 | if (msg->flags & I2C_M_TEN) |
324 | w |= OMAP_I2C_CON_XA; | 457 | w |= OMAP_I2C_CON_XA; |
325 | if (!(msg->flags & I2C_M_RD)) | 458 | if (!(msg->flags & I2C_M_RD)) |
326 | w |= OMAP_I2C_CON_TRX; | 459 | w |= OMAP_I2C_CON_TRX; |
327 | if (stop) | 460 | |
461 | if (!dev->b_hw && stop) | ||
328 | w |= OMAP_I2C_CON_STP; | 462 | w |= OMAP_I2C_CON_STP; |
463 | |||
329 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); | 464 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); |
330 | 465 | ||
331 | r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, | 466 | /* |
332 | OMAP_I2C_TIMEOUT); | 467 | * Don't write stt and stp together on some hardware. |
468 | */ | ||
469 | if (dev->b_hw && stop) { | ||
470 | unsigned long delay = jiffies + OMAP_I2C_TIMEOUT; | ||
471 | u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); | ||
472 | while (con & OMAP_I2C_CON_STT) { | ||
473 | con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); | ||
474 | |||
475 | /* Let the user know if i2c is in a bad state */ | ||
476 | if (time_after(jiffies, delay)) { | ||
477 | dev_err(dev->dev, "controller timed out " | ||
478 | "waiting for start condition to finish\n"); | ||
479 | return -ETIMEDOUT; | ||
480 | } | ||
481 | cpu_relax(); | ||
482 | } | ||
483 | |||
484 | w |= OMAP_I2C_CON_STP; | ||
485 | w &= ~OMAP_I2C_CON_STT; | ||
486 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); | ||
487 | } | ||
488 | |||
489 | /* | ||
490 | * REVISIT: We should abort the transfer on signals, but the bus goes | ||
491 | * into arbitration and we're currently unable to recover from it. | ||
492 | */ | ||
493 | r = wait_for_completion_timeout(&dev->cmd_complete, | ||
494 | OMAP_I2C_TIMEOUT); | ||
333 | dev->buf_len = 0; | 495 | dev->buf_len = 0; |
334 | if (r < 0) | 496 | if (r < 0) |
335 | return r; | 497 | return r; |
@@ -376,7 +538,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
376 | 538 | ||
377 | omap_i2c_unidle(dev); | 539 | omap_i2c_unidle(dev); |
378 | 540 | ||
379 | if ((r = omap_i2c_wait_for_bb(dev)) < 0) | 541 | r = omap_i2c_wait_for_bb(dev); |
542 | if (r < 0) | ||
380 | goto out; | 543 | goto out; |
381 | 544 | ||
382 | for (i = 0; i < num; i++) { | 545 | for (i = 0; i < num; i++) { |
@@ -411,6 +574,9 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat) | |||
411 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); | 574 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); |
412 | } | 575 | } |
413 | 576 | ||
577 | /* rev1 devices are apparently only on some 15xx */ | ||
578 | #ifdef CONFIG_ARCH_OMAP15XX | ||
579 | |||
414 | static irqreturn_t | 580 | static irqreturn_t |
415 | omap_i2c_rev1_isr(int this_irq, void *dev_id) | 581 | omap_i2c_rev1_isr(int this_irq, void *dev_id) |
416 | { | 582 | { |
@@ -465,6 +631,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id) | |||
465 | 631 | ||
466 | return IRQ_HANDLED; | 632 | return IRQ_HANDLED; |
467 | } | 633 | } |
634 | #else | ||
635 | #define omap_i2c_rev1_isr NULL | ||
636 | #endif | ||
468 | 637 | ||
469 | static irqreturn_t | 638 | static irqreturn_t |
470 | omap_i2c_isr(int this_irq, void *dev_id) | 639 | omap_i2c_isr(int this_irq, void *dev_id) |
@@ -472,7 +641,7 @@ omap_i2c_isr(int this_irq, void *dev_id) | |||
472 | struct omap_i2c_dev *dev = dev_id; | 641 | struct omap_i2c_dev *dev = dev_id; |
473 | u16 bits; | 642 | u16 bits; |
474 | u16 stat, w; | 643 | u16 stat, w; |
475 | int count = 0; | 644 | int err, count = 0; |
476 | 645 | ||
477 | if (dev->idle) | 646 | if (dev->idle) |
478 | return IRQ_NONE; | 647 | return IRQ_NONE; |
@@ -487,39 +656,96 @@ omap_i2c_isr(int this_irq, void *dev_id) | |||
487 | 656 | ||
488 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); | 657 | omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); |
489 | 658 | ||
490 | if (stat & OMAP_I2C_STAT_ARDY) { | 659 | err = 0; |
491 | omap_i2c_complete_cmd(dev, 0); | 660 | if (stat & OMAP_I2C_STAT_NACK) { |
492 | continue; | 661 | err |= OMAP_I2C_STAT_NACK; |
662 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, | ||
663 | OMAP_I2C_CON_STP); | ||
493 | } | 664 | } |
494 | if (stat & OMAP_I2C_STAT_RRDY) { | 665 | if (stat & OMAP_I2C_STAT_AL) { |
495 | w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); | 666 | dev_err(dev->dev, "Arbitration lost\n"); |
496 | if (dev->buf_len) { | 667 | err |= OMAP_I2C_STAT_AL; |
497 | *dev->buf++ = w; | 668 | } |
498 | dev->buf_len--; | 669 | if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | |
670 | OMAP_I2C_STAT_AL)) | ||
671 | omap_i2c_complete_cmd(dev, err); | ||
672 | if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { | ||
673 | u8 num_bytes = 1; | ||
674 | if (dev->fifo_size) { | ||
675 | if (stat & OMAP_I2C_STAT_RRDY) | ||
676 | num_bytes = dev->fifo_size; | ||
677 | else | ||
678 | num_bytes = omap_i2c_read_reg(dev, | ||
679 | OMAP_I2C_BUFSTAT_REG); | ||
680 | } | ||
681 | while (num_bytes) { | ||
682 | num_bytes--; | ||
683 | w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); | ||
499 | if (dev->buf_len) { | 684 | if (dev->buf_len) { |
500 | *dev->buf++ = w >> 8; | 685 | *dev->buf++ = w; |
501 | dev->buf_len--; | 686 | dev->buf_len--; |
687 | /* Data reg from 2430 is 8 bit wide */ | ||
688 | if (!cpu_is_omap2430() && | ||
689 | !cpu_is_omap34xx()) { | ||
690 | if (dev->buf_len) { | ||
691 | *dev->buf++ = w >> 8; | ||
692 | dev->buf_len--; | ||
693 | } | ||
694 | } | ||
695 | } else { | ||
696 | if (stat & OMAP_I2C_STAT_RRDY) | ||
697 | dev_err(dev->dev, | ||
698 | "RRDY IRQ while no data" | ||
699 | " requested\n"); | ||
700 | if (stat & OMAP_I2C_STAT_RDR) | ||
701 | dev_err(dev->dev, | ||
702 | "RDR IRQ while no data" | ||
703 | " requested\n"); | ||
704 | break; | ||
502 | } | 705 | } |
503 | } else | 706 | } |
504 | dev_err(dev->dev, "RRDY IRQ while no data " | 707 | omap_i2c_ack_stat(dev, |
505 | "requested\n"); | 708 | stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)); |
506 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY); | ||
507 | continue; | 709 | continue; |
508 | } | 710 | } |
509 | if (stat & OMAP_I2C_STAT_XRDY) { | 711 | if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) { |
510 | w = 0; | 712 | u8 num_bytes = 1; |
511 | if (dev->buf_len) { | 713 | if (dev->fifo_size) { |
512 | w = *dev->buf++; | 714 | if (stat & OMAP_I2C_STAT_XRDY) |
513 | dev->buf_len--; | 715 | num_bytes = dev->fifo_size; |
716 | else | ||
717 | num_bytes = omap_i2c_read_reg(dev, | ||
718 | OMAP_I2C_BUFSTAT_REG); | ||
719 | } | ||
720 | while (num_bytes) { | ||
721 | num_bytes--; | ||
722 | w = 0; | ||
514 | if (dev->buf_len) { | 723 | if (dev->buf_len) { |
515 | w |= *dev->buf++ << 8; | 724 | w = *dev->buf++; |
516 | dev->buf_len--; | 725 | dev->buf_len--; |
726 | /* Data reg from 2430 is 8 bit wide */ | ||
727 | if (!cpu_is_omap2430() && | ||
728 | !cpu_is_omap34xx()) { | ||
729 | if (dev->buf_len) { | ||
730 | w |= *dev->buf++ << 8; | ||
731 | dev->buf_len--; | ||
732 | } | ||
733 | } | ||
734 | } else { | ||
735 | if (stat & OMAP_I2C_STAT_XRDY) | ||
736 | dev_err(dev->dev, | ||
737 | "XRDY IRQ while no " | ||
738 | "data to send\n"); | ||
739 | if (stat & OMAP_I2C_STAT_XDR) | ||
740 | dev_err(dev->dev, | ||
741 | "XDR IRQ while no " | ||
742 | "data to send\n"); | ||
743 | break; | ||
517 | } | 744 | } |
518 | } else | 745 | omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); |
519 | dev_err(dev->dev, "XRDY IRQ while no " | 746 | } |
520 | "data to send\n"); | 747 | omap_i2c_ack_stat(dev, |
521 | omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); | 748 | stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); |
522 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY); | ||
523 | continue; | 749 | continue; |
524 | } | 750 | } |
525 | if (stat & OMAP_I2C_STAT_ROVR) { | 751 | if (stat & OMAP_I2C_STAT_ROVR) { |
@@ -527,18 +753,9 @@ omap_i2c_isr(int this_irq, void *dev_id) | |||
527 | dev->cmd_err |= OMAP_I2C_STAT_ROVR; | 753 | dev->cmd_err |= OMAP_I2C_STAT_ROVR; |
528 | } | 754 | } |
529 | if (stat & OMAP_I2C_STAT_XUDF) { | 755 | if (stat & OMAP_I2C_STAT_XUDF) { |
530 | dev_err(dev->dev, "Transmit overflow\n"); | 756 | dev_err(dev->dev, "Transmit underflow\n"); |
531 | dev->cmd_err |= OMAP_I2C_STAT_XUDF; | 757 | dev->cmd_err |= OMAP_I2C_STAT_XUDF; |
532 | } | 758 | } |
533 | if (stat & OMAP_I2C_STAT_NACK) { | ||
534 | omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK); | ||
535 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, | ||
536 | OMAP_I2C_CON_STP); | ||
537 | } | ||
538 | if (stat & OMAP_I2C_STAT_AL) { | ||
539 | dev_err(dev->dev, "Arbitration lost\n"); | ||
540 | omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL); | ||
541 | } | ||
542 | } | 759 | } |
543 | 760 | ||
544 | return count ? IRQ_HANDLED : IRQ_NONE; | 761 | return count ? IRQ_HANDLED : IRQ_NONE; |
@@ -549,13 +766,15 @@ static const struct i2c_algorithm omap_i2c_algo = { | |||
549 | .functionality = omap_i2c_func, | 766 | .functionality = omap_i2c_func, |
550 | }; | 767 | }; |
551 | 768 | ||
552 | static int | 769 | static int __init |
553 | omap_i2c_probe(struct platform_device *pdev) | 770 | omap_i2c_probe(struct platform_device *pdev) |
554 | { | 771 | { |
555 | struct omap_i2c_dev *dev; | 772 | struct omap_i2c_dev *dev; |
556 | struct i2c_adapter *adap; | 773 | struct i2c_adapter *adap; |
557 | struct resource *mem, *irq, *ioarea; | 774 | struct resource *mem, *irq, *ioarea; |
775 | irq_handler_t isr; | ||
558 | int r; | 776 | int r; |
777 | u32 speed = 0; | ||
559 | 778 | ||
560 | /* NOTE: driver uses the static register mapping */ | 779 | /* NOTE: driver uses the static register mapping */ |
561 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 780 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -576,17 +795,19 @@ omap_i2c_probe(struct platform_device *pdev) | |||
576 | return -EBUSY; | 795 | return -EBUSY; |
577 | } | 796 | } |
578 | 797 | ||
579 | if (clock > 200) | ||
580 | clock = 400; /* Fast mode */ | ||
581 | else | ||
582 | clock = 100; /* Standard mode */ | ||
583 | |||
584 | dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL); | 798 | dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL); |
585 | if (!dev) { | 799 | if (!dev) { |
586 | r = -ENOMEM; | 800 | r = -ENOMEM; |
587 | goto err_release_region; | 801 | goto err_release_region; |
588 | } | 802 | } |
589 | 803 | ||
804 | if (pdev->dev.platform_data != NULL) | ||
805 | speed = *(u32 *)pdev->dev.platform_data; | ||
806 | else | ||
807 | speed = 100; /* Defualt speed */ | ||
808 | |||
809 | dev->speed = speed; | ||
810 | dev->idle = 1; | ||
590 | dev->dev = &pdev->dev; | 811 | dev->dev = &pdev->dev; |
591 | dev->irq = irq->start; | 812 | dev->irq = irq->start; |
592 | dev->base = ioremap(mem->start, mem->end - mem->start + 1); | 813 | dev->base = ioremap(mem->start, mem->end - mem->start + 1); |
@@ -602,22 +823,39 @@ omap_i2c_probe(struct platform_device *pdev) | |||
602 | 823 | ||
603 | omap_i2c_unidle(dev); | 824 | omap_i2c_unidle(dev); |
604 | 825 | ||
605 | if (cpu_is_omap15xx()) | 826 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; |
606 | dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20; | 827 | |
828 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | ||
829 | u16 s; | ||
830 | |||
831 | /* Set up the fifo size - Get total size */ | ||
832 | s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3; | ||
833 | dev->fifo_size = 0x8 << s; | ||
834 | |||
835 | /* | ||
836 | * Set up notification threshold as half the total available | ||
837 | * size. This is to ensure that we can handle the status on int | ||
838 | * call back latencies. | ||
839 | */ | ||
840 | dev->fifo_size = (dev->fifo_size / 2); | ||
841 | dev->b_hw = 1; /* Enable hardware fixes */ | ||
842 | } | ||
607 | 843 | ||
608 | /* reset ASAP, clearing any IRQs */ | 844 | /* reset ASAP, clearing any IRQs */ |
609 | omap_i2c_init(dev); | 845 | omap_i2c_init(dev); |
610 | 846 | ||
611 | r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr, | 847 | isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr; |
612 | 0, pdev->name, dev); | 848 | r = request_irq(dev->irq, isr, 0, pdev->name, dev); |
613 | 849 | ||
614 | if (r) { | 850 | if (r) { |
615 | dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); | 851 | dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); |
616 | goto err_unuse_clocks; | 852 | goto err_unuse_clocks; |
617 | } | 853 | } |
618 | r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; | 854 | |
619 | dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", | 855 | dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", |
620 | pdev->id, r >> 4, r & 0xf, clock); | 856 | pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed); |
857 | |||
858 | omap_i2c_idle(dev); | ||
621 | 859 | ||
622 | adap = &dev->adapter; | 860 | adap = &dev->adapter; |
623 | i2c_set_adapdata(adap, dev); | 861 | i2c_set_adapdata(adap, dev); |
@@ -635,8 +873,6 @@ omap_i2c_probe(struct platform_device *pdev) | |||
635 | goto err_free_irq; | 873 | goto err_free_irq; |
636 | } | 874 | } |
637 | 875 | ||
638 | omap_i2c_idle(dev); | ||
639 | |||
640 | return 0; | 876 | return 0; |
641 | 877 | ||
642 | err_free_irq: | 878 | err_free_irq: |
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index c39079f9c73f..f69f91ffb469 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -35,11 +35,9 @@ | |||
35 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
36 | #include <linux/cpufreq.h> | 36 | #include <linux/cpufreq.h> |
37 | 37 | ||
38 | #include <mach/hardware.h> | ||
39 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
40 | #include <asm/io.h> | 39 | #include <asm/io.h> |
41 | 40 | ||
42 | #include <mach/regs-gpio.h> | ||
43 | #include <plat/regs-iic.h> | 41 | #include <plat/regs-iic.h> |
44 | #include <plat/iic.h> | 42 | #include <plat/iic.h> |
45 | 43 | ||
@@ -64,6 +62,7 @@ struct s3c24xx_i2c { | |||
64 | unsigned int msg_ptr; | 62 | unsigned int msg_ptr; |
65 | 63 | ||
66 | unsigned int tx_setup; | 64 | unsigned int tx_setup; |
65 | unsigned int irq; | ||
67 | 66 | ||
68 | enum s3c24xx_i2c_state state; | 67 | enum s3c24xx_i2c_state state; |
69 | unsigned long clkrate; | 68 | unsigned long clkrate; |
@@ -71,7 +70,6 @@ struct s3c24xx_i2c { | |||
71 | void __iomem *regs; | 70 | void __iomem *regs; |
72 | struct clk *clk; | 71 | struct clk *clk; |
73 | struct device *dev; | 72 | struct device *dev; |
74 | struct resource *irq; | ||
75 | struct resource *ioarea; | 73 | struct resource *ioarea; |
76 | struct i2c_adapter adap; | 74 | struct i2c_adapter adap; |
77 | 75 | ||
@@ -80,16 +78,7 @@ struct s3c24xx_i2c { | |||
80 | #endif | 78 | #endif |
81 | }; | 79 | }; |
82 | 80 | ||
83 | /* default platform data to use if not supplied in the platform_device | 81 | /* default platform data removed, dev should always carry data. */ |
84 | */ | ||
85 | |||
86 | static struct s3c2410_platform_i2c s3c24xx_i2c_default_platform = { | ||
87 | .flags = 0, | ||
88 | .slave_addr = 0x10, | ||
89 | .bus_freq = 100*1000, | ||
90 | .max_freq = 400*1000, | ||
91 | .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON, | ||
92 | }; | ||
93 | 82 | ||
94 | /* s3c24xx_i2c_is2440() | 83 | /* s3c24xx_i2c_is2440() |
95 | * | 84 | * |
@@ -103,21 +92,6 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c) | |||
103 | return !strcmp(pdev->name, "s3c2440-i2c"); | 92 | return !strcmp(pdev->name, "s3c2440-i2c"); |
104 | } | 93 | } |
105 | 94 | ||
106 | |||
107 | /* s3c24xx_i2c_get_platformdata | ||
108 | * | ||
109 | * get the platform data associated with the given device, or return | ||
110 | * the default if there is none | ||
111 | */ | ||
112 | |||
113 | static inline struct s3c2410_platform_i2c *s3c24xx_i2c_get_platformdata(struct device *dev) | ||
114 | { | ||
115 | if (dev->platform_data != NULL) | ||
116 | return (struct s3c2410_platform_i2c *)dev->platform_data; | ||
117 | |||
118 | return &s3c24xx_i2c_default_platform; | ||
119 | } | ||
120 | |||
121 | /* s3c24xx_i2c_master_complete | 95 | /* s3c24xx_i2c_master_complete |
122 | * | 96 | * |
123 | * complete the message and wake up the caller, using the given return code, | 97 | * complete the message and wake up the caller, using the given return code, |
@@ -130,7 +104,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) | |||
130 | 104 | ||
131 | i2c->msg_ptr = 0; | 105 | i2c->msg_ptr = 0; |
132 | i2c->msg = NULL; | 106 | i2c->msg = NULL; |
133 | i2c->msg_idx ++; | 107 | i2c->msg_idx++; |
134 | i2c->msg_num = 0; | 108 | i2c->msg_num = 0; |
135 | if (ret) | 109 | if (ret) |
136 | i2c->msg_idx = ret; | 110 | i2c->msg_idx = ret; |
@@ -141,19 +115,17 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) | |||
141 | static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) | 115 | static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) |
142 | { | 116 | { |
143 | unsigned long tmp; | 117 | unsigned long tmp; |
144 | 118 | ||
145 | tmp = readl(i2c->regs + S3C2410_IICCON); | 119 | tmp = readl(i2c->regs + S3C2410_IICCON); |
146 | writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); | 120 | writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); |
147 | |||
148 | } | 121 | } |
149 | 122 | ||
150 | static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) | 123 | static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) |
151 | { | 124 | { |
152 | unsigned long tmp; | 125 | unsigned long tmp; |
153 | 126 | ||
154 | tmp = readl(i2c->regs + S3C2410_IICCON); | 127 | tmp = readl(i2c->regs + S3C2410_IICCON); |
155 | writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); | 128 | writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); |
156 | |||
157 | } | 129 | } |
158 | 130 | ||
159 | /* irq enable/disable functions */ | 131 | /* irq enable/disable functions */ |
@@ -161,7 +133,7 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) | |||
161 | static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) | 133 | static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) |
162 | { | 134 | { |
163 | unsigned long tmp; | 135 | unsigned long tmp; |
164 | 136 | ||
165 | tmp = readl(i2c->regs + S3C2410_IICCON); | 137 | tmp = readl(i2c->regs + S3C2410_IICCON); |
166 | writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); | 138 | writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); |
167 | } | 139 | } |
@@ -169,7 +141,7 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) | |||
169 | static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) | 141 | static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) |
170 | { | 142 | { |
171 | unsigned long tmp; | 143 | unsigned long tmp; |
172 | 144 | ||
173 | tmp = readl(i2c->regs + S3C2410_IICCON); | 145 | tmp = readl(i2c->regs + S3C2410_IICCON); |
174 | writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); | 146 | writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); |
175 | } | 147 | } |
@@ -177,10 +149,10 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) | |||
177 | 149 | ||
178 | /* s3c24xx_i2c_message_start | 150 | /* s3c24xx_i2c_message_start |
179 | * | 151 | * |
180 | * put the start of a message onto the bus | 152 | * put the start of a message onto the bus |
181 | */ | 153 | */ |
182 | 154 | ||
183 | static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, | 155 | static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, |
184 | struct i2c_msg *msg) | 156 | struct i2c_msg *msg) |
185 | { | 157 | { |
186 | unsigned int addr = (msg->addr & 0x7f) << 1; | 158 | unsigned int addr = (msg->addr & 0x7f) << 1; |
@@ -199,15 +171,15 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, | |||
199 | if (msg->flags & I2C_M_REV_DIR_ADDR) | 171 | if (msg->flags & I2C_M_REV_DIR_ADDR) |
200 | addr ^= 1; | 172 | addr ^= 1; |
201 | 173 | ||
202 | // todo - check for wether ack wanted or not | 174 | /* todo - check for wether ack wanted or not */ |
203 | s3c24xx_i2c_enable_ack(i2c); | 175 | s3c24xx_i2c_enable_ack(i2c); |
204 | 176 | ||
205 | iiccon = readl(i2c->regs + S3C2410_IICCON); | 177 | iiccon = readl(i2c->regs + S3C2410_IICCON); |
206 | writel(stat, i2c->regs + S3C2410_IICSTAT); | 178 | writel(stat, i2c->regs + S3C2410_IICSTAT); |
207 | 179 | ||
208 | dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); | 180 | dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); |
209 | writeb(addr, i2c->regs + S3C2410_IICDS); | 181 | writeb(addr, i2c->regs + S3C2410_IICDS); |
210 | 182 | ||
211 | /* delay here to ensure the data byte has gotten onto the bus | 183 | /* delay here to ensure the data byte has gotten onto the bus |
212 | * before the transaction is started */ | 184 | * before the transaction is started */ |
213 | 185 | ||
@@ -215,8 +187,8 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, | |||
215 | 187 | ||
216 | dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); | 188 | dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); |
217 | writel(iiccon, i2c->regs + S3C2410_IICCON); | 189 | writel(iiccon, i2c->regs + S3C2410_IICCON); |
218 | 190 | ||
219 | stat |= S3C2410_IICSTAT_START; | 191 | stat |= S3C2410_IICSTAT_START; |
220 | writel(stat, i2c->regs + S3C2410_IICSTAT); | 192 | writel(stat, i2c->regs + S3C2410_IICSTAT); |
221 | } | 193 | } |
222 | 194 | ||
@@ -227,11 +199,11 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) | |||
227 | dev_dbg(i2c->dev, "STOP\n"); | 199 | dev_dbg(i2c->dev, "STOP\n"); |
228 | 200 | ||
229 | /* stop the transfer */ | 201 | /* stop the transfer */ |
230 | iicstat &= ~ S3C2410_IICSTAT_START; | 202 | iicstat &= ~S3C2410_IICSTAT_START; |
231 | writel(iicstat, i2c->regs + S3C2410_IICSTAT); | 203 | writel(iicstat, i2c->regs + S3C2410_IICSTAT); |
232 | 204 | ||
233 | i2c->state = STATE_STOP; | 205 | i2c->state = STATE_STOP; |
234 | 206 | ||
235 | s3c24xx_i2c_master_complete(i2c, ret); | 207 | s3c24xx_i2c_master_complete(i2c, ret); |
236 | s3c24xx_i2c_disable_irq(i2c); | 208 | s3c24xx_i2c_disable_irq(i2c); |
237 | } | 209 | } |
@@ -241,7 +213,7 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) | |||
241 | 213 | ||
242 | /* is_lastmsg() | 214 | /* is_lastmsg() |
243 | * | 215 | * |
244 | * returns TRUE if the current message is the last in the set | 216 | * returns TRUE if the current message is the last in the set |
245 | */ | 217 | */ |
246 | 218 | ||
247 | static inline int is_lastmsg(struct s3c24xx_i2c *i2c) | 219 | static inline int is_lastmsg(struct s3c24xx_i2c *i2c) |
@@ -289,14 +261,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
289 | 261 | ||
290 | case STATE_STOP: | 262 | case STATE_STOP: |
291 | dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); | 263 | dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); |
292 | s3c24xx_i2c_disable_irq(i2c); | 264 | s3c24xx_i2c_disable_irq(i2c); |
293 | goto out_ack; | 265 | goto out_ack; |
294 | 266 | ||
295 | case STATE_START: | 267 | case STATE_START: |
296 | /* last thing we did was send a start condition on the | 268 | /* last thing we did was send a start condition on the |
297 | * bus, or started a new i2c message | 269 | * bus, or started a new i2c message |
298 | */ | 270 | */ |
299 | 271 | ||
300 | if (iicstat & S3C2410_IICSTAT_LASTBIT && | 272 | if (iicstat & S3C2410_IICSTAT_LASTBIT && |
301 | !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { | 273 | !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { |
302 | /* ack was not received... */ | 274 | /* ack was not received... */ |
@@ -322,7 +294,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
322 | if (i2c->state == STATE_READ) | 294 | if (i2c->state == STATE_READ) |
323 | goto prepare_read; | 295 | goto prepare_read; |
324 | 296 | ||
325 | /* fall through to the write state, as we will need to | 297 | /* fall through to the write state, as we will need to |
326 | * send a byte as well */ | 298 | * send a byte as well */ |
327 | 299 | ||
328 | case STATE_WRITE: | 300 | case STATE_WRITE: |
@@ -339,7 +311,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
339 | } | 311 | } |
340 | } | 312 | } |
341 | 313 | ||
342 | retry_write: | 314 | retry_write: |
343 | 315 | ||
344 | if (!is_msgend(i2c)) { | 316 | if (!is_msgend(i2c)) { |
345 | byte = i2c->msg->buf[i2c->msg_ptr++]; | 317 | byte = i2c->msg->buf[i2c->msg_ptr++]; |
@@ -359,9 +331,9 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
359 | dev_dbg(i2c->dev, "WRITE: Next Message\n"); | 331 | dev_dbg(i2c->dev, "WRITE: Next Message\n"); |
360 | 332 | ||
361 | i2c->msg_ptr = 0; | 333 | i2c->msg_ptr = 0; |
362 | i2c->msg_idx ++; | 334 | i2c->msg_idx++; |
363 | i2c->msg++; | 335 | i2c->msg++; |
364 | 336 | ||
365 | /* check to see if we need to do another message */ | 337 | /* check to see if we need to do another message */ |
366 | if (i2c->msg->flags & I2C_M_NOSTART) { | 338 | if (i2c->msg->flags & I2C_M_NOSTART) { |
367 | 339 | ||
@@ -375,7 +347,6 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
375 | 347 | ||
376 | goto retry_write; | 348 | goto retry_write; |
377 | } else { | 349 | } else { |
378 | |||
379 | /* send the new start */ | 350 | /* send the new start */ |
380 | s3c24xx_i2c_message_start(i2c, i2c->msg); | 351 | s3c24xx_i2c_message_start(i2c, i2c->msg); |
381 | i2c->state = STATE_START; | 352 | i2c->state = STATE_START; |
@@ -389,7 +360,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
389 | break; | 360 | break; |
390 | 361 | ||
391 | case STATE_READ: | 362 | case STATE_READ: |
392 | /* we have a byte of data in the data register, do | 363 | /* we have a byte of data in the data register, do |
393 | * something with it, and then work out wether we are | 364 | * something with it, and then work out wether we are |
394 | * going to do any more read/write | 365 | * going to do any more read/write |
395 | */ | 366 | */ |
@@ -397,13 +368,13 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
397 | byte = readb(i2c->regs + S3C2410_IICDS); | 368 | byte = readb(i2c->regs + S3C2410_IICDS); |
398 | i2c->msg->buf[i2c->msg_ptr++] = byte; | 369 | i2c->msg->buf[i2c->msg_ptr++] = byte; |
399 | 370 | ||
400 | prepare_read: | 371 | prepare_read: |
401 | if (is_msglast(i2c)) { | 372 | if (is_msglast(i2c)) { |
402 | /* last byte of buffer */ | 373 | /* last byte of buffer */ |
403 | 374 | ||
404 | if (is_lastmsg(i2c)) | 375 | if (is_lastmsg(i2c)) |
405 | s3c24xx_i2c_disable_ack(i2c); | 376 | s3c24xx_i2c_disable_ack(i2c); |
406 | 377 | ||
407 | } else if (is_msgend(i2c)) { | 378 | } else if (is_msgend(i2c)) { |
408 | /* ok, we've read the entire buffer, see if there | 379 | /* ok, we've read the entire buffer, see if there |
409 | * is anything else we need to do */ | 380 | * is anything else we need to do */ |
@@ -429,7 +400,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) | |||
429 | /* acknowlegde the IRQ and get back on with the work */ | 400 | /* acknowlegde the IRQ and get back on with the work */ |
430 | 401 | ||
431 | out_ack: | 402 | out_ack: |
432 | tmp = readl(i2c->regs + S3C2410_IICCON); | 403 | tmp = readl(i2c->regs + S3C2410_IICCON); |
433 | tmp &= ~S3C2410_IICCON_IRQPEND; | 404 | tmp &= ~S3C2410_IICCON_IRQPEND; |
434 | writel(tmp, i2c->regs + S3C2410_IICCON); | 405 | writel(tmp, i2c->regs + S3C2410_IICCON); |
435 | out: | 406 | out: |
@@ -450,19 +421,19 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) | |||
450 | status = readl(i2c->regs + S3C2410_IICSTAT); | 421 | status = readl(i2c->regs + S3C2410_IICSTAT); |
451 | 422 | ||
452 | if (status & S3C2410_IICSTAT_ARBITR) { | 423 | if (status & S3C2410_IICSTAT_ARBITR) { |
453 | // deal with arbitration loss | 424 | /* deal with arbitration loss */ |
454 | dev_err(i2c->dev, "deal with arbitration loss\n"); | 425 | dev_err(i2c->dev, "deal with arbitration loss\n"); |
455 | } | 426 | } |
456 | 427 | ||
457 | if (i2c->state == STATE_IDLE) { | 428 | if (i2c->state == STATE_IDLE) { |
458 | dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); | 429 | dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); |
459 | 430 | ||
460 | tmp = readl(i2c->regs + S3C2410_IICCON); | 431 | tmp = readl(i2c->regs + S3C2410_IICCON); |
461 | tmp &= ~S3C2410_IICCON_IRQPEND; | 432 | tmp &= ~S3C2410_IICCON_IRQPEND; |
462 | writel(tmp, i2c->regs + S3C2410_IICCON); | 433 | writel(tmp, i2c->regs + S3C2410_IICCON); |
463 | goto out; | 434 | goto out; |
464 | } | 435 | } |
465 | 436 | ||
466 | /* pretty much this leaves us with the fact that we've | 437 | /* pretty much this leaves us with the fact that we've |
467 | * transmitted or received whatever byte we last sent */ | 438 | * transmitted or received whatever byte we last sent */ |
468 | 439 | ||
@@ -485,16 +456,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) | |||
485 | 456 | ||
486 | while (timeout-- > 0) { | 457 | while (timeout-- > 0) { |
487 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); | 458 | iicstat = readl(i2c->regs + S3C2410_IICSTAT); |
488 | 459 | ||
489 | if (!(iicstat & S3C2410_IICSTAT_BUSBUSY)) | 460 | if (!(iicstat & S3C2410_IICSTAT_BUSBUSY)) |
490 | return 0; | 461 | return 0; |
491 | 462 | ||
492 | msleep(1); | 463 | msleep(1); |
493 | } | 464 | } |
494 | 465 | ||
495 | dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n", | ||
496 | __raw_readl(S3C2410_GPEDAT)); | ||
497 | |||
498 | return -ETIMEDOUT; | 466 | return -ETIMEDOUT; |
499 | } | 467 | } |
500 | 468 | ||
@@ -503,7 +471,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) | |||
503 | * this starts an i2c transfer | 471 | * this starts an i2c transfer |
504 | */ | 472 | */ |
505 | 473 | ||
506 | static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) | 474 | static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, |
475 | struct i2c_msg *msgs, int num) | ||
507 | { | 476 | { |
508 | unsigned long timeout; | 477 | unsigned long timeout; |
509 | int ret; | 478 | int ret; |
@@ -529,12 +498,12 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int | |||
529 | s3c24xx_i2c_enable_irq(i2c); | 498 | s3c24xx_i2c_enable_irq(i2c); |
530 | s3c24xx_i2c_message_start(i2c, msgs); | 499 | s3c24xx_i2c_message_start(i2c, msgs); |
531 | spin_unlock_irq(&i2c->lock); | 500 | spin_unlock_irq(&i2c->lock); |
532 | 501 | ||
533 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); | 502 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); |
534 | 503 | ||
535 | ret = i2c->msg_idx; | 504 | ret = i2c->msg_idx; |
536 | 505 | ||
537 | /* having these next two as dev_err() makes life very | 506 | /* having these next two as dev_err() makes life very |
538 | * noisy when doing an i2cdetect */ | 507 | * noisy when doing an i2cdetect */ |
539 | 508 | ||
540 | if (timeout == 0) | 509 | if (timeout == 0) |
@@ -591,19 +560,6 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = { | |||
591 | .functionality = s3c24xx_i2c_func, | 560 | .functionality = s3c24xx_i2c_func, |
592 | }; | 561 | }; |
593 | 562 | ||
594 | static struct s3c24xx_i2c s3c24xx_i2c = { | ||
595 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock), | ||
596 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), | ||
597 | .tx_setup = 50, | ||
598 | .adap = { | ||
599 | .name = "s3c2410-i2c", | ||
600 | .owner = THIS_MODULE, | ||
601 | .algo = &s3c24xx_i2c_algorithm, | ||
602 | .retries = 2, | ||
603 | .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, | ||
604 | }, | ||
605 | }; | ||
606 | |||
607 | /* s3c24xx_i2c_calcdivisor | 563 | /* s3c24xx_i2c_calcdivisor |
608 | * | 564 | * |
609 | * return the divisor settings for a given frequency | 565 | * return the divisor settings for a given frequency |
@@ -643,7 +599,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted) | |||
643 | { | 599 | { |
644 | int diff = freq - wanted; | 600 | int diff = freq - wanted; |
645 | 601 | ||
646 | return (diff >= -2 && diff <= 2); | 602 | return diff >= -2 && diff <= 2; |
647 | } | 603 | } |
648 | 604 | ||
649 | /* s3c24xx_i2c_clockrate | 605 | /* s3c24xx_i2c_clockrate |
@@ -655,7 +611,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted) | |||
655 | 611 | ||
656 | static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) | 612 | static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) |
657 | { | 613 | { |
658 | struct s3c2410_platform_i2c *pdata; | 614 | struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data; |
659 | unsigned long clkin = clk_get_rate(i2c->clk); | 615 | unsigned long clkin = clk_get_rate(i2c->clk); |
660 | unsigned int divs, div1; | 616 | unsigned int divs, div1; |
661 | u32 iiccon; | 617 | u32 iiccon; |
@@ -663,10 +619,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) | |||
663 | int start, end; | 619 | int start, end; |
664 | 620 | ||
665 | i2c->clkrate = clkin; | 621 | i2c->clkrate = clkin; |
666 | |||
667 | pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent); | ||
668 | clkin /= 1000; /* clkin now in KHz */ | 622 | clkin /= 1000; /* clkin now in KHz */ |
669 | 623 | ||
670 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", | 624 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", |
671 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); | 625 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); |
672 | 626 | ||
@@ -774,7 +728,7 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) | |||
774 | 728 | ||
775 | /* s3c24xx_i2c_init | 729 | /* s3c24xx_i2c_init |
776 | * | 730 | * |
777 | * initialise the controller, set the IO lines and frequency | 731 | * initialise the controller, set the IO lines and frequency |
778 | */ | 732 | */ |
779 | 733 | ||
780 | static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | 734 | static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) |
@@ -785,15 +739,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
785 | 739 | ||
786 | /* get the plafrom data */ | 740 | /* get the plafrom data */ |
787 | 741 | ||
788 | pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent); | 742 | pdata = i2c->dev->platform_data; |
789 | 743 | ||
790 | /* inititalise the gpio */ | 744 | /* inititalise the gpio */ |
791 | 745 | ||
792 | s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA); | 746 | if (pdata->cfg_gpio) |
793 | s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL); | 747 | pdata->cfg_gpio(to_platform_device(i2c->dev)); |
794 | 748 | ||
795 | /* write slave address */ | 749 | /* write slave address */ |
796 | 750 | ||
797 | writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); | 751 | writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); |
798 | 752 | ||
799 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); | 753 | dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); |
@@ -831,12 +785,32 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
831 | 785 | ||
832 | static int s3c24xx_i2c_probe(struct platform_device *pdev) | 786 | static int s3c24xx_i2c_probe(struct platform_device *pdev) |
833 | { | 787 | { |
834 | struct s3c24xx_i2c *i2c = &s3c24xx_i2c; | 788 | struct s3c24xx_i2c *i2c; |
835 | struct s3c2410_platform_i2c *pdata; | 789 | struct s3c2410_platform_i2c *pdata; |
836 | struct resource *res; | 790 | struct resource *res; |
837 | int ret; | 791 | int ret; |
838 | 792 | ||
839 | pdata = s3c24xx_i2c_get_platformdata(&pdev->dev); | 793 | pdata = pdev->dev.platform_data; |
794 | if (!pdata) { | ||
795 | dev_err(&pdev->dev, "no platform data\n"); | ||
796 | return -EINVAL; | ||
797 | } | ||
798 | |||
799 | i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL); | ||
800 | if (!i2c) { | ||
801 | dev_err(&pdev->dev, "no memory for state\n"); | ||
802 | return -ENOMEM; | ||
803 | } | ||
804 | |||
805 | strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); | ||
806 | i2c->adap.owner = THIS_MODULE; | ||
807 | i2c->adap.algo = &s3c24xx_i2c_algorithm; | ||
808 | i2c->adap.retries = 2; | ||
809 | i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | ||
810 | i2c->tx_setup = 50; | ||
811 | |||
812 | spin_lock_init(&i2c->lock); | ||
813 | init_waitqueue_head(&i2c->wait); | ||
840 | 814 | ||
841 | /* find the clock and enable it */ | 815 | /* find the clock and enable it */ |
842 | 816 | ||
@@ -878,7 +852,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
878 | goto err_ioarea; | 852 | goto err_ioarea; |
879 | } | 853 | } |
880 | 854 | ||
881 | dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); | 855 | dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", |
856 | i2c->regs, i2c->ioarea, res); | ||
882 | 857 | ||
883 | /* setup info block for the i2c core */ | 858 | /* setup info block for the i2c core */ |
884 | 859 | ||
@@ -892,29 +867,23 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
892 | goto err_iomap; | 867 | goto err_iomap; |
893 | 868 | ||
894 | /* find the IRQ for this unit (note, this relies on the init call to | 869 | /* find the IRQ for this unit (note, this relies on the init call to |
895 | * ensure no current IRQs pending | 870 | * ensure no current IRQs pending |
896 | */ | 871 | */ |
897 | 872 | ||
898 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 873 | i2c->irq = ret = platform_get_irq(pdev, 0); |
899 | if (res == NULL) { | 874 | if (ret <= 0) { |
900 | dev_err(&pdev->dev, "cannot find IRQ\n"); | 875 | dev_err(&pdev->dev, "cannot find IRQ\n"); |
901 | ret = -ENOENT; | ||
902 | goto err_iomap; | 876 | goto err_iomap; |
903 | } | 877 | } |
904 | 878 | ||
905 | ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED, | 879 | ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED, |
906 | pdev->name, i2c); | 880 | dev_name(&pdev->dev), i2c); |
907 | 881 | ||
908 | if (ret != 0) { | 882 | if (ret != 0) { |
909 | dev_err(&pdev->dev, "cannot claim IRQ\n"); | 883 | dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); |
910 | goto err_iomap; | 884 | goto err_iomap; |
911 | } | 885 | } |
912 | 886 | ||
913 | i2c->irq = res; | ||
914 | |||
915 | dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res, | ||
916 | (unsigned long)res->start); | ||
917 | |||
918 | ret = s3c24xx_i2c_register_cpufreq(i2c); | 887 | ret = s3c24xx_i2c_register_cpufreq(i2c); |
919 | if (ret < 0) { | 888 | if (ret < 0) { |
920 | dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); | 889 | dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); |
@@ -944,7 +913,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
944 | s3c24xx_i2c_deregister_cpufreq(i2c); | 913 | s3c24xx_i2c_deregister_cpufreq(i2c); |
945 | 914 | ||
946 | err_irq: | 915 | err_irq: |
947 | free_irq(i2c->irq->start, i2c); | 916 | free_irq(i2c->irq, i2c); |
948 | 917 | ||
949 | err_iomap: | 918 | err_iomap: |
950 | iounmap(i2c->regs); | 919 | iounmap(i2c->regs); |
@@ -958,6 +927,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
958 | clk_put(i2c->clk); | 927 | clk_put(i2c->clk); |
959 | 928 | ||
960 | err_noclk: | 929 | err_noclk: |
930 | kfree(i2c); | ||
961 | return ret; | 931 | return ret; |
962 | } | 932 | } |
963 | 933 | ||
@@ -973,7 +943,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) | |||
973 | s3c24xx_i2c_deregister_cpufreq(i2c); | 943 | s3c24xx_i2c_deregister_cpufreq(i2c); |
974 | 944 | ||
975 | i2c_del_adapter(&i2c->adap); | 945 | i2c_del_adapter(&i2c->adap); |
976 | free_irq(i2c->irq->start, i2c); | 946 | free_irq(i2c->irq, i2c); |
977 | 947 | ||
978 | clk_disable(i2c->clk); | 948 | clk_disable(i2c->clk); |
979 | clk_put(i2c->clk); | 949 | clk_put(i2c->clk); |
@@ -982,6 +952,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) | |||
982 | 952 | ||
983 | release_resource(i2c->ioarea); | 953 | release_resource(i2c->ioarea); |
984 | kfree(i2c->ioarea); | 954 | kfree(i2c->ioarea); |
955 | kfree(i2c); | ||
985 | 956 | ||
986 | return 0; | 957 | return 0; |
987 | } | 958 | } |
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 4c35702830ce..864ac561fdbb 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig | |||
@@ -126,19 +126,6 @@ config ISP1301_OMAP | |||
126 | This driver can also be built as a module. If so, the module | 126 | This driver can also be built as a module. If so, the module |
127 | will be called isp1301_omap. | 127 | will be called isp1301_omap. |
128 | 128 | ||
129 | config TPS65010 | ||
130 | tristate "TPS6501x Power Management chips" | ||
131 | depends on GPIOLIB | ||
132 | default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK | ||
133 | help | ||
134 | If you say yes here you get support for the TPS6501x series of | ||
135 | Power Management chips. These include voltage regulators, | ||
136 | lithium ion/polymer battery charging, and other features that | ||
137 | are often used in portable devices like cell phones and cameras. | ||
138 | |||
139 | This driver can also be built as a module. If so, the module | ||
140 | will be called tps65010. | ||
141 | |||
142 | config SENSORS_MAX6875 | 129 | config SENSORS_MAX6875 |
143 | tristate "Maxim MAX6875 Power supply supervisor" | 130 | tristate "Maxim MAX6875 Power supply supervisor" |
144 | depends on EXPERIMENTAL | 131 | depends on EXPERIMENTAL |
@@ -164,16 +151,6 @@ config SENSORS_TSL2550 | |||
164 | This driver can also be built as a module. If so, the module | 151 | This driver can also be built as a module. If so, the module |
165 | will be called tsl2550. | 152 | will be called tsl2550. |
166 | 153 | ||
167 | config MENELAUS | ||
168 | bool "TWL92330/Menelaus PM chip" | ||
169 | depends on I2C=y && ARCH_OMAP24XX | ||
170 | help | ||
171 | If you say yes here you get support for the Texas Instruments | ||
172 | TWL92330/Menelaus Power Management chip. This include voltage | ||
173 | regulators, Dual slot memory card tranceivers, real-time clock | ||
174 | and other features that are often used in portable devices like | ||
175 | cell phones and PDAs. | ||
176 | |||
177 | config MCU_MPC8349EMITX | 154 | config MCU_MPC8349EMITX |
178 | tristate "MPC8349E-mITX MCU driver" | 155 | tristate "MPC8349E-mITX MCU driver" |
179 | depends on I2C && PPC_83xx | 156 | depends on I2C && PPC_83xx |
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 23d2a31b0a64..8b95f41a5001 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile | |||
@@ -19,8 +19,6 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o | |||
19 | obj-$(CONFIG_PCF8575) += pcf8575.o | 19 | obj-$(CONFIG_PCF8575) += pcf8575.o |
20 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | 20 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o |
21 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 21 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
22 | obj-$(CONFIG_TPS65010) += tps65010.o | ||
23 | obj-$(CONFIG_MENELAUS) += menelaus.o | ||
24 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o | 22 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o |
25 | obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o | 23 | obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o |
26 | 24 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 53912c327bfe..8dc2bb781605 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c | |||
@@ -57,9 +57,6 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry, | |||
57 | } | 57 | } |
58 | 58 | ||
59 | inode->i_mode = mode; | 59 | inode->i_mode = mode; |
60 | inode->i_uid = 0; | ||
61 | inode->i_gid = 0; | ||
62 | inode->i_blocks = 0; | ||
63 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 60 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
64 | inode->i_private = data; | 61 | inode->i_private = data; |
65 | if ((mode & S_IFMT) == S_IFDIR) { | 62 | if ((mode & S_IFMT) == S_IFDIR) { |
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index d5b4cc357a3c..650120261abf 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c | |||
@@ -1519,7 +1519,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep) | |||
1519 | int digit2 = 0; | 1519 | int digit2 = 0; |
1520 | if (!isdigit(*s)) return -3; | 1520 | if (!isdigit(*s)) return -3; |
1521 | while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } | 1521 | while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } |
1522 | if (digit1 <= 0 && digit1 > 30) return -4; | 1522 | if (digit1 <= 0 || digit1 > 30) return -4; |
1523 | if (*s == 0 || *s == ',' || *s == ' ') { | 1523 | if (*s == 0 || *s == ',' || *s == ' ') { |
1524 | bmask |= (1 << digit1); | 1524 | bmask |= (1 << digit1); |
1525 | digit1 = 0; | 1525 | digit1 = 0; |
@@ -1530,7 +1530,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep) | |||
1530 | s++; | 1530 | s++; |
1531 | if (!isdigit(*s)) return -3; | 1531 | if (!isdigit(*s)) return -3; |
1532 | while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } | 1532 | while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } |
1533 | if (digit2 <= 0 && digit2 > 30) return -4; | 1533 | if (digit2 <= 0 || digit2 > 30) return -4; |
1534 | if (*s == 0 || *s == ',' || *s == ' ') { | 1534 | if (*s == 0 || *s == ',' || *s == ' ') { |
1535 | if (digit1 > digit2) | 1535 | if (digit1 > digit2) |
1536 | for (i = digit2; i <= digit1 ; i++) | 1536 | for (i = digit2; i <= digit1 ; i++) |
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 0aa66ec4cbdd..b129409925af 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c | |||
@@ -111,8 +111,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent) | |||
111 | goto fail; | 111 | goto fail; |
112 | inode->i_ino = 1; | 112 | inode->i_ino = 1; |
113 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 113 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
114 | inode->i_blocks = 0; | ||
115 | inode->i_uid = inode->i_gid = 0; | ||
116 | inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; | 114 | inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; |
117 | inode->i_op = &simple_dir_inode_operations; | 115 | inode->i_op = &simple_dir_inode_operations; |
118 | inode->i_fop = &simple_dir_operations; | 116 | inode->i_fop = &simple_dir_operations; |
diff --git a/drivers/md/Makefile b/drivers/md/Makefile index 1c615804ea76..72880b7e28d9 100644 --- a/drivers/md/Makefile +++ b/drivers/md/Makefile | |||
@@ -3,9 +3,10 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ | 5 | dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \ |
6 | dm-ioctl.o dm-io.o dm-kcopyd.o | 6 | dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o |
7 | dm-multipath-objs := dm-path-selector.o dm-mpath.o | 7 | dm-multipath-objs := dm-path-selector.o dm-mpath.o |
8 | dm-snapshot-objs := dm-snap.o dm-exception-store.o | 8 | dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-snap-transient.o \ |
9 | dm-snap-persistent.o | ||
9 | dm-mirror-objs := dm-raid1.o | 10 | dm-mirror-objs := dm-raid1.o |
10 | md-mod-objs := md.o bitmap.o | 11 | md-mod-objs := md.o bitmap.o |
11 | raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ | 12 | raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \ |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 3326750ec02c..35bda49796fb 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -1322,11 +1322,7 @@ static int __init dm_crypt_init(void) | |||
1322 | 1322 | ||
1323 | static void __exit dm_crypt_exit(void) | 1323 | static void __exit dm_crypt_exit(void) |
1324 | { | 1324 | { |
1325 | int r = dm_unregister_target(&crypt_target); | 1325 | dm_unregister_target(&crypt_target); |
1326 | |||
1327 | if (r < 0) | ||
1328 | DMERR("unregister failed %d", r); | ||
1329 | |||
1330 | kmem_cache_destroy(_crypt_io_pool); | 1326 | kmem_cache_destroy(_crypt_io_pool); |
1331 | } | 1327 | } |
1332 | 1328 | ||
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 848b381f1173..59ee1b015d2d 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c | |||
@@ -364,11 +364,7 @@ bad_queue: | |||
364 | 364 | ||
365 | static void __exit dm_delay_exit(void) | 365 | static void __exit dm_delay_exit(void) |
366 | { | 366 | { |
367 | int r = dm_unregister_target(&delay_target); | 367 | dm_unregister_target(&delay_target); |
368 | |||
369 | if (r < 0) | ||
370 | DMERR("unregister failed %d", r); | ||
371 | |||
372 | kmem_cache_destroy(delayed_cache); | 368 | kmem_cache_destroy(delayed_cache); |
373 | destroy_workqueue(kdelayd_wq); | 369 | destroy_workqueue(kdelayd_wq); |
374 | } | 370 | } |
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 01590f3e0009..dccbfb0e010f 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
@@ -1,756 +1,45 @@ | |||
1 | /* | 1 | /* |
2 | * dm-exception-store.c | ||
3 | * | ||
4 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. | 2 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. |
5 | * Copyright (C) 2006 Red Hat GmbH | 3 | * Copyright (C) 2006-2008 Red Hat GmbH |
6 | * | 4 | * |
7 | * This file is released under the GPL. | 5 | * This file is released under the GPL. |
8 | */ | 6 | */ |
9 | 7 | ||
10 | #include "dm-snap.h" | 8 | #include "dm-exception-store.h" |
11 | 9 | ||
12 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
13 | #include <linux/pagemap.h> | 11 | #include <linux/pagemap.h> |
14 | #include <linux/vmalloc.h> | 12 | #include <linux/vmalloc.h> |
15 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
16 | #include <linux/dm-io.h> | ||
17 | #include <linux/dm-kcopyd.h> | ||
18 | |||
19 | #define DM_MSG_PREFIX "snapshots" | ||
20 | #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ | ||
21 | |||
22 | /*----------------------------------------------------------------- | ||
23 | * Persistent snapshots, by persistent we mean that the snapshot | ||
24 | * will survive a reboot. | ||
25 | *---------------------------------------------------------------*/ | ||
26 | |||
27 | /* | ||
28 | * We need to store a record of which parts of the origin have | ||
29 | * been copied to the snapshot device. The snapshot code | ||
30 | * requires that we copy exception chunks to chunk aligned areas | ||
31 | * of the COW store. It makes sense therefore, to store the | ||
32 | * metadata in chunk size blocks. | ||
33 | * | ||
34 | * There is no backward or forward compatibility implemented, | ||
35 | * snapshots with different disk versions than the kernel will | ||
36 | * not be usable. It is expected that "lvcreate" will blank out | ||
37 | * the start of a fresh COW device before calling the snapshot | ||
38 | * constructor. | ||
39 | * | ||
40 | * The first chunk of the COW device just contains the header. | ||
41 | * After this there is a chunk filled with exception metadata, | ||
42 | * followed by as many exception chunks as can fit in the | ||
43 | * metadata areas. | ||
44 | * | ||
45 | * All on disk structures are in little-endian format. The end | ||
46 | * of the exceptions info is indicated by an exception with a | ||
47 | * new_chunk of 0, which is invalid since it would point to the | ||
48 | * header chunk. | ||
49 | */ | ||
50 | |||
51 | /* | ||
52 | * Magic for persistent snapshots: "SnAp" - Feeble isn't it. | ||
53 | */ | ||
54 | #define SNAP_MAGIC 0x70416e53 | ||
55 | |||
56 | /* | ||
57 | * The on-disk version of the metadata. | ||
58 | */ | ||
59 | #define SNAPSHOT_DISK_VERSION 1 | ||
60 | |||
61 | struct disk_header { | ||
62 | uint32_t magic; | ||
63 | |||
64 | /* | ||
65 | * Is this snapshot valid. There is no way of recovering | ||
66 | * an invalid snapshot. | ||
67 | */ | ||
68 | uint32_t valid; | ||
69 | |||
70 | /* | ||
71 | * Simple, incrementing version. no backward | ||
72 | * compatibility. | ||
73 | */ | ||
74 | uint32_t version; | ||
75 | |||
76 | /* In sectors */ | ||
77 | uint32_t chunk_size; | ||
78 | }; | ||
79 | |||
80 | struct disk_exception { | ||
81 | uint64_t old_chunk; | ||
82 | uint64_t new_chunk; | ||
83 | }; | ||
84 | |||
85 | struct commit_callback { | ||
86 | void (*callback)(void *, int success); | ||
87 | void *context; | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * The top level structure for a persistent exception store. | ||
92 | */ | ||
93 | struct pstore { | ||
94 | struct dm_snapshot *snap; /* up pointer to my snapshot */ | ||
95 | int version; | ||
96 | int valid; | ||
97 | uint32_t exceptions_per_area; | ||
98 | |||
99 | /* | ||
100 | * Now that we have an asynchronous kcopyd there is no | ||
101 | * need for large chunk sizes, so it wont hurt to have a | ||
102 | * whole chunks worth of metadata in memory at once. | ||
103 | */ | ||
104 | void *area; | ||
105 | |||
106 | /* | ||
107 | * An area of zeros used to clear the next area. | ||
108 | */ | ||
109 | void *zero_area; | ||
110 | |||
111 | /* | ||
112 | * Used to keep track of which metadata area the data in | ||
113 | * 'chunk' refers to. | ||
114 | */ | ||
115 | chunk_t current_area; | ||
116 | |||
117 | /* | ||
118 | * The next free chunk for an exception. | ||
119 | */ | ||
120 | chunk_t next_free; | ||
121 | |||
122 | /* | ||
123 | * The index of next free exception in the current | ||
124 | * metadata area. | ||
125 | */ | ||
126 | uint32_t current_committed; | ||
127 | |||
128 | atomic_t pending_count; | ||
129 | uint32_t callback_count; | ||
130 | struct commit_callback *callbacks; | ||
131 | struct dm_io_client *io_client; | ||
132 | |||
133 | struct workqueue_struct *metadata_wq; | ||
134 | }; | ||
135 | |||
136 | static unsigned sectors_to_pages(unsigned sectors) | ||
137 | { | ||
138 | return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9); | ||
139 | } | ||
140 | |||
141 | static int alloc_area(struct pstore *ps) | ||
142 | { | ||
143 | int r = -ENOMEM; | ||
144 | size_t len; | ||
145 | |||
146 | len = ps->snap->chunk_size << SECTOR_SHIFT; | ||
147 | |||
148 | /* | ||
149 | * Allocate the chunk_size block of memory that will hold | ||
150 | * a single metadata area. | ||
151 | */ | ||
152 | ps->area = vmalloc(len); | ||
153 | if (!ps->area) | ||
154 | return r; | ||
155 | |||
156 | ps->zero_area = vmalloc(len); | ||
157 | if (!ps->zero_area) { | ||
158 | vfree(ps->area); | ||
159 | return r; | ||
160 | } | ||
161 | memset(ps->zero_area, 0, len); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static void free_area(struct pstore *ps) | ||
167 | { | ||
168 | vfree(ps->area); | ||
169 | ps->area = NULL; | ||
170 | vfree(ps->zero_area); | ||
171 | ps->zero_area = NULL; | ||
172 | } | ||
173 | |||
174 | struct mdata_req { | ||
175 | struct dm_io_region *where; | ||
176 | struct dm_io_request *io_req; | ||
177 | struct work_struct work; | ||
178 | int result; | ||
179 | }; | ||
180 | |||
181 | static void do_metadata(struct work_struct *work) | ||
182 | { | ||
183 | struct mdata_req *req = container_of(work, struct mdata_req, work); | ||
184 | |||
185 | req->result = dm_io(req->io_req, 1, req->where, NULL); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Read or write a chunk aligned and sized block of data from a device. | ||
190 | */ | ||
191 | static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata) | ||
192 | { | ||
193 | struct dm_io_region where = { | ||
194 | .bdev = ps->snap->cow->bdev, | ||
195 | .sector = ps->snap->chunk_size * chunk, | ||
196 | .count = ps->snap->chunk_size, | ||
197 | }; | ||
198 | struct dm_io_request io_req = { | ||
199 | .bi_rw = rw, | ||
200 | .mem.type = DM_IO_VMA, | ||
201 | .mem.ptr.vma = ps->area, | ||
202 | .client = ps->io_client, | ||
203 | .notify.fn = NULL, | ||
204 | }; | ||
205 | struct mdata_req req; | ||
206 | |||
207 | if (!metadata) | ||
208 | return dm_io(&io_req, 1, &where, NULL); | ||
209 | |||
210 | req.where = &where; | ||
211 | req.io_req = &io_req; | ||
212 | |||
213 | /* | ||
214 | * Issue the synchronous I/O from a different thread | ||
215 | * to avoid generic_make_request recursion. | ||
216 | */ | ||
217 | INIT_WORK(&req.work, do_metadata); | ||
218 | queue_work(ps->metadata_wq, &req.work); | ||
219 | flush_workqueue(ps->metadata_wq); | ||
220 | |||
221 | return req.result; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Convert a metadata area index to a chunk index. | ||
226 | */ | ||
227 | static chunk_t area_location(struct pstore *ps, chunk_t area) | ||
228 | { | ||
229 | return 1 + ((ps->exceptions_per_area + 1) * area); | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * Read or write a metadata area. Remembering to skip the first | ||
234 | * chunk which holds the header. | ||
235 | */ | ||
236 | static int area_io(struct pstore *ps, int rw) | ||
237 | { | ||
238 | int r; | ||
239 | chunk_t chunk; | ||
240 | |||
241 | chunk = area_location(ps, ps->current_area); | ||
242 | |||
243 | r = chunk_io(ps, chunk, rw, 0); | ||
244 | if (r) | ||
245 | return r; | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static void zero_memory_area(struct pstore *ps) | ||
251 | { | ||
252 | memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); | ||
253 | } | ||
254 | |||
255 | static int zero_disk_area(struct pstore *ps, chunk_t area) | ||
256 | { | ||
257 | struct dm_io_region where = { | ||
258 | .bdev = ps->snap->cow->bdev, | ||
259 | .sector = ps->snap->chunk_size * area_location(ps, area), | ||
260 | .count = ps->snap->chunk_size, | ||
261 | }; | ||
262 | struct dm_io_request io_req = { | ||
263 | .bi_rw = WRITE, | ||
264 | .mem.type = DM_IO_VMA, | ||
265 | .mem.ptr.vma = ps->zero_area, | ||
266 | .client = ps->io_client, | ||
267 | .notify.fn = NULL, | ||
268 | }; | ||
269 | |||
270 | return dm_io(&io_req, 1, &where, NULL); | ||
271 | } | ||
272 | |||
273 | static int read_header(struct pstore *ps, int *new_snapshot) | ||
274 | { | ||
275 | int r; | ||
276 | struct disk_header *dh; | ||
277 | chunk_t chunk_size; | ||
278 | int chunk_size_supplied = 1; | ||
279 | |||
280 | /* | ||
281 | * Use default chunk size (or hardsect_size, if larger) if none supplied | ||
282 | */ | ||
283 | if (!ps->snap->chunk_size) { | ||
284 | ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, | ||
285 | bdev_hardsect_size(ps->snap->cow->bdev) >> 9); | ||
286 | ps->snap->chunk_mask = ps->snap->chunk_size - 1; | ||
287 | ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1; | ||
288 | chunk_size_supplied = 0; | ||
289 | } | ||
290 | |||
291 | ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap-> | ||
292 | chunk_size)); | ||
293 | if (IS_ERR(ps->io_client)) | ||
294 | return PTR_ERR(ps->io_client); | ||
295 | |||
296 | r = alloc_area(ps); | ||
297 | if (r) | ||
298 | return r; | ||
299 | |||
300 | r = chunk_io(ps, 0, READ, 1); | ||
301 | if (r) | ||
302 | goto bad; | ||
303 | |||
304 | dh = (struct disk_header *) ps->area; | ||
305 | |||
306 | if (le32_to_cpu(dh->magic) == 0) { | ||
307 | *new_snapshot = 1; | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | if (le32_to_cpu(dh->magic) != SNAP_MAGIC) { | ||
312 | DMWARN("Invalid or corrupt snapshot"); | ||
313 | r = -ENXIO; | ||
314 | goto bad; | ||
315 | } | ||
316 | |||
317 | *new_snapshot = 0; | ||
318 | ps->valid = le32_to_cpu(dh->valid); | ||
319 | ps->version = le32_to_cpu(dh->version); | ||
320 | chunk_size = le32_to_cpu(dh->chunk_size); | ||
321 | |||
322 | if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size) | ||
323 | return 0; | ||
324 | |||
325 | DMWARN("chunk size %llu in device metadata overrides " | ||
326 | "table chunk size of %llu.", | ||
327 | (unsigned long long)chunk_size, | ||
328 | (unsigned long long)ps->snap->chunk_size); | ||
329 | |||
330 | /* We had a bogus chunk_size. Fix stuff up. */ | ||
331 | free_area(ps); | ||
332 | |||
333 | ps->snap->chunk_size = chunk_size; | ||
334 | ps->snap->chunk_mask = chunk_size - 1; | ||
335 | ps->snap->chunk_shift = ffs(chunk_size) - 1; | ||
336 | |||
337 | r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size), | ||
338 | ps->io_client); | ||
339 | if (r) | ||
340 | return r; | ||
341 | |||
342 | r = alloc_area(ps); | ||
343 | return r; | ||
344 | |||
345 | bad: | ||
346 | free_area(ps); | ||
347 | return r; | ||
348 | } | ||
349 | |||
350 | static int write_header(struct pstore *ps) | ||
351 | { | ||
352 | struct disk_header *dh; | ||
353 | |||
354 | memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); | ||
355 | |||
356 | dh = (struct disk_header *) ps->area; | ||
357 | dh->magic = cpu_to_le32(SNAP_MAGIC); | ||
358 | dh->valid = cpu_to_le32(ps->valid); | ||
359 | dh->version = cpu_to_le32(ps->version); | ||
360 | dh->chunk_size = cpu_to_le32(ps->snap->chunk_size); | ||
361 | |||
362 | return chunk_io(ps, 0, WRITE, 1); | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * Access functions for the disk exceptions, these do the endian conversions. | ||
367 | */ | ||
368 | static struct disk_exception *get_exception(struct pstore *ps, uint32_t index) | ||
369 | { | ||
370 | BUG_ON(index >= ps->exceptions_per_area); | ||
371 | |||
372 | return ((struct disk_exception *) ps->area) + index; | ||
373 | } | ||
374 | 14 | ||
375 | static void read_exception(struct pstore *ps, | 15 | #define DM_MSG_PREFIX "snapshot exception stores" |
376 | uint32_t index, struct disk_exception *result) | ||
377 | { | ||
378 | struct disk_exception *e = get_exception(ps, index); | ||
379 | |||
380 | /* copy it */ | ||
381 | result->old_chunk = le64_to_cpu(e->old_chunk); | ||
382 | result->new_chunk = le64_to_cpu(e->new_chunk); | ||
383 | } | ||
384 | |||
385 | static void write_exception(struct pstore *ps, | ||
386 | uint32_t index, struct disk_exception *de) | ||
387 | { | ||
388 | struct disk_exception *e = get_exception(ps, index); | ||
389 | |||
390 | /* copy it */ | ||
391 | e->old_chunk = cpu_to_le64(de->old_chunk); | ||
392 | e->new_chunk = cpu_to_le64(de->new_chunk); | ||
393 | } | ||
394 | 16 | ||
395 | /* | 17 | int dm_exception_store_init(void) |
396 | * Registers the exceptions that are present in the current area. | ||
397 | * 'full' is filled in to indicate if the area has been | ||
398 | * filled. | ||
399 | */ | ||
400 | static int insert_exceptions(struct pstore *ps, int *full) | ||
401 | { | 18 | { |
402 | int r; | 19 | int r; |
403 | unsigned int i; | ||
404 | struct disk_exception de; | ||
405 | |||
406 | /* presume the area is full */ | ||
407 | *full = 1; | ||
408 | |||
409 | for (i = 0; i < ps->exceptions_per_area; i++) { | ||
410 | read_exception(ps, i, &de); | ||
411 | |||
412 | /* | ||
413 | * If the new_chunk is pointing at the start of | ||
414 | * the COW device, where the first metadata area | ||
415 | * is we know that we've hit the end of the | ||
416 | * exceptions. Therefore the area is not full. | ||
417 | */ | ||
418 | if (de.new_chunk == 0LL) { | ||
419 | ps->current_committed = i; | ||
420 | *full = 0; | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * Keep track of the start of the free chunks. | ||
426 | */ | ||
427 | if (ps->next_free <= de.new_chunk) | ||
428 | ps->next_free = de.new_chunk + 1; | ||
429 | |||
430 | /* | ||
431 | * Otherwise we add the exception to the snapshot. | ||
432 | */ | ||
433 | r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk); | ||
434 | if (r) | ||
435 | return r; | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int read_exceptions(struct pstore *ps) | ||
442 | { | ||
443 | int r, full = 1; | ||
444 | |||
445 | /* | ||
446 | * Keeping reading chunks and inserting exceptions until | ||
447 | * we find a partially full area. | ||
448 | */ | ||
449 | for (ps->current_area = 0; full; ps->current_area++) { | ||
450 | r = area_io(ps, READ); | ||
451 | if (r) | ||
452 | return r; | ||
453 | 20 | ||
454 | r = insert_exceptions(ps, &full); | 21 | r = dm_transient_snapshot_init(); |
455 | if (r) | 22 | if (r) { |
456 | return r; | 23 | DMERR("Unable to register transient exception store type."); |
24 | goto transient_fail; | ||
457 | } | 25 | } |
458 | 26 | ||
459 | ps->current_area--; | 27 | r = dm_persistent_snapshot_init(); |
460 | 28 | if (r) { | |
461 | return 0; | 29 | DMERR("Unable to register persistent exception store type"); |
462 | } | 30 | goto persistent_fail; |
463 | |||
464 | static struct pstore *get_info(struct exception_store *store) | ||
465 | { | ||
466 | return (struct pstore *) store->context; | ||
467 | } | ||
468 | |||
469 | static void persistent_fraction_full(struct exception_store *store, | ||
470 | sector_t *numerator, sector_t *denominator) | ||
471 | { | ||
472 | *numerator = get_info(store)->next_free * store->snap->chunk_size; | ||
473 | *denominator = get_dev_size(store->snap->cow->bdev); | ||
474 | } | ||
475 | |||
476 | static void persistent_destroy(struct exception_store *store) | ||
477 | { | ||
478 | struct pstore *ps = get_info(store); | ||
479 | |||
480 | destroy_workqueue(ps->metadata_wq); | ||
481 | dm_io_client_destroy(ps->io_client); | ||
482 | vfree(ps->callbacks); | ||
483 | free_area(ps); | ||
484 | kfree(ps); | ||
485 | } | ||
486 | |||
487 | static int persistent_read_metadata(struct exception_store *store) | ||
488 | { | ||
489 | int r, uninitialized_var(new_snapshot); | ||
490 | struct pstore *ps = get_info(store); | ||
491 | |||
492 | /* | ||
493 | * Read the snapshot header. | ||
494 | */ | ||
495 | r = read_header(ps, &new_snapshot); | ||
496 | if (r) | ||
497 | return r; | ||
498 | |||
499 | /* | ||
500 | * Now we know correct chunk_size, complete the initialisation. | ||
501 | */ | ||
502 | ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) / | ||
503 | sizeof(struct disk_exception); | ||
504 | ps->callbacks = dm_vcalloc(ps->exceptions_per_area, | ||
505 | sizeof(*ps->callbacks)); | ||
506 | if (!ps->callbacks) | ||
507 | return -ENOMEM; | ||
508 | |||
509 | /* | ||
510 | * Do we need to setup a new snapshot ? | ||
511 | */ | ||
512 | if (new_snapshot) { | ||
513 | r = write_header(ps); | ||
514 | if (r) { | ||
515 | DMWARN("write_header failed"); | ||
516 | return r; | ||
517 | } | ||
518 | |||
519 | ps->current_area = 0; | ||
520 | zero_memory_area(ps); | ||
521 | r = zero_disk_area(ps, 0); | ||
522 | if (r) { | ||
523 | DMWARN("zero_disk_area(0) failed"); | ||
524 | return r; | ||
525 | } | ||
526 | } else { | ||
527 | /* | ||
528 | * Sanity checks. | ||
529 | */ | ||
530 | if (ps->version != SNAPSHOT_DISK_VERSION) { | ||
531 | DMWARN("unable to handle snapshot disk version %d", | ||
532 | ps->version); | ||
533 | return -EINVAL; | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Metadata are valid, but snapshot is invalidated | ||
538 | */ | ||
539 | if (!ps->valid) | ||
540 | return 1; | ||
541 | |||
542 | /* | ||
543 | * Read the metadata. | ||
544 | */ | ||
545 | r = read_exceptions(ps); | ||
546 | if (r) | ||
547 | return r; | ||
548 | } | 31 | } |
549 | 32 | ||
550 | return 0; | 33 | return 0; |
551 | } | ||
552 | |||
553 | static int persistent_prepare(struct exception_store *store, | ||
554 | struct dm_snap_exception *e) | ||
555 | { | ||
556 | struct pstore *ps = get_info(store); | ||
557 | uint32_t stride; | ||
558 | chunk_t next_free; | ||
559 | sector_t size = get_dev_size(store->snap->cow->bdev); | ||
560 | |||
561 | /* Is there enough room ? */ | ||
562 | if (size < ((ps->next_free + 1) * store->snap->chunk_size)) | ||
563 | return -ENOSPC; | ||
564 | 34 | ||
565 | e->new_chunk = ps->next_free; | 35 | persistent_fail: |
566 | 36 | dm_persistent_snapshot_exit(); | |
567 | /* | 37 | transient_fail: |
568 | * Move onto the next free pending, making sure to take | 38 | return r; |
569 | * into account the location of the metadata chunks. | ||
570 | */ | ||
571 | stride = (ps->exceptions_per_area + 1); | ||
572 | next_free = ++ps->next_free; | ||
573 | if (sector_div(next_free, stride) == 1) | ||
574 | ps->next_free++; | ||
575 | |||
576 | atomic_inc(&ps->pending_count); | ||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | static void persistent_commit(struct exception_store *store, | ||
581 | struct dm_snap_exception *e, | ||
582 | void (*callback) (void *, int success), | ||
583 | void *callback_context) | ||
584 | { | ||
585 | unsigned int i; | ||
586 | struct pstore *ps = get_info(store); | ||
587 | struct disk_exception de; | ||
588 | struct commit_callback *cb; | ||
589 | |||
590 | de.old_chunk = e->old_chunk; | ||
591 | de.new_chunk = e->new_chunk; | ||
592 | write_exception(ps, ps->current_committed++, &de); | ||
593 | |||
594 | /* | ||
595 | * Add the callback to the back of the array. This code | ||
596 | * is the only place where the callback array is | ||
597 | * manipulated, and we know that it will never be called | ||
598 | * multiple times concurrently. | ||
599 | */ | ||
600 | cb = ps->callbacks + ps->callback_count++; | ||
601 | cb->callback = callback; | ||
602 | cb->context = callback_context; | ||
603 | |||
604 | /* | ||
605 | * If there are exceptions in flight and we have not yet | ||
606 | * filled this metadata area there's nothing more to do. | ||
607 | */ | ||
608 | if (!atomic_dec_and_test(&ps->pending_count) && | ||
609 | (ps->current_committed != ps->exceptions_per_area)) | ||
610 | return; | ||
611 | |||
612 | /* | ||
613 | * If we completely filled the current area, then wipe the next one. | ||
614 | */ | ||
615 | if ((ps->current_committed == ps->exceptions_per_area) && | ||
616 | zero_disk_area(ps, ps->current_area + 1)) | ||
617 | ps->valid = 0; | ||
618 | |||
619 | /* | ||
620 | * Commit exceptions to disk. | ||
621 | */ | ||
622 | if (ps->valid && area_io(ps, WRITE)) | ||
623 | ps->valid = 0; | ||
624 | |||
625 | /* | ||
626 | * Advance to the next area if this one is full. | ||
627 | */ | ||
628 | if (ps->current_committed == ps->exceptions_per_area) { | ||
629 | ps->current_committed = 0; | ||
630 | ps->current_area++; | ||
631 | zero_memory_area(ps); | ||
632 | } | ||
633 | |||
634 | for (i = 0; i < ps->callback_count; i++) { | ||
635 | cb = ps->callbacks + i; | ||
636 | cb->callback(cb->context, ps->valid); | ||
637 | } | ||
638 | |||
639 | ps->callback_count = 0; | ||
640 | } | ||
641 | |||
642 | static void persistent_drop(struct exception_store *store) | ||
643 | { | ||
644 | struct pstore *ps = get_info(store); | ||
645 | |||
646 | ps->valid = 0; | ||
647 | if (write_header(ps)) | ||
648 | DMWARN("write header failed"); | ||
649 | } | ||
650 | |||
651 | int dm_create_persistent(struct exception_store *store) | ||
652 | { | ||
653 | struct pstore *ps; | ||
654 | |||
655 | /* allocate the pstore */ | ||
656 | ps = kmalloc(sizeof(*ps), GFP_KERNEL); | ||
657 | if (!ps) | ||
658 | return -ENOMEM; | ||
659 | |||
660 | ps->snap = store->snap; | ||
661 | ps->valid = 1; | ||
662 | ps->version = SNAPSHOT_DISK_VERSION; | ||
663 | ps->area = NULL; | ||
664 | ps->next_free = 2; /* skipping the header and first area */ | ||
665 | ps->current_committed = 0; | ||
666 | |||
667 | ps->callback_count = 0; | ||
668 | atomic_set(&ps->pending_count, 0); | ||
669 | ps->callbacks = NULL; | ||
670 | |||
671 | ps->metadata_wq = create_singlethread_workqueue("ksnaphd"); | ||
672 | if (!ps->metadata_wq) { | ||
673 | kfree(ps); | ||
674 | DMERR("couldn't start header metadata update thread"); | ||
675 | return -ENOMEM; | ||
676 | } | ||
677 | |||
678 | store->destroy = persistent_destroy; | ||
679 | store->read_metadata = persistent_read_metadata; | ||
680 | store->prepare_exception = persistent_prepare; | ||
681 | store->commit_exception = persistent_commit; | ||
682 | store->drop_snapshot = persistent_drop; | ||
683 | store->fraction_full = persistent_fraction_full; | ||
684 | store->context = ps; | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | /*----------------------------------------------------------------- | ||
690 | * Implementation of the store for non-persistent snapshots. | ||
691 | *---------------------------------------------------------------*/ | ||
692 | struct transient_c { | ||
693 | sector_t next_free; | ||
694 | }; | ||
695 | |||
696 | static void transient_destroy(struct exception_store *store) | ||
697 | { | ||
698 | kfree(store->context); | ||
699 | } | ||
700 | |||
701 | static int transient_read_metadata(struct exception_store *store) | ||
702 | { | ||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | static int transient_prepare(struct exception_store *store, | ||
707 | struct dm_snap_exception *e) | ||
708 | { | ||
709 | struct transient_c *tc = (struct transient_c *) store->context; | ||
710 | sector_t size = get_dev_size(store->snap->cow->bdev); | ||
711 | |||
712 | if (size < (tc->next_free + store->snap->chunk_size)) | ||
713 | return -1; | ||
714 | |||
715 | e->new_chunk = sector_to_chunk(store->snap, tc->next_free); | ||
716 | tc->next_free += store->snap->chunk_size; | ||
717 | |||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static void transient_commit(struct exception_store *store, | ||
722 | struct dm_snap_exception *e, | ||
723 | void (*callback) (void *, int success), | ||
724 | void *callback_context) | ||
725 | { | ||
726 | /* Just succeed */ | ||
727 | callback(callback_context, 1); | ||
728 | } | ||
729 | |||
730 | static void transient_fraction_full(struct exception_store *store, | ||
731 | sector_t *numerator, sector_t *denominator) | ||
732 | { | ||
733 | *numerator = ((struct transient_c *) store->context)->next_free; | ||
734 | *denominator = get_dev_size(store->snap->cow->bdev); | ||
735 | } | 39 | } |
736 | 40 | ||
737 | int dm_create_transient(struct exception_store *store) | 41 | void dm_exception_store_exit(void) |
738 | { | 42 | { |
739 | struct transient_c *tc; | 43 | dm_persistent_snapshot_exit(); |
740 | 44 | dm_transient_snapshot_exit(); | |
741 | store->destroy = transient_destroy; | ||
742 | store->read_metadata = transient_read_metadata; | ||
743 | store->prepare_exception = transient_prepare; | ||
744 | store->commit_exception = transient_commit; | ||
745 | store->drop_snapshot = NULL; | ||
746 | store->fraction_full = transient_fraction_full; | ||
747 | |||
748 | tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); | ||
749 | if (!tc) | ||
750 | return -ENOMEM; | ||
751 | |||
752 | tc->next_free = 0; | ||
753 | store->context = tc; | ||
754 | |||
755 | return 0; | ||
756 | } | 45 | } |
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h new file mode 100644 index 000000000000..bb9f33d5daa2 --- /dev/null +++ b/drivers/md/dm-exception-store.h | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. | ||
3 | * Copyright (C) 2008 Red Hat, Inc. All rights reserved. | ||
4 | * | ||
5 | * Device-mapper snapshot exception store. | ||
6 | * | ||
7 | * This file is released under the GPL. | ||
8 | */ | ||
9 | |||
10 | #ifndef _LINUX_DM_EXCEPTION_STORE | ||
11 | #define _LINUX_DM_EXCEPTION_STORE | ||
12 | |||
13 | #include <linux/blkdev.h> | ||
14 | #include <linux/device-mapper.h> | ||
15 | |||
16 | /* | ||
17 | * The snapshot code deals with largish chunks of the disk at a | ||
18 | * time. Typically 32k - 512k. | ||
19 | */ | ||
20 | typedef sector_t chunk_t; | ||
21 | |||
22 | /* | ||
23 | * An exception is used where an old chunk of data has been | ||
24 | * replaced by a new one. | ||
25 | * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number | ||
26 | * of chunks that follow contiguously. Remaining bits hold the number of the | ||
27 | * chunk within the device. | ||
28 | */ | ||
29 | struct dm_snap_exception { | ||
30 | struct list_head hash_list; | ||
31 | |||
32 | chunk_t old_chunk; | ||
33 | chunk_t new_chunk; | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Abstraction to handle the meta/layout of exception stores (the | ||
38 | * COW device). | ||
39 | */ | ||
40 | struct dm_exception_store { | ||
41 | /* | ||
42 | * Destroys this object when you've finished with it. | ||
43 | */ | ||
44 | void (*destroy) (struct dm_exception_store *store); | ||
45 | |||
46 | /* | ||
47 | * The target shouldn't read the COW device until this is | ||
48 | * called. As exceptions are read from the COW, they are | ||
49 | * reported back via the callback. | ||
50 | */ | ||
51 | int (*read_metadata) (struct dm_exception_store *store, | ||
52 | int (*callback)(void *callback_context, | ||
53 | chunk_t old, chunk_t new), | ||
54 | void *callback_context); | ||
55 | |||
56 | /* | ||
57 | * Find somewhere to store the next exception. | ||
58 | */ | ||
59 | int (*prepare_exception) (struct dm_exception_store *store, | ||
60 | struct dm_snap_exception *e); | ||
61 | |||
62 | /* | ||
63 | * Update the metadata with this exception. | ||
64 | */ | ||
65 | void (*commit_exception) (struct dm_exception_store *store, | ||
66 | struct dm_snap_exception *e, | ||
67 | void (*callback) (void *, int success), | ||
68 | void *callback_context); | ||
69 | |||
70 | /* | ||
71 | * The snapshot is invalid, note this in the metadata. | ||
72 | */ | ||
73 | void (*drop_snapshot) (struct dm_exception_store *store); | ||
74 | |||
75 | int (*status) (struct dm_exception_store *store, status_type_t status, | ||
76 | char *result, unsigned int maxlen); | ||
77 | |||
78 | /* | ||
79 | * Return how full the snapshot is. | ||
80 | */ | ||
81 | void (*fraction_full) (struct dm_exception_store *store, | ||
82 | sector_t *numerator, | ||
83 | sector_t *denominator); | ||
84 | |||
85 | struct dm_snapshot *snap; | ||
86 | void *context; | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * Funtions to manipulate consecutive chunks | ||
91 | */ | ||
92 | # if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) | ||
93 | # define DM_CHUNK_CONSECUTIVE_BITS 8 | ||
94 | # define DM_CHUNK_NUMBER_BITS 56 | ||
95 | |||
96 | static inline chunk_t dm_chunk_number(chunk_t chunk) | ||
97 | { | ||
98 | return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); | ||
99 | } | ||
100 | |||
101 | static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) | ||
102 | { | ||
103 | return e->new_chunk >> DM_CHUNK_NUMBER_BITS; | ||
104 | } | ||
105 | |||
106 | static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) | ||
107 | { | ||
108 | e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); | ||
109 | |||
110 | BUG_ON(!dm_consecutive_chunk_count(e)); | ||
111 | } | ||
112 | |||
113 | # else | ||
114 | # define DM_CHUNK_CONSECUTIVE_BITS 0 | ||
115 | |||
116 | static inline chunk_t dm_chunk_number(chunk_t chunk) | ||
117 | { | ||
118 | return chunk; | ||
119 | } | ||
120 | |||
121 | static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) | ||
122 | { | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | # endif | ||
131 | |||
132 | int dm_exception_store_init(void); | ||
133 | void dm_exception_store_exit(void); | ||
134 | |||
135 | /* | ||
136 | * Two exception store implementations. | ||
137 | */ | ||
138 | int dm_persistent_snapshot_init(void); | ||
139 | void dm_persistent_snapshot_exit(void); | ||
140 | |||
141 | int dm_transient_snapshot_init(void); | ||
142 | void dm_transient_snapshot_exit(void); | ||
143 | |||
144 | int dm_create_persistent(struct dm_exception_store *store); | ||
145 | |||
146 | int dm_create_transient(struct dm_exception_store *store); | ||
147 | |||
148 | #endif /* _LINUX_DM_EXCEPTION_STORE */ | ||
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 777c948180f9..54d0588fc1f6 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -233,7 +233,7 @@ static void __hash_remove(struct hash_cell *hc) | |||
233 | } | 233 | } |
234 | 234 | ||
235 | if (hc->new_map) | 235 | if (hc->new_map) |
236 | dm_table_put(hc->new_map); | 236 | dm_table_destroy(hc->new_map); |
237 | dm_put(hc->md); | 237 | dm_put(hc->md); |
238 | free_cell(hc); | 238 | free_cell(hc); |
239 | } | 239 | } |
@@ -827,8 +827,8 @@ static int do_resume(struct dm_ioctl *param) | |||
827 | 827 | ||
828 | r = dm_swap_table(md, new_map); | 828 | r = dm_swap_table(md, new_map); |
829 | if (r) { | 829 | if (r) { |
830 | dm_table_destroy(new_map); | ||
830 | dm_put(md); | 831 | dm_put(md); |
831 | dm_table_put(new_map); | ||
832 | return r; | 832 | return r; |
833 | } | 833 | } |
834 | 834 | ||
@@ -836,8 +836,6 @@ static int do_resume(struct dm_ioctl *param) | |||
836 | set_disk_ro(dm_disk(md), 0); | 836 | set_disk_ro(dm_disk(md), 0); |
837 | else | 837 | else |
838 | set_disk_ro(dm_disk(md), 1); | 838 | set_disk_ro(dm_disk(md), 1); |
839 | |||
840 | dm_table_put(new_map); | ||
841 | } | 839 | } |
842 | 840 | ||
843 | if (dm_suspended(md)) | 841 | if (dm_suspended(md)) |
@@ -1080,7 +1078,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
1080 | } | 1078 | } |
1081 | 1079 | ||
1082 | if (hc->new_map) | 1080 | if (hc->new_map) |
1083 | dm_table_put(hc->new_map); | 1081 | dm_table_destroy(hc->new_map); |
1084 | hc->new_map = t; | 1082 | hc->new_map = t; |
1085 | up_write(&_hash_lock); | 1083 | up_write(&_hash_lock); |
1086 | 1084 | ||
@@ -1109,7 +1107,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size) | |||
1109 | } | 1107 | } |
1110 | 1108 | ||
1111 | if (hc->new_map) { | 1109 | if (hc->new_map) { |
1112 | dm_table_put(hc->new_map); | 1110 | dm_table_destroy(hc->new_map); |
1113 | hc->new_map = NULL; | 1111 | hc->new_map = NULL; |
1114 | } | 1112 | } |
1115 | 1113 | ||
@@ -1550,8 +1548,10 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid) | |||
1550 | goto out; | 1548 | goto out; |
1551 | } | 1549 | } |
1552 | 1550 | ||
1553 | strcpy(name, hc->name); | 1551 | if (name) |
1554 | strcpy(uuid, hc->uuid ? : ""); | 1552 | strcpy(name, hc->name); |
1553 | if (uuid) | ||
1554 | strcpy(uuid, hc->uuid ? : ""); | ||
1555 | 1555 | ||
1556 | out: | 1556 | out: |
1557 | up_read(&_hash_lock); | 1557 | up_read(&_hash_lock); |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 44042becad8a..bfa107f59d96 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
@@ -142,6 +142,7 @@ static struct target_type linear_target = { | |||
142 | .status = linear_status, | 142 | .status = linear_status, |
143 | .ioctl = linear_ioctl, | 143 | .ioctl = linear_ioctl, |
144 | .merge = linear_merge, | 144 | .merge = linear_merge, |
145 | .features = DM_TARGET_SUPPORTS_BARRIERS, | ||
145 | }; | 146 | }; |
146 | 147 | ||
147 | int __init dm_linear_init(void) | 148 | int __init dm_linear_init(void) |
@@ -156,8 +157,5 @@ int __init dm_linear_init(void) | |||
156 | 157 | ||
157 | void dm_linear_exit(void) | 158 | void dm_linear_exit(void) |
158 | { | 159 | { |
159 | int r = dm_unregister_target(&linear_target); | 160 | dm_unregister_target(&linear_target); |
160 | |||
161 | if (r < 0) | ||
162 | DMERR("unregister failed %d", r); | ||
163 | } | 161 | } |
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index a8c0fc79ca78..737961f275c1 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -326,8 +326,6 @@ static void header_from_disk(struct log_header *core, struct log_header *disk) | |||
326 | static int rw_header(struct log_c *lc, int rw) | 326 | static int rw_header(struct log_c *lc, int rw) |
327 | { | 327 | { |
328 | lc->io_req.bi_rw = rw; | 328 | lc->io_req.bi_rw = rw; |
329 | lc->io_req.mem.ptr.vma = lc->disk_header; | ||
330 | lc->io_req.notify.fn = NULL; | ||
331 | 329 | ||
332 | return dm_io(&lc->io_req, 1, &lc->header_location, NULL); | 330 | return dm_io(&lc->io_req, 1, &lc->header_location, NULL); |
333 | } | 331 | } |
@@ -362,10 +360,15 @@ static int read_header(struct log_c *log) | |||
362 | return 0; | 360 | return 0; |
363 | } | 361 | } |
364 | 362 | ||
365 | static inline int write_header(struct log_c *log) | 363 | static int _check_region_size(struct dm_target *ti, uint32_t region_size) |
366 | { | 364 | { |
367 | header_to_disk(&log->header, log->disk_header); | 365 | if (region_size < 2 || region_size > ti->len) |
368 | return rw_header(log, WRITE); | 366 | return 0; |
367 | |||
368 | if (!is_power_of_2(region_size)) | ||
369 | return 0; | ||
370 | |||
371 | return 1; | ||
369 | } | 372 | } |
370 | 373 | ||
371 | /*---------------------------------------------------------------- | 374 | /*---------------------------------------------------------------- |
@@ -403,8 +406,9 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
403 | } | 406 | } |
404 | } | 407 | } |
405 | 408 | ||
406 | if (sscanf(argv[0], "%u", ®ion_size) != 1) { | 409 | if (sscanf(argv[0], "%u", ®ion_size) != 1 || |
407 | DMWARN("invalid region size string"); | 410 | !_check_region_size(ti, region_size)) { |
411 | DMWARN("invalid region size %s", argv[0]); | ||
408 | return -EINVAL; | 412 | return -EINVAL; |
409 | } | 413 | } |
410 | 414 | ||
@@ -453,8 +457,18 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
453 | */ | 457 | */ |
454 | buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + | 458 | buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + |
455 | bitset_size, ti->limits.hardsect_size); | 459 | bitset_size, ti->limits.hardsect_size); |
460 | |||
461 | if (buf_size > dev->bdev->bd_inode->i_size) { | ||
462 | DMWARN("log device %s too small: need %llu bytes", | ||
463 | dev->name, (unsigned long long)buf_size); | ||
464 | kfree(lc); | ||
465 | return -EINVAL; | ||
466 | } | ||
467 | |||
456 | lc->header_location.count = buf_size >> SECTOR_SHIFT; | 468 | lc->header_location.count = buf_size >> SECTOR_SHIFT; |
469 | |||
457 | lc->io_req.mem.type = DM_IO_VMA; | 470 | lc->io_req.mem.type = DM_IO_VMA; |
471 | lc->io_req.notify.fn = NULL; | ||
458 | lc->io_req.client = dm_io_client_create(dm_div_up(buf_size, | 472 | lc->io_req.client = dm_io_client_create(dm_div_up(buf_size, |
459 | PAGE_SIZE)); | 473 | PAGE_SIZE)); |
460 | if (IS_ERR(lc->io_req.client)) { | 474 | if (IS_ERR(lc->io_req.client)) { |
@@ -467,10 +481,12 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
467 | lc->disk_header = vmalloc(buf_size); | 481 | lc->disk_header = vmalloc(buf_size); |
468 | if (!lc->disk_header) { | 482 | if (!lc->disk_header) { |
469 | DMWARN("couldn't allocate disk log buffer"); | 483 | DMWARN("couldn't allocate disk log buffer"); |
484 | dm_io_client_destroy(lc->io_req.client); | ||
470 | kfree(lc); | 485 | kfree(lc); |
471 | return -ENOMEM; | 486 | return -ENOMEM; |
472 | } | 487 | } |
473 | 488 | ||
489 | lc->io_req.mem.ptr.vma = lc->disk_header; | ||
474 | lc->clean_bits = (void *)lc->disk_header + | 490 | lc->clean_bits = (void *)lc->disk_header + |
475 | (LOG_OFFSET << SECTOR_SHIFT); | 491 | (LOG_OFFSET << SECTOR_SHIFT); |
476 | } | 492 | } |
@@ -482,6 +498,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
482 | DMWARN("couldn't allocate sync bitset"); | 498 | DMWARN("couldn't allocate sync bitset"); |
483 | if (!dev) | 499 | if (!dev) |
484 | vfree(lc->clean_bits); | 500 | vfree(lc->clean_bits); |
501 | else | ||
502 | dm_io_client_destroy(lc->io_req.client); | ||
485 | vfree(lc->disk_header); | 503 | vfree(lc->disk_header); |
486 | kfree(lc); | 504 | kfree(lc); |
487 | return -ENOMEM; | 505 | return -ENOMEM; |
@@ -495,6 +513,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
495 | vfree(lc->sync_bits); | 513 | vfree(lc->sync_bits); |
496 | if (!dev) | 514 | if (!dev) |
497 | vfree(lc->clean_bits); | 515 | vfree(lc->clean_bits); |
516 | else | ||
517 | dm_io_client_destroy(lc->io_req.client); | ||
498 | vfree(lc->disk_header); | 518 | vfree(lc->disk_header); |
499 | kfree(lc); | 519 | kfree(lc); |
500 | return -ENOMEM; | 520 | return -ENOMEM; |
@@ -631,8 +651,10 @@ static int disk_resume(struct dm_dirty_log *log) | |||
631 | /* set the correct number of regions in the header */ | 651 | /* set the correct number of regions in the header */ |
632 | lc->header.nr_regions = lc->region_count; | 652 | lc->header.nr_regions = lc->region_count; |
633 | 653 | ||
654 | header_to_disk(&lc->header, lc->disk_header); | ||
655 | |||
634 | /* write the new header */ | 656 | /* write the new header */ |
635 | r = write_header(lc); | 657 | r = rw_header(lc, WRITE); |
636 | if (r) { | 658 | if (r) { |
637 | DMWARN("%s: Failed to write header on dirty region log device", | 659 | DMWARN("%s: Failed to write header on dirty region log device", |
638 | lc->log_dev->name); | 660 | lc->log_dev->name); |
@@ -682,7 +704,7 @@ static int disk_flush(struct dm_dirty_log *log) | |||
682 | if (!lc->touched) | 704 | if (!lc->touched) |
683 | return 0; | 705 | return 0; |
684 | 706 | ||
685 | r = write_header(lc); | 707 | r = rw_header(lc, WRITE); |
686 | if (r) | 708 | if (r) |
687 | fail_log_device(lc); | 709 | fail_log_device(lc); |
688 | else | 710 | else |
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 3d7f4923cd13..095f77bf9681 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -889,7 +889,7 @@ static int fail_path(struct pgpath *pgpath) | |||
889 | dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti, | 889 | dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti, |
890 | pgpath->path.dev->name, m->nr_valid_paths); | 890 | pgpath->path.dev->name, m->nr_valid_paths); |
891 | 891 | ||
892 | queue_work(kmultipathd, &m->trigger_event); | 892 | schedule_work(&m->trigger_event); |
893 | queue_work(kmultipathd, &pgpath->deactivate_path); | 893 | queue_work(kmultipathd, &pgpath->deactivate_path); |
894 | 894 | ||
895 | out: | 895 | out: |
@@ -932,7 +932,7 @@ static int reinstate_path(struct pgpath *pgpath) | |||
932 | dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, | 932 | dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti, |
933 | pgpath->path.dev->name, m->nr_valid_paths); | 933 | pgpath->path.dev->name, m->nr_valid_paths); |
934 | 934 | ||
935 | queue_work(kmultipathd, &m->trigger_event); | 935 | schedule_work(&m->trigger_event); |
936 | 936 | ||
937 | out: | 937 | out: |
938 | spin_unlock_irqrestore(&m->lock, flags); | 938 | spin_unlock_irqrestore(&m->lock, flags); |
@@ -976,7 +976,7 @@ static void bypass_pg(struct multipath *m, struct priority_group *pg, | |||
976 | 976 | ||
977 | spin_unlock_irqrestore(&m->lock, flags); | 977 | spin_unlock_irqrestore(&m->lock, flags); |
978 | 978 | ||
979 | queue_work(kmultipathd, &m->trigger_event); | 979 | schedule_work(&m->trigger_event); |
980 | } | 980 | } |
981 | 981 | ||
982 | /* | 982 | /* |
@@ -1006,7 +1006,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr) | |||
1006 | } | 1006 | } |
1007 | spin_unlock_irqrestore(&m->lock, flags); | 1007 | spin_unlock_irqrestore(&m->lock, flags); |
1008 | 1008 | ||
1009 | queue_work(kmultipathd, &m->trigger_event); | 1009 | schedule_work(&m->trigger_event); |
1010 | return 0; | 1010 | return 0; |
1011 | } | 1011 | } |
1012 | 1012 | ||
@@ -1495,14 +1495,10 @@ static int __init dm_multipath_init(void) | |||
1495 | 1495 | ||
1496 | static void __exit dm_multipath_exit(void) | 1496 | static void __exit dm_multipath_exit(void) |
1497 | { | 1497 | { |
1498 | int r; | ||
1499 | |||
1500 | destroy_workqueue(kmpath_handlerd); | 1498 | destroy_workqueue(kmpath_handlerd); |
1501 | destroy_workqueue(kmultipathd); | 1499 | destroy_workqueue(kmultipathd); |
1502 | 1500 | ||
1503 | r = dm_unregister_target(&multipath_target); | 1501 | dm_unregister_target(&multipath_target); |
1504 | if (r < 0) | ||
1505 | DMERR("target unregister failed %d", r); | ||
1506 | kmem_cache_destroy(_mpio_cache); | 1502 | kmem_cache_destroy(_mpio_cache); |
1507 | } | 1503 | } |
1508 | 1504 | ||
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index ec43f9fa4b2a..4d6bc101962e 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -197,9 +197,6 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type) | |||
197 | struct mirror_set *ms = m->ms; | 197 | struct mirror_set *ms = m->ms; |
198 | struct mirror *new; | 198 | struct mirror *new; |
199 | 199 | ||
200 | if (!errors_handled(ms)) | ||
201 | return; | ||
202 | |||
203 | /* | 200 | /* |
204 | * error_count is used for nothing more than a | 201 | * error_count is used for nothing more than a |
205 | * simple way to tell if a device has encountered | 202 | * simple way to tell if a device has encountered |
@@ -210,6 +207,9 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type) | |||
210 | if (test_and_set_bit(error_type, &m->error_type)) | 207 | if (test_and_set_bit(error_type, &m->error_type)) |
211 | return; | 208 | return; |
212 | 209 | ||
210 | if (!errors_handled(ms)) | ||
211 | return; | ||
212 | |||
213 | if (m != get_default_mirror(ms)) | 213 | if (m != get_default_mirror(ms)) |
214 | goto out; | 214 | goto out; |
215 | 215 | ||
@@ -808,12 +808,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti, | |||
808 | kfree(ms); | 808 | kfree(ms); |
809 | } | 809 | } |
810 | 810 | ||
811 | static inline int _check_region_size(struct dm_target *ti, uint32_t size) | ||
812 | { | ||
813 | return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) || | ||
814 | size > ti->len); | ||
815 | } | ||
816 | |||
817 | static int get_mirror(struct mirror_set *ms, struct dm_target *ti, | 811 | static int get_mirror(struct mirror_set *ms, struct dm_target *ti, |
818 | unsigned int mirror, char **argv) | 812 | unsigned int mirror, char **argv) |
819 | { | 813 | { |
@@ -872,12 +866,6 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti, | |||
872 | return NULL; | 866 | return NULL; |
873 | } | 867 | } |
874 | 868 | ||
875 | if (!_check_region_size(ti, dl->type->get_region_size(dl))) { | ||
876 | ti->error = "Invalid region size"; | ||
877 | dm_dirty_log_destroy(dl); | ||
878 | return NULL; | ||
879 | } | ||
880 | |||
881 | return dl; | 869 | return dl; |
882 | } | 870 | } |
883 | 871 | ||
@@ -1300,11 +1288,7 @@ static int __init dm_mirror_init(void) | |||
1300 | 1288 | ||
1301 | static void __exit dm_mirror_exit(void) | 1289 | static void __exit dm_mirror_exit(void) |
1302 | { | 1290 | { |
1303 | int r; | 1291 | dm_unregister_target(&mirror_target); |
1304 | |||
1305 | r = dm_unregister_target(&mirror_target); | ||
1306 | if (r < 0) | ||
1307 | DMERR("unregister failed %d", r); | ||
1308 | } | 1292 | } |
1309 | 1293 | ||
1310 | /* Module hooks */ | 1294 | /* Module hooks */ |
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c new file mode 100644 index 000000000000..936b34e0959f --- /dev/null +++ b/drivers/md/dm-snap-persistent.c | |||
@@ -0,0 +1,704 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. | ||
3 | * Copyright (C) 2006-2008 Red Hat GmbH | ||
4 | * | ||
5 | * This file is released under the GPL. | ||
6 | */ | ||
7 | |||
8 | #include "dm-exception-store.h" | ||
9 | #include "dm-snap.h" | ||
10 | |||
11 | #include <linux/mm.h> | ||
12 | #include <linux/pagemap.h> | ||
13 | #include <linux/vmalloc.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/dm-io.h> | ||
16 | |||
17 | #define DM_MSG_PREFIX "persistent snapshot" | ||
18 | #define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ | ||
19 | |||
20 | /*----------------------------------------------------------------- | ||
21 | * Persistent snapshots, by persistent we mean that the snapshot | ||
22 | * will survive a reboot. | ||
23 | *---------------------------------------------------------------*/ | ||
24 | |||
25 | /* | ||
26 | * We need to store a record of which parts of the origin have | ||
27 | * been copied to the snapshot device. The snapshot code | ||
28 | * requires that we copy exception chunks to chunk aligned areas | ||
29 | * of the COW store. It makes sense therefore, to store the | ||
30 | * metadata in chunk size blocks. | ||
31 | * | ||
32 | * There is no backward or forward compatibility implemented, | ||
33 | * snapshots with different disk versions than the kernel will | ||
34 | * not be usable. It is expected that "lvcreate" will blank out | ||
35 | * the start of a fresh COW device before calling the snapshot | ||
36 | * constructor. | ||
37 | * | ||
38 | * The first chunk of the COW device just contains the header. | ||
39 | * After this there is a chunk filled with exception metadata, | ||
40 | * followed by as many exception chunks as can fit in the | ||
41 | * metadata areas. | ||
42 | * | ||
43 | * All on disk structures are in little-endian format. The end | ||
44 | * of the exceptions info is indicated by an exception with a | ||
45 | * new_chunk of 0, which is invalid since it would point to the | ||
46 | * header chunk. | ||
47 | */ | ||
48 | |||
49 | /* | ||
50 | * Magic for persistent snapshots: "SnAp" - Feeble isn't it. | ||
51 | */ | ||
52 | #define SNAP_MAGIC 0x70416e53 | ||
53 | |||
54 | /* | ||
55 | * The on-disk version of the metadata. | ||
56 | */ | ||
57 | #define SNAPSHOT_DISK_VERSION 1 | ||
58 | |||
59 | struct disk_header { | ||
60 | uint32_t magic; | ||
61 | |||
62 | /* | ||
63 | * Is this snapshot valid. There is no way of recovering | ||
64 | * an invalid snapshot. | ||
65 | */ | ||
66 | uint32_t valid; | ||
67 | |||
68 | /* | ||
69 | * Simple, incrementing version. no backward | ||
70 | * compatibility. | ||
71 | */ | ||
72 | uint32_t version; | ||
73 | |||
74 | /* In sectors */ | ||
75 | uint32_t chunk_size; | ||
76 | }; | ||
77 | |||
78 | struct disk_exception { | ||
79 | uint64_t old_chunk; | ||
80 | uint64_t new_chunk; | ||
81 | }; | ||
82 | |||
83 | struct commit_callback { | ||
84 | void (*callback)(void *, int success); | ||
85 | void *context; | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * The top level structure for a persistent exception store. | ||
90 | */ | ||
91 | struct pstore { | ||
92 | struct dm_snapshot *snap; /* up pointer to my snapshot */ | ||
93 | int version; | ||
94 | int valid; | ||
95 | uint32_t exceptions_per_area; | ||
96 | |||
97 | /* | ||
98 | * Now that we have an asynchronous kcopyd there is no | ||
99 | * need for large chunk sizes, so it wont hurt to have a | ||
100 | * whole chunks worth of metadata in memory at once. | ||
101 | */ | ||
102 | void *area; | ||
103 | |||
104 | /* | ||
105 | * An area of zeros used to clear the next area. | ||
106 | */ | ||
107 | void *zero_area; | ||
108 | |||
109 | /* | ||
110 | * Used to keep track of which metadata area the data in | ||
111 | * 'chunk' refers to. | ||
112 | */ | ||
113 | chunk_t current_area; | ||
114 | |||
115 | /* | ||
116 | * The next free chunk for an exception. | ||
117 | */ | ||
118 | chunk_t next_free; | ||
119 | |||
120 | /* | ||
121 | * The index of next free exception in the current | ||
122 | * metadata area. | ||
123 | */ | ||
124 | uint32_t current_committed; | ||
125 | |||
126 | atomic_t pending_count; | ||
127 | uint32_t callback_count; | ||
128 | struct commit_callback *callbacks; | ||
129 | struct dm_io_client *io_client; | ||
130 | |||
131 | struct workqueue_struct *metadata_wq; | ||
132 | }; | ||
133 | |||
134 | static unsigned sectors_to_pages(unsigned sectors) | ||
135 | { | ||
136 | return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9); | ||
137 | } | ||
138 | |||
139 | static int alloc_area(struct pstore *ps) | ||
140 | { | ||
141 | int r = -ENOMEM; | ||
142 | size_t len; | ||
143 | |||
144 | len = ps->snap->chunk_size << SECTOR_SHIFT; | ||
145 | |||
146 | /* | ||
147 | * Allocate the chunk_size block of memory that will hold | ||
148 | * a single metadata area. | ||
149 | */ | ||
150 | ps->area = vmalloc(len); | ||
151 | if (!ps->area) | ||
152 | return r; | ||
153 | |||
154 | ps->zero_area = vmalloc(len); | ||
155 | if (!ps->zero_area) { | ||
156 | vfree(ps->area); | ||
157 | return r; | ||
158 | } | ||
159 | memset(ps->zero_area, 0, len); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void free_area(struct pstore *ps) | ||
165 | { | ||
166 | vfree(ps->area); | ||
167 | ps->area = NULL; | ||
168 | vfree(ps->zero_area); | ||
169 | ps->zero_area = NULL; | ||
170 | } | ||
171 | |||
172 | struct mdata_req { | ||
173 | struct dm_io_region *where; | ||
174 | struct dm_io_request *io_req; | ||
175 | struct work_struct work; | ||
176 | int result; | ||
177 | }; | ||
178 | |||
179 | static void do_metadata(struct work_struct *work) | ||
180 | { | ||
181 | struct mdata_req *req = container_of(work, struct mdata_req, work); | ||
182 | |||
183 | req->result = dm_io(req->io_req, 1, req->where, NULL); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Read or write a chunk aligned and sized block of data from a device. | ||
188 | */ | ||
189 | static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata) | ||
190 | { | ||
191 | struct dm_io_region where = { | ||
192 | .bdev = ps->snap->cow->bdev, | ||
193 | .sector = ps->snap->chunk_size * chunk, | ||
194 | .count = ps->snap->chunk_size, | ||
195 | }; | ||
196 | struct dm_io_request io_req = { | ||
197 | .bi_rw = rw, | ||
198 | .mem.type = DM_IO_VMA, | ||
199 | .mem.ptr.vma = ps->area, | ||
200 | .client = ps->io_client, | ||
201 | .notify.fn = NULL, | ||
202 | }; | ||
203 | struct mdata_req req; | ||
204 | |||
205 | if (!metadata) | ||
206 | return dm_io(&io_req, 1, &where, NULL); | ||
207 | |||
208 | req.where = &where; | ||
209 | req.io_req = &io_req; | ||
210 | |||
211 | /* | ||
212 | * Issue the synchronous I/O from a different thread | ||
213 | * to avoid generic_make_request recursion. | ||
214 | */ | ||
215 | INIT_WORK(&req.work, do_metadata); | ||
216 | queue_work(ps->metadata_wq, &req.work); | ||
217 | flush_workqueue(ps->metadata_wq); | ||
218 | |||
219 | return req.result; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * Convert a metadata area index to a chunk index. | ||
224 | */ | ||
225 | static chunk_t area_location(struct pstore *ps, chunk_t area) | ||
226 | { | ||
227 | return 1 + ((ps->exceptions_per_area + 1) * area); | ||
228 | } | ||
229 | |||
230 | /* | ||
231 | * Read or write a metadata area. Remembering to skip the first | ||
232 | * chunk which holds the header. | ||
233 | */ | ||
234 | static int area_io(struct pstore *ps, int rw) | ||
235 | { | ||
236 | int r; | ||
237 | chunk_t chunk; | ||
238 | |||
239 | chunk = area_location(ps, ps->current_area); | ||
240 | |||
241 | r = chunk_io(ps, chunk, rw, 0); | ||
242 | if (r) | ||
243 | return r; | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static void zero_memory_area(struct pstore *ps) | ||
249 | { | ||
250 | memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); | ||
251 | } | ||
252 | |||
253 | static int zero_disk_area(struct pstore *ps, chunk_t area) | ||
254 | { | ||
255 | struct dm_io_region where = { | ||
256 | .bdev = ps->snap->cow->bdev, | ||
257 | .sector = ps->snap->chunk_size * area_location(ps, area), | ||
258 | .count = ps->snap->chunk_size, | ||
259 | }; | ||
260 | struct dm_io_request io_req = { | ||
261 | .bi_rw = WRITE, | ||
262 | .mem.type = DM_IO_VMA, | ||
263 | .mem.ptr.vma = ps->zero_area, | ||
264 | .client = ps->io_client, | ||
265 | .notify.fn = NULL, | ||
266 | }; | ||
267 | |||
268 | return dm_io(&io_req, 1, &where, NULL); | ||
269 | } | ||
270 | |||
271 | static int read_header(struct pstore *ps, int *new_snapshot) | ||
272 | { | ||
273 | int r; | ||
274 | struct disk_header *dh; | ||
275 | chunk_t chunk_size; | ||
276 | int chunk_size_supplied = 1; | ||
277 | |||
278 | /* | ||
279 | * Use default chunk size (or hardsect_size, if larger) if none supplied | ||
280 | */ | ||
281 | if (!ps->snap->chunk_size) { | ||
282 | ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, | ||
283 | bdev_hardsect_size(ps->snap->cow->bdev) >> 9); | ||
284 | ps->snap->chunk_mask = ps->snap->chunk_size - 1; | ||
285 | ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1; | ||
286 | chunk_size_supplied = 0; | ||
287 | } | ||
288 | |||
289 | ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap-> | ||
290 | chunk_size)); | ||
291 | if (IS_ERR(ps->io_client)) | ||
292 | return PTR_ERR(ps->io_client); | ||
293 | |||
294 | r = alloc_area(ps); | ||
295 | if (r) | ||
296 | return r; | ||
297 | |||
298 | r = chunk_io(ps, 0, READ, 1); | ||
299 | if (r) | ||
300 | goto bad; | ||
301 | |||
302 | dh = (struct disk_header *) ps->area; | ||
303 | |||
304 | if (le32_to_cpu(dh->magic) == 0) { | ||
305 | *new_snapshot = 1; | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | if (le32_to_cpu(dh->magic) != SNAP_MAGIC) { | ||
310 | DMWARN("Invalid or corrupt snapshot"); | ||
311 | r = -ENXIO; | ||
312 | goto bad; | ||
313 | } | ||
314 | |||
315 | *new_snapshot = 0; | ||
316 | ps->valid = le32_to_cpu(dh->valid); | ||
317 | ps->version = le32_to_cpu(dh->version); | ||
318 | chunk_size = le32_to_cpu(dh->chunk_size); | ||
319 | |||
320 | if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size) | ||
321 | return 0; | ||
322 | |||
323 | DMWARN("chunk size %llu in device metadata overrides " | ||
324 | "table chunk size of %llu.", | ||
325 | (unsigned long long)chunk_size, | ||
326 | (unsigned long long)ps->snap->chunk_size); | ||
327 | |||
328 | /* We had a bogus chunk_size. Fix stuff up. */ | ||
329 | free_area(ps); | ||
330 | |||
331 | ps->snap->chunk_size = chunk_size; | ||
332 | ps->snap->chunk_mask = chunk_size - 1; | ||
333 | ps->snap->chunk_shift = ffs(chunk_size) - 1; | ||
334 | |||
335 | r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size), | ||
336 | ps->io_client); | ||
337 | if (r) | ||
338 | return r; | ||
339 | |||
340 | r = alloc_area(ps); | ||
341 | return r; | ||
342 | |||
343 | bad: | ||
344 | free_area(ps); | ||
345 | return r; | ||
346 | } | ||
347 | |||
348 | static int write_header(struct pstore *ps) | ||
349 | { | ||
350 | struct disk_header *dh; | ||
351 | |||
352 | memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT); | ||
353 | |||
354 | dh = (struct disk_header *) ps->area; | ||
355 | dh->magic = cpu_to_le32(SNAP_MAGIC); | ||
356 | dh->valid = cpu_to_le32(ps->valid); | ||
357 | dh->version = cpu_to_le32(ps->version); | ||
358 | dh->chunk_size = cpu_to_le32(ps->snap->chunk_size); | ||
359 | |||
360 | return chunk_io(ps, 0, WRITE, 1); | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * Access functions for the disk exceptions, these do the endian conversions. | ||
365 | */ | ||
366 | static struct disk_exception *get_exception(struct pstore *ps, uint32_t index) | ||
367 | { | ||
368 | BUG_ON(index >= ps->exceptions_per_area); | ||
369 | |||
370 | return ((struct disk_exception *) ps->area) + index; | ||
371 | } | ||
372 | |||
373 | static void read_exception(struct pstore *ps, | ||
374 | uint32_t index, struct disk_exception *result) | ||
375 | { | ||
376 | struct disk_exception *e = get_exception(ps, index); | ||
377 | |||
378 | /* copy it */ | ||
379 | result->old_chunk = le64_to_cpu(e->old_chunk); | ||
380 | result->new_chunk = le64_to_cpu(e->new_chunk); | ||
381 | } | ||
382 | |||
383 | static void write_exception(struct pstore *ps, | ||
384 | uint32_t index, struct disk_exception *de) | ||
385 | { | ||
386 | struct disk_exception *e = get_exception(ps, index); | ||
387 | |||
388 | /* copy it */ | ||
389 | e->old_chunk = cpu_to_le64(de->old_chunk); | ||
390 | e->new_chunk = cpu_to_le64(de->new_chunk); | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Registers the exceptions that are present in the current area. | ||
395 | * 'full' is filled in to indicate if the area has been | ||
396 | * filled. | ||
397 | */ | ||
398 | static int insert_exceptions(struct pstore *ps, | ||
399 | int (*callback)(void *callback_context, | ||
400 | chunk_t old, chunk_t new), | ||
401 | void *callback_context, | ||
402 | int *full) | ||
403 | { | ||
404 | int r; | ||
405 | unsigned int i; | ||
406 | struct disk_exception de; | ||
407 | |||
408 | /* presume the area is full */ | ||
409 | *full = 1; | ||
410 | |||
411 | for (i = 0; i < ps->exceptions_per_area; i++) { | ||
412 | read_exception(ps, i, &de); | ||
413 | |||
414 | /* | ||
415 | * If the new_chunk is pointing at the start of | ||
416 | * the COW device, where the first metadata area | ||
417 | * is we know that we've hit the end of the | ||
418 | * exceptions. Therefore the area is not full. | ||
419 | */ | ||
420 | if (de.new_chunk == 0LL) { | ||
421 | ps->current_committed = i; | ||
422 | *full = 0; | ||
423 | break; | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * Keep track of the start of the free chunks. | ||
428 | */ | ||
429 | if (ps->next_free <= de.new_chunk) | ||
430 | ps->next_free = de.new_chunk + 1; | ||
431 | |||
432 | /* | ||
433 | * Otherwise we add the exception to the snapshot. | ||
434 | */ | ||
435 | r = callback(callback_context, de.old_chunk, de.new_chunk); | ||
436 | if (r) | ||
437 | return r; | ||
438 | } | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int read_exceptions(struct pstore *ps, | ||
444 | int (*callback)(void *callback_context, chunk_t old, | ||
445 | chunk_t new), | ||
446 | void *callback_context) | ||
447 | { | ||
448 | int r, full = 1; | ||
449 | |||
450 | /* | ||
451 | * Keeping reading chunks and inserting exceptions until | ||
452 | * we find a partially full area. | ||
453 | */ | ||
454 | for (ps->current_area = 0; full; ps->current_area++) { | ||
455 | r = area_io(ps, READ); | ||
456 | if (r) | ||
457 | return r; | ||
458 | |||
459 | r = insert_exceptions(ps, callback, callback_context, &full); | ||
460 | if (r) | ||
461 | return r; | ||
462 | } | ||
463 | |||
464 | ps->current_area--; | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static struct pstore *get_info(struct dm_exception_store *store) | ||
470 | { | ||
471 | return (struct pstore *) store->context; | ||
472 | } | ||
473 | |||
474 | static void persistent_fraction_full(struct dm_exception_store *store, | ||
475 | sector_t *numerator, sector_t *denominator) | ||
476 | { | ||
477 | *numerator = get_info(store)->next_free * store->snap->chunk_size; | ||
478 | *denominator = get_dev_size(store->snap->cow->bdev); | ||
479 | } | ||
480 | |||
481 | static void persistent_destroy(struct dm_exception_store *store) | ||
482 | { | ||
483 | struct pstore *ps = get_info(store); | ||
484 | |||
485 | destroy_workqueue(ps->metadata_wq); | ||
486 | dm_io_client_destroy(ps->io_client); | ||
487 | vfree(ps->callbacks); | ||
488 | free_area(ps); | ||
489 | kfree(ps); | ||
490 | } | ||
491 | |||
492 | static int persistent_read_metadata(struct dm_exception_store *store, | ||
493 | int (*callback)(void *callback_context, | ||
494 | chunk_t old, chunk_t new), | ||
495 | void *callback_context) | ||
496 | { | ||
497 | int r, uninitialized_var(new_snapshot); | ||
498 | struct pstore *ps = get_info(store); | ||
499 | |||
500 | /* | ||
501 | * Read the snapshot header. | ||
502 | */ | ||
503 | r = read_header(ps, &new_snapshot); | ||
504 | if (r) | ||
505 | return r; | ||
506 | |||
507 | /* | ||
508 | * Now we know correct chunk_size, complete the initialisation. | ||
509 | */ | ||
510 | ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) / | ||
511 | sizeof(struct disk_exception); | ||
512 | ps->callbacks = dm_vcalloc(ps->exceptions_per_area, | ||
513 | sizeof(*ps->callbacks)); | ||
514 | if (!ps->callbacks) | ||
515 | return -ENOMEM; | ||
516 | |||
517 | /* | ||
518 | * Do we need to setup a new snapshot ? | ||
519 | */ | ||
520 | if (new_snapshot) { | ||
521 | r = write_header(ps); | ||
522 | if (r) { | ||
523 | DMWARN("write_header failed"); | ||
524 | return r; | ||
525 | } | ||
526 | |||
527 | ps->current_area = 0; | ||
528 | zero_memory_area(ps); | ||
529 | r = zero_disk_area(ps, 0); | ||
530 | if (r) { | ||
531 | DMWARN("zero_disk_area(0) failed"); | ||
532 | return r; | ||
533 | } | ||
534 | } else { | ||
535 | /* | ||
536 | * Sanity checks. | ||
537 | */ | ||
538 | if (ps->version != SNAPSHOT_DISK_VERSION) { | ||
539 | DMWARN("unable to handle snapshot disk version %d", | ||
540 | ps->version); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * Metadata are valid, but snapshot is invalidated | ||
546 | */ | ||
547 | if (!ps->valid) | ||
548 | return 1; | ||
549 | |||
550 | /* | ||
551 | * Read the metadata. | ||
552 | */ | ||
553 | r = read_exceptions(ps, callback, callback_context); | ||
554 | if (r) | ||
555 | return r; | ||
556 | } | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int persistent_prepare_exception(struct dm_exception_store *store, | ||
562 | struct dm_snap_exception *e) | ||
563 | { | ||
564 | struct pstore *ps = get_info(store); | ||
565 | uint32_t stride; | ||
566 | chunk_t next_free; | ||
567 | sector_t size = get_dev_size(store->snap->cow->bdev); | ||
568 | |||
569 | /* Is there enough room ? */ | ||
570 | if (size < ((ps->next_free + 1) * store->snap->chunk_size)) | ||
571 | return -ENOSPC; | ||
572 | |||
573 | e->new_chunk = ps->next_free; | ||
574 | |||
575 | /* | ||
576 | * Move onto the next free pending, making sure to take | ||
577 | * into account the location of the metadata chunks. | ||
578 | */ | ||
579 | stride = (ps->exceptions_per_area + 1); | ||
580 | next_free = ++ps->next_free; | ||
581 | if (sector_div(next_free, stride) == 1) | ||
582 | ps->next_free++; | ||
583 | |||
584 | atomic_inc(&ps->pending_count); | ||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static void persistent_commit_exception(struct dm_exception_store *store, | ||
589 | struct dm_snap_exception *e, | ||
590 | void (*callback) (void *, int success), | ||
591 | void *callback_context) | ||
592 | { | ||
593 | unsigned int i; | ||
594 | struct pstore *ps = get_info(store); | ||
595 | struct disk_exception de; | ||
596 | struct commit_callback *cb; | ||
597 | |||
598 | de.old_chunk = e->old_chunk; | ||
599 | de.new_chunk = e->new_chunk; | ||
600 | write_exception(ps, ps->current_committed++, &de); | ||
601 | |||
602 | /* | ||
603 | * Add the callback to the back of the array. This code | ||
604 | * is the only place where the callback array is | ||
605 | * manipulated, and we know that it will never be called | ||
606 | * multiple times concurrently. | ||
607 | */ | ||
608 | cb = ps->callbacks + ps->callback_count++; | ||
609 | cb->callback = callback; | ||
610 | cb->context = callback_context; | ||
611 | |||
612 | /* | ||
613 | * If there are exceptions in flight and we have not yet | ||
614 | * filled this metadata area there's nothing more to do. | ||
615 | */ | ||
616 | if (!atomic_dec_and_test(&ps->pending_count) && | ||
617 | (ps->current_committed != ps->exceptions_per_area)) | ||
618 | return; | ||
619 | |||
620 | /* | ||
621 | * If we completely filled the current area, then wipe the next one. | ||
622 | */ | ||
623 | if ((ps->current_committed == ps->exceptions_per_area) && | ||
624 | zero_disk_area(ps, ps->current_area + 1)) | ||
625 | ps->valid = 0; | ||
626 | |||
627 | /* | ||
628 | * Commit exceptions to disk. | ||
629 | */ | ||
630 | if (ps->valid && area_io(ps, WRITE)) | ||
631 | ps->valid = 0; | ||
632 | |||
633 | /* | ||
634 | * Advance to the next area if this one is full. | ||
635 | */ | ||
636 | if (ps->current_committed == ps->exceptions_per_area) { | ||
637 | ps->current_committed = 0; | ||
638 | ps->current_area++; | ||
639 | zero_memory_area(ps); | ||
640 | } | ||
641 | |||
642 | for (i = 0; i < ps->callback_count; i++) { | ||
643 | cb = ps->callbacks + i; | ||
644 | cb->callback(cb->context, ps->valid); | ||
645 | } | ||
646 | |||
647 | ps->callback_count = 0; | ||
648 | } | ||
649 | |||
650 | static void persistent_drop_snapshot(struct dm_exception_store *store) | ||
651 | { | ||
652 | struct pstore *ps = get_info(store); | ||
653 | |||
654 | ps->valid = 0; | ||
655 | if (write_header(ps)) | ||
656 | DMWARN("write header failed"); | ||
657 | } | ||
658 | |||
659 | int dm_create_persistent(struct dm_exception_store *store) | ||
660 | { | ||
661 | struct pstore *ps; | ||
662 | |||
663 | /* allocate the pstore */ | ||
664 | ps = kmalloc(sizeof(*ps), GFP_KERNEL); | ||
665 | if (!ps) | ||
666 | return -ENOMEM; | ||
667 | |||
668 | ps->snap = store->snap; | ||
669 | ps->valid = 1; | ||
670 | ps->version = SNAPSHOT_DISK_VERSION; | ||
671 | ps->area = NULL; | ||
672 | ps->next_free = 2; /* skipping the header and first area */ | ||
673 | ps->current_committed = 0; | ||
674 | |||
675 | ps->callback_count = 0; | ||
676 | atomic_set(&ps->pending_count, 0); | ||
677 | ps->callbacks = NULL; | ||
678 | |||
679 | ps->metadata_wq = create_singlethread_workqueue("ksnaphd"); | ||
680 | if (!ps->metadata_wq) { | ||
681 | kfree(ps); | ||
682 | DMERR("couldn't start header metadata update thread"); | ||
683 | return -ENOMEM; | ||
684 | } | ||
685 | |||
686 | store->destroy = persistent_destroy; | ||
687 | store->read_metadata = persistent_read_metadata; | ||
688 | store->prepare_exception = persistent_prepare_exception; | ||
689 | store->commit_exception = persistent_commit_exception; | ||
690 | store->drop_snapshot = persistent_drop_snapshot; | ||
691 | store->fraction_full = persistent_fraction_full; | ||
692 | store->context = ps; | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | int dm_persistent_snapshot_init(void) | ||
698 | { | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | void dm_persistent_snapshot_exit(void) | ||
703 | { | ||
704 | } | ||
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c new file mode 100644 index 000000000000..7f6e2e6dcb0d --- /dev/null +++ b/drivers/md/dm-snap-transient.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. | ||
3 | * Copyright (C) 2006-2008 Red Hat GmbH | ||
4 | * | ||
5 | * This file is released under the GPL. | ||
6 | */ | ||
7 | |||
8 | #include "dm-exception-store.h" | ||
9 | #include "dm-snap.h" | ||
10 | |||
11 | #include <linux/mm.h> | ||
12 | #include <linux/pagemap.h> | ||
13 | #include <linux/vmalloc.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/dm-io.h> | ||
16 | |||
17 | #define DM_MSG_PREFIX "transient snapshot" | ||
18 | |||
19 | /*----------------------------------------------------------------- | ||
20 | * Implementation of the store for non-persistent snapshots. | ||
21 | *---------------------------------------------------------------*/ | ||
22 | struct transient_c { | ||
23 | sector_t next_free; | ||
24 | }; | ||
25 | |||
26 | static void transient_destroy(struct dm_exception_store *store) | ||
27 | { | ||
28 | kfree(store->context); | ||
29 | } | ||
30 | |||
31 | static int transient_read_metadata(struct dm_exception_store *store, | ||
32 | int (*callback)(void *callback_context, | ||
33 | chunk_t old, chunk_t new), | ||
34 | void *callback_context) | ||
35 | { | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static int transient_prepare_exception(struct dm_exception_store *store, | ||
40 | struct dm_snap_exception *e) | ||
41 | { | ||
42 | struct transient_c *tc = (struct transient_c *) store->context; | ||
43 | sector_t size = get_dev_size(store->snap->cow->bdev); | ||
44 | |||
45 | if (size < (tc->next_free + store->snap->chunk_size)) | ||
46 | return -1; | ||
47 | |||
48 | e->new_chunk = sector_to_chunk(store->snap, tc->next_free); | ||
49 | tc->next_free += store->snap->chunk_size; | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | static void transient_commit_exception(struct dm_exception_store *store, | ||
55 | struct dm_snap_exception *e, | ||
56 | void (*callback) (void *, int success), | ||
57 | void *callback_context) | ||
58 | { | ||
59 | /* Just succeed */ | ||
60 | callback(callback_context, 1); | ||
61 | } | ||
62 | |||
63 | static void transient_fraction_full(struct dm_exception_store *store, | ||
64 | sector_t *numerator, sector_t *denominator) | ||
65 | { | ||
66 | *numerator = ((struct transient_c *) store->context)->next_free; | ||
67 | *denominator = get_dev_size(store->snap->cow->bdev); | ||
68 | } | ||
69 | |||
70 | int dm_create_transient(struct dm_exception_store *store) | ||
71 | { | ||
72 | struct transient_c *tc; | ||
73 | |||
74 | store->destroy = transient_destroy; | ||
75 | store->read_metadata = transient_read_metadata; | ||
76 | store->prepare_exception = transient_prepare_exception; | ||
77 | store->commit_exception = transient_commit_exception; | ||
78 | store->drop_snapshot = NULL; | ||
79 | store->fraction_full = transient_fraction_full; | ||
80 | |||
81 | tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL); | ||
82 | if (!tc) | ||
83 | return -ENOMEM; | ||
84 | |||
85 | tc->next_free = 0; | ||
86 | store->context = tc; | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | int dm_transient_snapshot_init(void) | ||
92 | { | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | void dm_transient_snapshot_exit(void) | ||
97 | { | ||
98 | } | ||
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 6c96db26b87c..65ff82ff124e 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/blkdev.h> | 9 | #include <linux/blkdev.h> |
10 | #include <linux/ctype.h> | 10 | #include <linux/ctype.h> |
11 | #include <linux/device-mapper.h> | 11 | #include <linux/device-mapper.h> |
12 | #include <linux/delay.h> | ||
12 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include <linux/kdev_t.h> | 15 | #include <linux/kdev_t.h> |
@@ -20,6 +21,7 @@ | |||
20 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
21 | #include <linux/dm-kcopyd.h> | 22 | #include <linux/dm-kcopyd.h> |
22 | 23 | ||
24 | #include "dm-exception-store.h" | ||
23 | #include "dm-snap.h" | 25 | #include "dm-snap.h" |
24 | #include "dm-bio-list.h" | 26 | #include "dm-bio-list.h" |
25 | 27 | ||
@@ -428,8 +430,13 @@ out: | |||
428 | list_add(&new_e->hash_list, e ? &e->hash_list : l); | 430 | list_add(&new_e->hash_list, e ? &e->hash_list : l); |
429 | } | 431 | } |
430 | 432 | ||
431 | int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new) | 433 | /* |
434 | * Callback used by the exception stores to load exceptions when | ||
435 | * initialising. | ||
436 | */ | ||
437 | static int dm_add_exception(void *context, chunk_t old, chunk_t new) | ||
432 | { | 438 | { |
439 | struct dm_snapshot *s = context; | ||
433 | struct dm_snap_exception *e; | 440 | struct dm_snap_exception *e; |
434 | 441 | ||
435 | e = alloc_exception(); | 442 | e = alloc_exception(); |
@@ -658,7 +665,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
658 | spin_lock_init(&s->tracked_chunk_lock); | 665 | spin_lock_init(&s->tracked_chunk_lock); |
659 | 666 | ||
660 | /* Metadata must only be loaded into one table at once */ | 667 | /* Metadata must only be loaded into one table at once */ |
661 | r = s->store.read_metadata(&s->store); | 668 | r = s->store.read_metadata(&s->store, dm_add_exception, (void *)s); |
662 | if (r < 0) { | 669 | if (r < 0) { |
663 | ti->error = "Failed to read snapshot metadata"; | 670 | ti->error = "Failed to read snapshot metadata"; |
664 | goto bad_load_and_register; | 671 | goto bad_load_and_register; |
@@ -735,7 +742,7 @@ static void snapshot_dtr(struct dm_target *ti) | |||
735 | unregister_snapshot(s); | 742 | unregister_snapshot(s); |
736 | 743 | ||
737 | while (atomic_read(&s->pending_exceptions_count)) | 744 | while (atomic_read(&s->pending_exceptions_count)) |
738 | yield(); | 745 | msleep(1); |
739 | /* | 746 | /* |
740 | * Ensure instructions in mempool_destroy aren't reordered | 747 | * Ensure instructions in mempool_destroy aren't reordered |
741 | * before atomic_read. | 748 | * before atomic_read. |
@@ -888,10 +895,10 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success) | |||
888 | 895 | ||
889 | /* | 896 | /* |
890 | * Check for conflicting reads. This is extremely improbable, | 897 | * Check for conflicting reads. This is extremely improbable, |
891 | * so yield() is sufficient and there is no need for a wait queue. | 898 | * so msleep(1) is sufficient and there is no need for a wait queue. |
892 | */ | 899 | */ |
893 | while (__chunk_is_tracked(s, pe->e.old_chunk)) | 900 | while (__chunk_is_tracked(s, pe->e.old_chunk)) |
894 | yield(); | 901 | msleep(1); |
895 | 902 | ||
896 | /* | 903 | /* |
897 | * Add a proper exception, and remove the | 904 | * Add a proper exception, and remove the |
@@ -1404,6 +1411,12 @@ static int __init dm_snapshot_init(void) | |||
1404 | { | 1411 | { |
1405 | int r; | 1412 | int r; |
1406 | 1413 | ||
1414 | r = dm_exception_store_init(); | ||
1415 | if (r) { | ||
1416 | DMERR("Failed to initialize exception stores"); | ||
1417 | return r; | ||
1418 | } | ||
1419 | |||
1407 | r = dm_register_target(&snapshot_target); | 1420 | r = dm_register_target(&snapshot_target); |
1408 | if (r) { | 1421 | if (r) { |
1409 | DMERR("snapshot target register failed %d", r); | 1422 | DMERR("snapshot target register failed %d", r); |
@@ -1452,39 +1465,34 @@ static int __init dm_snapshot_init(void) | |||
1452 | 1465 | ||
1453 | return 0; | 1466 | return 0; |
1454 | 1467 | ||
1455 | bad_pending_pool: | 1468 | bad_pending_pool: |
1456 | kmem_cache_destroy(tracked_chunk_cache); | 1469 | kmem_cache_destroy(tracked_chunk_cache); |
1457 | bad5: | 1470 | bad5: |
1458 | kmem_cache_destroy(pending_cache); | 1471 | kmem_cache_destroy(pending_cache); |
1459 | bad4: | 1472 | bad4: |
1460 | kmem_cache_destroy(exception_cache); | 1473 | kmem_cache_destroy(exception_cache); |
1461 | bad3: | 1474 | bad3: |
1462 | exit_origin_hash(); | 1475 | exit_origin_hash(); |
1463 | bad2: | 1476 | bad2: |
1464 | dm_unregister_target(&origin_target); | 1477 | dm_unregister_target(&origin_target); |
1465 | bad1: | 1478 | bad1: |
1466 | dm_unregister_target(&snapshot_target); | 1479 | dm_unregister_target(&snapshot_target); |
1467 | return r; | 1480 | return r; |
1468 | } | 1481 | } |
1469 | 1482 | ||
1470 | static void __exit dm_snapshot_exit(void) | 1483 | static void __exit dm_snapshot_exit(void) |
1471 | { | 1484 | { |
1472 | int r; | ||
1473 | |||
1474 | destroy_workqueue(ksnapd); | 1485 | destroy_workqueue(ksnapd); |
1475 | 1486 | ||
1476 | r = dm_unregister_target(&snapshot_target); | 1487 | dm_unregister_target(&snapshot_target); |
1477 | if (r) | 1488 | dm_unregister_target(&origin_target); |
1478 | DMERR("snapshot unregister failed %d", r); | ||
1479 | |||
1480 | r = dm_unregister_target(&origin_target); | ||
1481 | if (r) | ||
1482 | DMERR("origin unregister failed %d", r); | ||
1483 | 1489 | ||
1484 | exit_origin_hash(); | 1490 | exit_origin_hash(); |
1485 | kmem_cache_destroy(pending_cache); | 1491 | kmem_cache_destroy(pending_cache); |
1486 | kmem_cache_destroy(exception_cache); | 1492 | kmem_cache_destroy(exception_cache); |
1487 | kmem_cache_destroy(tracked_chunk_cache); | 1493 | kmem_cache_destroy(tracked_chunk_cache); |
1494 | |||
1495 | dm_exception_store_exit(); | ||
1488 | } | 1496 | } |
1489 | 1497 | ||
1490 | /* Module hooks */ | 1498 | /* Module hooks */ |
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index 99c0106ede2d..d9e62b43cf85 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * dm-snapshot.c | ||
3 | * | ||
4 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. | 2 | * Copyright (C) 2001-2002 Sistina Software (UK) Limited. |
5 | * | 3 | * |
6 | * This file is released under the GPL. | 4 | * This file is released under the GPL. |
@@ -10,6 +8,7 @@ | |||
10 | #define DM_SNAPSHOT_H | 8 | #define DM_SNAPSHOT_H |
11 | 9 | ||
12 | #include <linux/device-mapper.h> | 10 | #include <linux/device-mapper.h> |
11 | #include "dm-exception-store.h" | ||
13 | #include "dm-bio-list.h" | 12 | #include "dm-bio-list.h" |
14 | #include <linux/blkdev.h> | 13 | #include <linux/blkdev.h> |
15 | #include <linux/workqueue.h> | 14 | #include <linux/workqueue.h> |
@@ -20,116 +19,6 @@ struct exception_table { | |||
20 | struct list_head *table; | 19 | struct list_head *table; |
21 | }; | 20 | }; |
22 | 21 | ||
23 | /* | ||
24 | * The snapshot code deals with largish chunks of the disk at a | ||
25 | * time. Typically 32k - 512k. | ||
26 | */ | ||
27 | typedef sector_t chunk_t; | ||
28 | |||
29 | /* | ||
30 | * An exception is used where an old chunk of data has been | ||
31 | * replaced by a new one. | ||
32 | * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number | ||
33 | * of chunks that follow contiguously. Remaining bits hold the number of the | ||
34 | * chunk within the device. | ||
35 | */ | ||
36 | struct dm_snap_exception { | ||
37 | struct list_head hash_list; | ||
38 | |||
39 | chunk_t old_chunk; | ||
40 | chunk_t new_chunk; | ||
41 | }; | ||
42 | |||
43 | /* | ||
44 | * Funtions to manipulate consecutive chunks | ||
45 | */ | ||
46 | # if defined(CONFIG_LBD) || (BITS_PER_LONG == 64) | ||
47 | # define DM_CHUNK_CONSECUTIVE_BITS 8 | ||
48 | # define DM_CHUNK_NUMBER_BITS 56 | ||
49 | |||
50 | static inline chunk_t dm_chunk_number(chunk_t chunk) | ||
51 | { | ||
52 | return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL); | ||
53 | } | ||
54 | |||
55 | static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) | ||
56 | { | ||
57 | return e->new_chunk >> DM_CHUNK_NUMBER_BITS; | ||
58 | } | ||
59 | |||
60 | static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) | ||
61 | { | ||
62 | e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS); | ||
63 | |||
64 | BUG_ON(!dm_consecutive_chunk_count(e)); | ||
65 | } | ||
66 | |||
67 | # else | ||
68 | # define DM_CHUNK_CONSECUTIVE_BITS 0 | ||
69 | |||
70 | static inline chunk_t dm_chunk_number(chunk_t chunk) | ||
71 | { | ||
72 | return chunk; | ||
73 | } | ||
74 | |||
75 | static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e) | ||
76 | { | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e) | ||
81 | { | ||
82 | } | ||
83 | |||
84 | # endif | ||
85 | |||
86 | /* | ||
87 | * Abstraction to handle the meta/layout of exception stores (the | ||
88 | * COW device). | ||
89 | */ | ||
90 | struct exception_store { | ||
91 | |||
92 | /* | ||
93 | * Destroys this object when you've finished with it. | ||
94 | */ | ||
95 | void (*destroy) (struct exception_store *store); | ||
96 | |||
97 | /* | ||
98 | * The target shouldn't read the COW device until this is | ||
99 | * called. | ||
100 | */ | ||
101 | int (*read_metadata) (struct exception_store *store); | ||
102 | |||
103 | /* | ||
104 | * Find somewhere to store the next exception. | ||
105 | */ | ||
106 | int (*prepare_exception) (struct exception_store *store, | ||
107 | struct dm_snap_exception *e); | ||
108 | |||
109 | /* | ||
110 | * Update the metadata with this exception. | ||
111 | */ | ||
112 | void (*commit_exception) (struct exception_store *store, | ||
113 | struct dm_snap_exception *e, | ||
114 | void (*callback) (void *, int success), | ||
115 | void *callback_context); | ||
116 | |||
117 | /* | ||
118 | * The snapshot is invalid, note this in the metadata. | ||
119 | */ | ||
120 | void (*drop_snapshot) (struct exception_store *store); | ||
121 | |||
122 | /* | ||
123 | * Return how full the snapshot is. | ||
124 | */ | ||
125 | void (*fraction_full) (struct exception_store *store, | ||
126 | sector_t *numerator, | ||
127 | sector_t *denominator); | ||
128 | |||
129 | struct dm_snapshot *snap; | ||
130 | void *context; | ||
131 | }; | ||
132 | |||
133 | #define DM_TRACKED_CHUNK_HASH_SIZE 16 | 22 | #define DM_TRACKED_CHUNK_HASH_SIZE 16 |
134 | #define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \ | 23 | #define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \ |
135 | (DM_TRACKED_CHUNK_HASH_SIZE - 1)) | 24 | (DM_TRACKED_CHUNK_HASH_SIZE - 1)) |
@@ -172,7 +61,7 @@ struct dm_snapshot { | |||
172 | spinlock_t pe_lock; | 61 | spinlock_t pe_lock; |
173 | 62 | ||
174 | /* The on disk metadata handler */ | 63 | /* The on disk metadata handler */ |
175 | struct exception_store store; | 64 | struct dm_exception_store store; |
176 | 65 | ||
177 | struct dm_kcopyd_client *kcopyd_client; | 66 | struct dm_kcopyd_client *kcopyd_client; |
178 | 67 | ||
@@ -187,20 +76,6 @@ struct dm_snapshot { | |||
187 | }; | 76 | }; |
188 | 77 | ||
189 | /* | 78 | /* |
190 | * Used by the exception stores to load exceptions hen | ||
191 | * initialising. | ||
192 | */ | ||
193 | int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new); | ||
194 | |||
195 | /* | ||
196 | * Constructor and destructor for the default persistent | ||
197 | * store. | ||
198 | */ | ||
199 | int dm_create_persistent(struct exception_store *store); | ||
200 | |||
201 | int dm_create_transient(struct exception_store *store); | ||
202 | |||
203 | /* | ||
204 | * Return the number of sectors in the device. | 79 | * Return the number of sectors in the device. |
205 | */ | 80 | */ |
206 | static inline sector_t get_dev_size(struct block_device *bdev) | 81 | static inline sector_t get_dev_size(struct block_device *bdev) |
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 9e4ef88d421e..41569bc60abc 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
@@ -337,9 +337,7 @@ int __init dm_stripe_init(void) | |||
337 | 337 | ||
338 | void dm_stripe_exit(void) | 338 | void dm_stripe_exit(void) |
339 | { | 339 | { |
340 | if (dm_unregister_target(&stripe_target)) | 340 | dm_unregister_target(&stripe_target); |
341 | DMWARN("target unregistration failed"); | ||
342 | |||
343 | destroy_workqueue(kstriped); | 341 | destroy_workqueue(kstriped); |
344 | 342 | ||
345 | return; | 343 | return; |
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c new file mode 100644 index 000000000000..a2a45e6c7c8b --- /dev/null +++ b/drivers/md/dm-sysfs.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Red Hat, Inc. All rights reserved. | ||
3 | * | ||
4 | * This file is released under the GPL. | ||
5 | */ | ||
6 | |||
7 | #include <linux/sysfs.h> | ||
8 | #include <linux/dm-ioctl.h> | ||
9 | #include "dm.h" | ||
10 | |||
11 | struct dm_sysfs_attr { | ||
12 | struct attribute attr; | ||
13 | ssize_t (*show)(struct mapped_device *, char *); | ||
14 | ssize_t (*store)(struct mapped_device *, char *); | ||
15 | }; | ||
16 | |||
17 | #define DM_ATTR_RO(_name) \ | ||
18 | struct dm_sysfs_attr dm_attr_##_name = \ | ||
19 | __ATTR(_name, S_IRUGO, dm_attr_##_name##_show, NULL) | ||
20 | |||
21 | static ssize_t dm_attr_show(struct kobject *kobj, struct attribute *attr, | ||
22 | char *page) | ||
23 | { | ||
24 | struct dm_sysfs_attr *dm_attr; | ||
25 | struct mapped_device *md; | ||
26 | ssize_t ret; | ||
27 | |||
28 | dm_attr = container_of(attr, struct dm_sysfs_attr, attr); | ||
29 | if (!dm_attr->show) | ||
30 | return -EIO; | ||
31 | |||
32 | md = dm_get_from_kobject(kobj); | ||
33 | if (!md) | ||
34 | return -EINVAL; | ||
35 | |||
36 | ret = dm_attr->show(md, page); | ||
37 | dm_put(md); | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | static ssize_t dm_attr_name_show(struct mapped_device *md, char *buf) | ||
43 | { | ||
44 | if (dm_copy_name_and_uuid(md, buf, NULL)) | ||
45 | return -EIO; | ||
46 | |||
47 | strcat(buf, "\n"); | ||
48 | return strlen(buf); | ||
49 | } | ||
50 | |||
51 | static ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf) | ||
52 | { | ||
53 | if (dm_copy_name_and_uuid(md, NULL, buf)) | ||
54 | return -EIO; | ||
55 | |||
56 | strcat(buf, "\n"); | ||
57 | return strlen(buf); | ||
58 | } | ||
59 | |||
60 | static DM_ATTR_RO(name); | ||
61 | static DM_ATTR_RO(uuid); | ||
62 | |||
63 | static struct attribute *dm_attrs[] = { | ||
64 | &dm_attr_name.attr, | ||
65 | &dm_attr_uuid.attr, | ||
66 | NULL, | ||
67 | }; | ||
68 | |||
69 | static struct sysfs_ops dm_sysfs_ops = { | ||
70 | .show = dm_attr_show, | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * dm kobject is embedded in mapped_device structure | ||
75 | * no need to define release function here | ||
76 | */ | ||
77 | static struct kobj_type dm_ktype = { | ||
78 | .sysfs_ops = &dm_sysfs_ops, | ||
79 | .default_attrs = dm_attrs, | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * Initialize kobj | ||
84 | * because nobody using md yet, no need to call explicit dm_get/put | ||
85 | */ | ||
86 | int dm_sysfs_init(struct mapped_device *md) | ||
87 | { | ||
88 | return kobject_init_and_add(dm_kobject(md), &dm_ktype, | ||
89 | &disk_to_dev(dm_disk(md))->kobj, | ||
90 | "%s", "dm"); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Remove kobj, called after all references removed | ||
95 | */ | ||
96 | void dm_sysfs_exit(struct mapped_device *md) | ||
97 | { | ||
98 | kobject_put(dm_kobject(md)); | ||
99 | } | ||
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 04e5fd742c2c..2fd66c30f7f8 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Sistina Software (UK) Limited. | 2 | * Copyright (C) 2001 Sistina Software (UK) Limited. |
3 | * Copyright (C) 2004 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This file is released under the GPL. | 5 | * This file is released under the GPL. |
6 | */ | 6 | */ |
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/delay.h> | ||
18 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
19 | 20 | ||
20 | #define DM_MSG_PREFIX "table" | 21 | #define DM_MSG_PREFIX "table" |
@@ -24,6 +25,19 @@ | |||
24 | #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t)) | 25 | #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t)) |
25 | #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) | 26 | #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) |
26 | 27 | ||
28 | /* | ||
29 | * The table has always exactly one reference from either mapped_device->map | ||
30 | * or hash_cell->new_map. This reference is not counted in table->holders. | ||
31 | * A pair of dm_create_table/dm_destroy_table functions is used for table | ||
32 | * creation/destruction. | ||
33 | * | ||
34 | * Temporary references from the other code increase table->holders. A pair | ||
35 | * of dm_table_get/dm_table_put functions is used to manipulate it. | ||
36 | * | ||
37 | * When the table is about to be destroyed, we wait for table->holders to | ||
38 | * drop to zero. | ||
39 | */ | ||
40 | |||
27 | struct dm_table { | 41 | struct dm_table { |
28 | struct mapped_device *md; | 42 | struct mapped_device *md; |
29 | atomic_t holders; | 43 | atomic_t holders; |
@@ -38,6 +52,8 @@ struct dm_table { | |||
38 | sector_t *highs; | 52 | sector_t *highs; |
39 | struct dm_target *targets; | 53 | struct dm_target *targets; |
40 | 54 | ||
55 | unsigned barriers_supported:1; | ||
56 | |||
41 | /* | 57 | /* |
42 | * Indicates the rw permissions for the new logical | 58 | * Indicates the rw permissions for the new logical |
43 | * device. This should be a combination of FMODE_READ | 59 | * device. This should be a combination of FMODE_READ |
@@ -226,7 +242,8 @@ int dm_table_create(struct dm_table **result, fmode_t mode, | |||
226 | return -ENOMEM; | 242 | return -ENOMEM; |
227 | 243 | ||
228 | INIT_LIST_HEAD(&t->devices); | 244 | INIT_LIST_HEAD(&t->devices); |
229 | atomic_set(&t->holders, 1); | 245 | atomic_set(&t->holders, 0); |
246 | t->barriers_supported = 1; | ||
230 | 247 | ||
231 | if (!num_targets) | 248 | if (!num_targets) |
232 | num_targets = KEYS_PER_NODE; | 249 | num_targets = KEYS_PER_NODE; |
@@ -256,10 +273,14 @@ static void free_devices(struct list_head *devices) | |||
256 | } | 273 | } |
257 | } | 274 | } |
258 | 275 | ||
259 | static void table_destroy(struct dm_table *t) | 276 | void dm_table_destroy(struct dm_table *t) |
260 | { | 277 | { |
261 | unsigned int i; | 278 | unsigned int i; |
262 | 279 | ||
280 | while (atomic_read(&t->holders)) | ||
281 | msleep(1); | ||
282 | smp_mb(); | ||
283 | |||
263 | /* free the indexes (see dm_table_complete) */ | 284 | /* free the indexes (see dm_table_complete) */ |
264 | if (t->depth >= 2) | 285 | if (t->depth >= 2) |
265 | vfree(t->index[t->depth - 2]); | 286 | vfree(t->index[t->depth - 2]); |
@@ -297,8 +318,8 @@ void dm_table_put(struct dm_table *t) | |||
297 | if (!t) | 318 | if (!t) |
298 | return; | 319 | return; |
299 | 320 | ||
300 | if (atomic_dec_and_test(&t->holders)) | 321 | smp_mb__before_atomic_dec(); |
301 | table_destroy(t); | 322 | atomic_dec(&t->holders); |
302 | } | 323 | } |
303 | 324 | ||
304 | /* | 325 | /* |
@@ -728,6 +749,10 @@ int dm_table_add_target(struct dm_table *t, const char *type, | |||
728 | /* FIXME: the plan is to combine high here and then have | 749 | /* FIXME: the plan is to combine high here and then have |
729 | * the merge fn apply the target level restrictions. */ | 750 | * the merge fn apply the target level restrictions. */ |
730 | combine_restrictions_low(&t->limits, &tgt->limits); | 751 | combine_restrictions_low(&t->limits, &tgt->limits); |
752 | |||
753 | if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS)) | ||
754 | t->barriers_supported = 0; | ||
755 | |||
731 | return 0; | 756 | return 0; |
732 | 757 | ||
733 | bad: | 758 | bad: |
@@ -772,6 +797,12 @@ int dm_table_complete(struct dm_table *t) | |||
772 | 797 | ||
773 | check_for_valid_limits(&t->limits); | 798 | check_for_valid_limits(&t->limits); |
774 | 799 | ||
800 | /* | ||
801 | * We only support barriers if there is exactly one underlying device. | ||
802 | */ | ||
803 | if (!list_is_singular(&t->devices)) | ||
804 | t->barriers_supported = 0; | ||
805 | |||
775 | /* how many indexes will the btree have ? */ | 806 | /* how many indexes will the btree have ? */ |
776 | leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); | 807 | leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE); |
777 | t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); | 808 | t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE); |
@@ -986,6 +1017,12 @@ struct mapped_device *dm_table_get_md(struct dm_table *t) | |||
986 | return t->md; | 1017 | return t->md; |
987 | } | 1018 | } |
988 | 1019 | ||
1020 | int dm_table_barrier_ok(struct dm_table *t) | ||
1021 | { | ||
1022 | return t->barriers_supported; | ||
1023 | } | ||
1024 | EXPORT_SYMBOL(dm_table_barrier_ok); | ||
1025 | |||
989 | EXPORT_SYMBOL(dm_vcalloc); | 1026 | EXPORT_SYMBOL(dm_vcalloc); |
990 | EXPORT_SYMBOL(dm_get_device); | 1027 | EXPORT_SYMBOL(dm_get_device); |
991 | EXPORT_SYMBOL(dm_put_device); | 1028 | EXPORT_SYMBOL(dm_put_device); |
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c index 835cf95b857f..7decf10006e4 100644 --- a/drivers/md/dm-target.c +++ b/drivers/md/dm-target.c | |||
@@ -130,26 +130,26 @@ int dm_register_target(struct target_type *t) | |||
130 | return rv; | 130 | return rv; |
131 | } | 131 | } |
132 | 132 | ||
133 | int dm_unregister_target(struct target_type *t) | 133 | void dm_unregister_target(struct target_type *t) |
134 | { | 134 | { |
135 | struct tt_internal *ti; | 135 | struct tt_internal *ti; |
136 | 136 | ||
137 | down_write(&_lock); | 137 | down_write(&_lock); |
138 | if (!(ti = __find_target_type(t->name))) { | 138 | if (!(ti = __find_target_type(t->name))) { |
139 | up_write(&_lock); | 139 | DMCRIT("Unregistering unrecognised target: %s", t->name); |
140 | return -EINVAL; | 140 | BUG(); |
141 | } | 141 | } |
142 | 142 | ||
143 | if (ti->use) { | 143 | if (ti->use) { |
144 | up_write(&_lock); | 144 | DMCRIT("Attempt to unregister target still in use: %s", |
145 | return -ETXTBSY; | 145 | t->name); |
146 | BUG(); | ||
146 | } | 147 | } |
147 | 148 | ||
148 | list_del(&ti->list); | 149 | list_del(&ti->list); |
149 | kfree(ti); | 150 | kfree(ti); |
150 | 151 | ||
151 | up_write(&_lock); | 152 | up_write(&_lock); |
152 | return 0; | ||
153 | } | 153 | } |
154 | 154 | ||
155 | /* | 155 | /* |
@@ -187,8 +187,7 @@ int __init dm_target_init(void) | |||
187 | 187 | ||
188 | void dm_target_exit(void) | 188 | void dm_target_exit(void) |
189 | { | 189 | { |
190 | if (dm_unregister_target(&error_target)) | 190 | dm_unregister_target(&error_target); |
191 | DMWARN("error target unregistration failed"); | ||
192 | } | 191 | } |
193 | 192 | ||
194 | EXPORT_SYMBOL(dm_register_target); | 193 | EXPORT_SYMBOL(dm_register_target); |
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c index cdbf126ec106..bbc97030c0c2 100644 --- a/drivers/md/dm-zero.c +++ b/drivers/md/dm-zero.c | |||
@@ -69,10 +69,7 @@ static int __init dm_zero_init(void) | |||
69 | 69 | ||
70 | static void __exit dm_zero_exit(void) | 70 | static void __exit dm_zero_exit(void) |
71 | { | 71 | { |
72 | int r = dm_unregister_target(&zero_target); | 72 | dm_unregister_target(&zero_target); |
73 | |||
74 | if (r < 0) | ||
75 | DMERR("unregister failed %d", r); | ||
76 | } | 73 | } |
77 | 74 | ||
78 | module_init(dm_zero_init) | 75 | module_init(dm_zero_init) |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 421c9f02d8ca..51ba1db4b3e7 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. | 2 | * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This file is released under the GPL. | 5 | * This file is released under the GPL. |
6 | */ | 6 | */ |
@@ -32,6 +32,7 @@ static unsigned int _major = 0; | |||
32 | 32 | ||
33 | static DEFINE_SPINLOCK(_minor_lock); | 33 | static DEFINE_SPINLOCK(_minor_lock); |
34 | /* | 34 | /* |
35 | * For bio-based dm. | ||
35 | * One of these is allocated per bio. | 36 | * One of these is allocated per bio. |
36 | */ | 37 | */ |
37 | struct dm_io { | 38 | struct dm_io { |
@@ -43,6 +44,7 @@ struct dm_io { | |||
43 | }; | 44 | }; |
44 | 45 | ||
45 | /* | 46 | /* |
47 | * For bio-based dm. | ||
46 | * One of these is allocated per target within a bio. Hopefully | 48 | * One of these is allocated per target within a bio. Hopefully |
47 | * this will be simplified out one day. | 49 | * this will be simplified out one day. |
48 | */ | 50 | */ |
@@ -54,6 +56,27 @@ struct dm_target_io { | |||
54 | 56 | ||
55 | DEFINE_TRACE(block_bio_complete); | 57 | DEFINE_TRACE(block_bio_complete); |
56 | 58 | ||
59 | /* | ||
60 | * For request-based dm. | ||
61 | * One of these is allocated per request. | ||
62 | */ | ||
63 | struct dm_rq_target_io { | ||
64 | struct mapped_device *md; | ||
65 | struct dm_target *ti; | ||
66 | struct request *orig, clone; | ||
67 | int error; | ||
68 | union map_info info; | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * For request-based dm. | ||
73 | * One of these is allocated per bio. | ||
74 | */ | ||
75 | struct dm_rq_clone_bio_info { | ||
76 | struct bio *orig; | ||
77 | struct request *rq; | ||
78 | }; | ||
79 | |||
57 | union map_info *dm_get_mapinfo(struct bio *bio) | 80 | union map_info *dm_get_mapinfo(struct bio *bio) |
58 | { | 81 | { |
59 | if (bio && bio->bi_private) | 82 | if (bio && bio->bi_private) |
@@ -144,11 +167,16 @@ struct mapped_device { | |||
144 | 167 | ||
145 | /* forced geometry settings */ | 168 | /* forced geometry settings */ |
146 | struct hd_geometry geometry; | 169 | struct hd_geometry geometry; |
170 | |||
171 | /* sysfs handle */ | ||
172 | struct kobject kobj; | ||
147 | }; | 173 | }; |
148 | 174 | ||
149 | #define MIN_IOS 256 | 175 | #define MIN_IOS 256 |
150 | static struct kmem_cache *_io_cache; | 176 | static struct kmem_cache *_io_cache; |
151 | static struct kmem_cache *_tio_cache; | 177 | static struct kmem_cache *_tio_cache; |
178 | static struct kmem_cache *_rq_tio_cache; | ||
179 | static struct kmem_cache *_rq_bio_info_cache; | ||
152 | 180 | ||
153 | static int __init local_init(void) | 181 | static int __init local_init(void) |
154 | { | 182 | { |
@@ -164,9 +192,17 @@ static int __init local_init(void) | |||
164 | if (!_tio_cache) | 192 | if (!_tio_cache) |
165 | goto out_free_io_cache; | 193 | goto out_free_io_cache; |
166 | 194 | ||
195 | _rq_tio_cache = KMEM_CACHE(dm_rq_target_io, 0); | ||
196 | if (!_rq_tio_cache) | ||
197 | goto out_free_tio_cache; | ||
198 | |||
199 | _rq_bio_info_cache = KMEM_CACHE(dm_rq_clone_bio_info, 0); | ||
200 | if (!_rq_bio_info_cache) | ||
201 | goto out_free_rq_tio_cache; | ||
202 | |||
167 | r = dm_uevent_init(); | 203 | r = dm_uevent_init(); |
168 | if (r) | 204 | if (r) |
169 | goto out_free_tio_cache; | 205 | goto out_free_rq_bio_info_cache; |
170 | 206 | ||
171 | _major = major; | 207 | _major = major; |
172 | r = register_blkdev(_major, _name); | 208 | r = register_blkdev(_major, _name); |
@@ -180,6 +216,10 @@ static int __init local_init(void) | |||
180 | 216 | ||
181 | out_uevent_exit: | 217 | out_uevent_exit: |
182 | dm_uevent_exit(); | 218 | dm_uevent_exit(); |
219 | out_free_rq_bio_info_cache: | ||
220 | kmem_cache_destroy(_rq_bio_info_cache); | ||
221 | out_free_rq_tio_cache: | ||
222 | kmem_cache_destroy(_rq_tio_cache); | ||
183 | out_free_tio_cache: | 223 | out_free_tio_cache: |
184 | kmem_cache_destroy(_tio_cache); | 224 | kmem_cache_destroy(_tio_cache); |
185 | out_free_io_cache: | 225 | out_free_io_cache: |
@@ -190,6 +230,8 @@ out_free_io_cache: | |||
190 | 230 | ||
191 | static void local_exit(void) | 231 | static void local_exit(void) |
192 | { | 232 | { |
233 | kmem_cache_destroy(_rq_bio_info_cache); | ||
234 | kmem_cache_destroy(_rq_tio_cache); | ||
193 | kmem_cache_destroy(_tio_cache); | 235 | kmem_cache_destroy(_tio_cache); |
194 | kmem_cache_destroy(_io_cache); | 236 | kmem_cache_destroy(_io_cache); |
195 | unregister_blkdev(_major, _name); | 237 | unregister_blkdev(_major, _name); |
@@ -796,7 +838,11 @@ static int __split_bio(struct mapped_device *md, struct bio *bio) | |||
796 | ci.map = dm_get_table(md); | 838 | ci.map = dm_get_table(md); |
797 | if (unlikely(!ci.map)) | 839 | if (unlikely(!ci.map)) |
798 | return -EIO; | 840 | return -EIO; |
799 | 841 | if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) { | |
842 | dm_table_put(ci.map); | ||
843 | bio_endio(bio, -EOPNOTSUPP); | ||
844 | return 0; | ||
845 | } | ||
800 | ci.md = md; | 846 | ci.md = md; |
801 | ci.bio = bio; | 847 | ci.bio = bio; |
802 | ci.io = alloc_io(md); | 848 | ci.io = alloc_io(md); |
@@ -880,15 +926,6 @@ static int dm_request(struct request_queue *q, struct bio *bio) | |||
880 | struct mapped_device *md = q->queuedata; | 926 | struct mapped_device *md = q->queuedata; |
881 | int cpu; | 927 | int cpu; |
882 | 928 | ||
883 | /* | ||
884 | * There is no use in forwarding any barrier request since we can't | ||
885 | * guarantee it is (or can be) handled by the targets correctly. | ||
886 | */ | ||
887 | if (unlikely(bio_barrier(bio))) { | ||
888 | bio_endio(bio, -EOPNOTSUPP); | ||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | down_read(&md->io_lock); | 929 | down_read(&md->io_lock); |
893 | 930 | ||
894 | cpu = part_stat_lock(); | 931 | cpu = part_stat_lock(); |
@@ -943,8 +980,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits) | |||
943 | struct mapped_device *md = congested_data; | 980 | struct mapped_device *md = congested_data; |
944 | struct dm_table *map; | 981 | struct dm_table *map; |
945 | 982 | ||
946 | atomic_inc(&md->pending); | ||
947 | |||
948 | if (!test_bit(DMF_BLOCK_IO, &md->flags)) { | 983 | if (!test_bit(DMF_BLOCK_IO, &md->flags)) { |
949 | map = dm_get_table(md); | 984 | map = dm_get_table(md); |
950 | if (map) { | 985 | if (map) { |
@@ -953,10 +988,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits) | |||
953 | } | 988 | } |
954 | } | 989 | } |
955 | 990 | ||
956 | if (!atomic_dec_return(&md->pending)) | ||
957 | /* nudge anyone waiting on suspend queue */ | ||
958 | wake_up(&md->wait); | ||
959 | |||
960 | return r; | 991 | return r; |
961 | } | 992 | } |
962 | 993 | ||
@@ -1216,10 +1247,12 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
1216 | 1247 | ||
1217 | if (md->suspended_bdev) | 1248 | if (md->suspended_bdev) |
1218 | __set_size(md, size); | 1249 | __set_size(md, size); |
1219 | if (size == 0) | 1250 | |
1251 | if (!size) { | ||
1252 | dm_table_destroy(t); | ||
1220 | return 0; | 1253 | return 0; |
1254 | } | ||
1221 | 1255 | ||
1222 | dm_table_get(t); | ||
1223 | dm_table_event_callback(t, event_callback, md); | 1256 | dm_table_event_callback(t, event_callback, md); |
1224 | 1257 | ||
1225 | write_lock(&md->map_lock); | 1258 | write_lock(&md->map_lock); |
@@ -1241,7 +1274,7 @@ static void __unbind(struct mapped_device *md) | |||
1241 | write_lock(&md->map_lock); | 1274 | write_lock(&md->map_lock); |
1242 | md->map = NULL; | 1275 | md->map = NULL; |
1243 | write_unlock(&md->map_lock); | 1276 | write_unlock(&md->map_lock); |
1244 | dm_table_put(map); | 1277 | dm_table_destroy(map); |
1245 | } | 1278 | } |
1246 | 1279 | ||
1247 | /* | 1280 | /* |
@@ -1255,6 +1288,8 @@ int dm_create(int minor, struct mapped_device **result) | |||
1255 | if (!md) | 1288 | if (!md) |
1256 | return -ENXIO; | 1289 | return -ENXIO; |
1257 | 1290 | ||
1291 | dm_sysfs_init(md); | ||
1292 | |||
1258 | *result = md; | 1293 | *result = md; |
1259 | return 0; | 1294 | return 0; |
1260 | } | 1295 | } |
@@ -1330,8 +1365,9 @@ void dm_put(struct mapped_device *md) | |||
1330 | dm_table_presuspend_targets(map); | 1365 | dm_table_presuspend_targets(map); |
1331 | dm_table_postsuspend_targets(map); | 1366 | dm_table_postsuspend_targets(map); |
1332 | } | 1367 | } |
1333 | __unbind(md); | 1368 | dm_sysfs_exit(md); |
1334 | dm_table_put(map); | 1369 | dm_table_put(map); |
1370 | __unbind(md); | ||
1335 | free_dev(md); | 1371 | free_dev(md); |
1336 | } | 1372 | } |
1337 | } | 1373 | } |
@@ -1669,6 +1705,27 @@ struct gendisk *dm_disk(struct mapped_device *md) | |||
1669 | return md->disk; | 1705 | return md->disk; |
1670 | } | 1706 | } |
1671 | 1707 | ||
1708 | struct kobject *dm_kobject(struct mapped_device *md) | ||
1709 | { | ||
1710 | return &md->kobj; | ||
1711 | } | ||
1712 | |||
1713 | /* | ||
1714 | * struct mapped_device should not be exported outside of dm.c | ||
1715 | * so use this check to verify that kobj is part of md structure | ||
1716 | */ | ||
1717 | struct mapped_device *dm_get_from_kobject(struct kobject *kobj) | ||
1718 | { | ||
1719 | struct mapped_device *md; | ||
1720 | |||
1721 | md = container_of(kobj, struct mapped_device, kobj); | ||
1722 | if (&md->kobj != kobj) | ||
1723 | return NULL; | ||
1724 | |||
1725 | dm_get(md); | ||
1726 | return md; | ||
1727 | } | ||
1728 | |||
1672 | int dm_suspended(struct mapped_device *md) | 1729 | int dm_suspended(struct mapped_device *md) |
1673 | { | 1730 | { |
1674 | return test_bit(DMF_SUSPENDED, &md->flags); | 1731 | return test_bit(DMF_SUSPENDED, &md->flags); |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 0ade60cdef42..20194e000c5a 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -36,6 +36,7 @@ struct dm_table; | |||
36 | /*----------------------------------------------------------------- | 36 | /*----------------------------------------------------------------- |
37 | * Internal table functions. | 37 | * Internal table functions. |
38 | *---------------------------------------------------------------*/ | 38 | *---------------------------------------------------------------*/ |
39 | void dm_table_destroy(struct dm_table *t); | ||
39 | void dm_table_event_callback(struct dm_table *t, | 40 | void dm_table_event_callback(struct dm_table *t, |
40 | void (*fn)(void *), void *context); | 41 | void (*fn)(void *), void *context); |
41 | struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); | 42 | struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); |
@@ -51,6 +52,7 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits); | |||
51 | * To check the return value from dm_table_find_target(). | 52 | * To check the return value from dm_table_find_target(). |
52 | */ | 53 | */ |
53 | #define dm_target_is_valid(t) ((t)->table) | 54 | #define dm_target_is_valid(t) ((t)->table) |
55 | int dm_table_barrier_ok(struct dm_table *t); | ||
54 | 56 | ||
55 | /*----------------------------------------------------------------- | 57 | /*----------------------------------------------------------------- |
56 | * A registry of target types. | 58 | * A registry of target types. |
@@ -72,6 +74,14 @@ int dm_interface_init(void); | |||
72 | void dm_interface_exit(void); | 74 | void dm_interface_exit(void); |
73 | 75 | ||
74 | /* | 76 | /* |
77 | * sysfs interface | ||
78 | */ | ||
79 | int dm_sysfs_init(struct mapped_device *md); | ||
80 | void dm_sysfs_exit(struct mapped_device *md); | ||
81 | struct kobject *dm_kobject(struct mapped_device *md); | ||
82 | struct mapped_device *dm_get_from_kobject(struct kobject *kobj); | ||
83 | |||
84 | /* | ||
75 | * Targets for linear and striped mappings | 85 | * Targets for linear and striped mappings |
76 | */ | 86 | */ |
77 | int dm_linear_init(void); | 87 | int dm_linear_init(void); |
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 56faef1a1d55..06c655c55587 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> | 19 | * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> |
20 | * Deepak Saxena <deepak@plexity.net> | 20 | * Deepak Saxena <deepak@plexity.net> |
21 | * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> | 21 | * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> |
22 | * Alan Cox <alan@redhat.com>: | 22 | * Alan Cox <alan@lxorguk.ukuu.org.uk>: |
23 | * Ported to Linux 2.5. | 23 | * Ported to Linux 2.5. |
24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: | 24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: |
25 | * Minor fixes for 2.6. | 25 | * Minor fixes for 2.6. |
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index f3384c32b9a1..efba7021948a 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() | 19 | * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() |
20 | * Deepak Saxena (11/18/1999): | 20 | * Deepak Saxena (11/18/1999): |
21 | * Added event managmenet support | 21 | * Added event managmenet support |
22 | * Alan Cox <alan@redhat.com>: | 22 | * Alan Cox <alan@lxorguk.ukuu.org.uk>: |
23 | * 2.4 rewrite ported to 2.5 | 23 | * 2.4 rewrite ported to 2.5 |
24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: | 24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: |
25 | * Added pass-thru support for Adaptec's raidutils | 25 | * Added pass-thru support for Adaptec's raidutils |
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 6e53a30bfd38..35c67d1f255e 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> | 19 | * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> |
20 | * Deepak Saxena <deepak@plexity.net> | 20 | * Deepak Saxena <deepak@plexity.net> |
21 | * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> | 21 | * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> |
22 | * Alan Cox <alan@redhat.com>: | 22 | * Alan Cox <alan@lxorguk.ukuu.org.uk>: |
23 | * Ported to Linux 2.5. | 23 | * Ported to Linux 2.5. |
24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: | 24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: |
25 | * Minor fixes for 2.6. | 25 | * Minor fixes for 2.6. |
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 610ef1204e68..25d6f2341983 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
@@ -19,7 +19,7 @@ | |||
19 | * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> | 19 | * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> |
20 | * Deepak Saxena <deepak@plexity.net> | 20 | * Deepak Saxena <deepak@plexity.net> |
21 | * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> | 21 | * Boji T Kannanthanam <boji.t.kannanthanam@intel.com> |
22 | * Alan Cox <alan@redhat.com>: | 22 | * Alan Cox <alan@lxorguk.ukuu.org.uk>: |
23 | * Ported to Linux 2.5. | 23 | * Ported to Linux 2.5. |
24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: | 24 | * Markus Lidel <Markus.Lidel@shadowconnect.com>: |
25 | * Minor fixes for 2.6. | 25 | * Minor fixes for 2.6. |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 257277394f8c..416f9e7286ba 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -34,6 +34,14 @@ config MFD_ASIC3 | |||
34 | This driver supports the ASIC3 multifunction chip found on many | 34 | This driver supports the ASIC3 multifunction chip found on many |
35 | PDAs (mainly iPAQ and HTC based ones) | 35 | PDAs (mainly iPAQ and HTC based ones) |
36 | 36 | ||
37 | config MFD_DM355EVM_MSP | ||
38 | bool "DaVinci DM355 EVM microcontroller" | ||
39 | depends on I2C && MACH_DAVINCI_DM355_EVM | ||
40 | help | ||
41 | This driver supports the MSP430 microcontroller used on these | ||
42 | boards. MSP430 firmware manages resets and power sequencing, | ||
43 | inputs from buttons and the IR remote, LEDs, an RTC, and more. | ||
44 | |||
37 | config HTC_EGPIO | 45 | config HTC_EGPIO |
38 | bool "HTC EGPIO support" | 46 | bool "HTC EGPIO support" |
39 | depends on GENERIC_HARDIRQS && GPIOLIB && ARM | 47 | depends on GENERIC_HARDIRQS && GPIOLIB && ARM |
@@ -61,9 +69,32 @@ config UCB1400_CORE | |||
61 | To compile this driver as a module, choose M here: the | 69 | To compile this driver as a module, choose M here: the |
62 | module will be called ucb1400_core. | 70 | module will be called ucb1400_core. |
63 | 71 | ||
72 | config TPS65010 | ||
73 | tristate "TPS6501x Power Management chips" | ||
74 | depends on I2C && GPIOLIB | ||
75 | default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK | ||
76 | help | ||
77 | If you say yes here you get support for the TPS6501x series of | ||
78 | Power Management chips. These include voltage regulators, | ||
79 | lithium ion/polymer battery charging, and other features that | ||
80 | are often used in portable devices like cell phones and cameras. | ||
81 | |||
82 | This driver can also be built as a module. If so, the module | ||
83 | will be called tps65010. | ||
84 | |||
85 | config MENELAUS | ||
86 | bool "Texas Instruments TWL92330/Menelaus PM chip" | ||
87 | depends on I2C=y && ARCH_OMAP24XX | ||
88 | help | ||
89 | If you say yes here you get support for the Texas Instruments | ||
90 | TWL92330/Menelaus Power Management chip. This include voltage | ||
91 | regulators, Dual slot memory card tranceivers, real-time clock | ||
92 | and other features that are often used in portable devices like | ||
93 | cell phones and PDAs. | ||
94 | |||
64 | config TWL4030_CORE | 95 | config TWL4030_CORE |
65 | bool "Texas Instruments TWL4030/TPS659x0 Support" | 96 | bool "Texas Instruments TWL4030/TPS659x0 Support" |
66 | depends on I2C=y && GENERIC_HARDIRQS && (ARCH_OMAP2 || ARCH_OMAP3) | 97 | depends on I2C=y && GENERIC_HARDIRQS |
67 | help | 98 | help |
68 | Say yes here if you have TWL4030 family chip on your board. | 99 | Say yes here if you have TWL4030 family chip on your board. |
69 | This core driver provides register access and IRQ handling | 100 | This core driver provides register access and IRQ handling |
@@ -116,6 +147,7 @@ config PMIC_DA903X | |||
116 | 147 | ||
117 | config MFD_WM8400 | 148 | config MFD_WM8400 |
118 | tristate "Support Wolfson Microelectronics WM8400" | 149 | tristate "Support Wolfson Microelectronics WM8400" |
150 | select MFD_CORE | ||
119 | depends on I2C | 151 | depends on I2C |
120 | help | 152 | help |
121 | Support for the Wolfson Microelecronics WM8400 PMIC and audio | 153 | Support for the Wolfson Microelecronics WM8400 PMIC and audio |
@@ -142,6 +174,38 @@ config MFD_WM8350_CONFIG_MODE_3 | |||
142 | bool | 174 | bool |
143 | depends on MFD_WM8350 | 175 | depends on MFD_WM8350 |
144 | 176 | ||
177 | config MFD_WM8351_CONFIG_MODE_0 | ||
178 | bool | ||
179 | depends on MFD_WM8350 | ||
180 | |||
181 | config MFD_WM8351_CONFIG_MODE_1 | ||
182 | bool | ||
183 | depends on MFD_WM8350 | ||
184 | |||
185 | config MFD_WM8351_CONFIG_MODE_2 | ||
186 | bool | ||
187 | depends on MFD_WM8350 | ||
188 | |||
189 | config MFD_WM8351_CONFIG_MODE_3 | ||
190 | bool | ||
191 | depends on MFD_WM8350 | ||
192 | |||
193 | config MFD_WM8352_CONFIG_MODE_0 | ||
194 | bool | ||
195 | depends on MFD_WM8350 | ||
196 | |||
197 | config MFD_WM8352_CONFIG_MODE_1 | ||
198 | bool | ||
199 | depends on MFD_WM8350 | ||
200 | |||
201 | config MFD_WM8352_CONFIG_MODE_2 | ||
202 | bool | ||
203 | depends on MFD_WM8350 | ||
204 | |||
205 | config MFD_WM8352_CONFIG_MODE_3 | ||
206 | bool | ||
207 | depends on MFD_WM8350 | ||
208 | |||
145 | config MFD_WM8350_I2C | 209 | config MFD_WM8350_I2C |
146 | tristate "Support Wolfson Microelectronics WM8350 with I2C" | 210 | tristate "Support Wolfson Microelectronics WM8350 with I2C" |
147 | select MFD_WM8350 | 211 | select MFD_WM8350 |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 9a5ad8af9116..0c9418b36c26 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -8,6 +8,8 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o | |||
8 | obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o | 8 | obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o |
9 | obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o | 9 | obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o |
10 | 10 | ||
11 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | ||
12 | |||
11 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o | 13 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o |
12 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o | 14 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o |
13 | obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o | 15 | obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o |
@@ -17,6 +19,9 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o | |||
17 | obj-$(CONFIG_MFD_WM8350) += wm8350.o | 19 | obj-$(CONFIG_MFD_WM8350) += wm8350.o |
18 | obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o | 20 | obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o |
19 | 21 | ||
22 | obj-$(CONFIG_TPS65010) += tps65010.o | ||
23 | obj-$(CONFIG_MENELAUS) += menelaus.o | ||
24 | |||
20 | obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o | 25 | obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o |
21 | 26 | ||
22 | obj-$(CONFIG_MFD_CORE) += mfd-core.o | 27 | obj-$(CONFIG_MFD_CORE) += mfd-core.o |
@@ -31,4 +36,4 @@ obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o | |||
31 | endif | 36 | endif |
32 | obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o | 37 | obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o |
33 | 38 | ||
34 | obj-$(CONFIG_PMIC_DA903X) += da903x.o \ No newline at end of file | 39 | obj-$(CONFIG_PMIC_DA903X) += da903x.o |
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 0b5bd85dfcec..99f8dcfe3d98 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
@@ -151,12 +151,24 @@ int da903x_write(struct device *dev, int reg, uint8_t val) | |||
151 | } | 151 | } |
152 | EXPORT_SYMBOL_GPL(da903x_write); | 152 | EXPORT_SYMBOL_GPL(da903x_write); |
153 | 153 | ||
154 | int da903x_writes(struct device *dev, int reg, int len, uint8_t *val) | ||
155 | { | ||
156 | return __da903x_writes(to_i2c_client(dev), reg, len, val); | ||
157 | } | ||
158 | EXPORT_SYMBOL_GPL(da903x_writes); | ||
159 | |||
154 | int da903x_read(struct device *dev, int reg, uint8_t *val) | 160 | int da903x_read(struct device *dev, int reg, uint8_t *val) |
155 | { | 161 | { |
156 | return __da903x_read(to_i2c_client(dev), reg, val); | 162 | return __da903x_read(to_i2c_client(dev), reg, val); |
157 | } | 163 | } |
158 | EXPORT_SYMBOL_GPL(da903x_read); | 164 | EXPORT_SYMBOL_GPL(da903x_read); |
159 | 165 | ||
166 | int da903x_reads(struct device *dev, int reg, int len, uint8_t *val) | ||
167 | { | ||
168 | return __da903x_reads(to_i2c_client(dev), reg, len, val); | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(da903x_reads); | ||
171 | |||
160 | int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask) | 172 | int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask) |
161 | { | 173 | { |
162 | struct da903x_chip *chip = dev_get_drvdata(dev); | 174 | struct da903x_chip *chip = dev_get_drvdata(dev); |
@@ -435,13 +447,13 @@ static const struct i2c_device_id da903x_id_table[] = { | |||
435 | }; | 447 | }; |
436 | MODULE_DEVICE_TABLE(i2c, da903x_id_table); | 448 | MODULE_DEVICE_TABLE(i2c, da903x_id_table); |
437 | 449 | ||
438 | static int __devexit __remove_subdev(struct device *dev, void *unused) | 450 | static int __remove_subdev(struct device *dev, void *unused) |
439 | { | 451 | { |
440 | platform_device_unregister(to_platform_device(dev)); | 452 | platform_device_unregister(to_platform_device(dev)); |
441 | return 0; | 453 | return 0; |
442 | } | 454 | } |
443 | 455 | ||
444 | static int __devexit da903x_remove_subdevs(struct da903x_chip *chip) | 456 | static int da903x_remove_subdevs(struct da903x_chip *chip) |
445 | { | 457 | { |
446 | return device_for_each_child(chip->dev, NULL, __remove_subdev); | 458 | return device_for_each_child(chip->dev, NULL, __remove_subdev); |
447 | } | 459 | } |
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c new file mode 100644 index 000000000000..4214b3f72426 --- /dev/null +++ b/drivers/mfd/dm355evm_msp.c | |||
@@ -0,0 +1,420 @@ | |||
1 | /* | ||
2 | * dm355evm_msp.c - driver for MSP430 firmware on DM355EVM board | ||
3 | * | ||
4 | * Copyright (C) 2008 David Brownell | ||
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/init.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/leds.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/i2c/dm355evm_msp.h> | ||
21 | |||
22 | |||
23 | /* | ||
24 | * The DM355 is a DaVinci chip with video support but no C64+ DSP. Its | ||
25 | * EVM board has an MSP430 programmed with firmware for various board | ||
26 | * support functions. This driver exposes some of them directly, and | ||
27 | * supports other drivers (e.g. RTC, input) for more complex access. | ||
28 | * | ||
29 | * Because this firmware is entirely board-specific, this file embeds | ||
30 | * knowledge that would be passed as platform_data in a generic driver. | ||
31 | * | ||
32 | * This driver was tested with firmware revision A4. | ||
33 | */ | ||
34 | |||
35 | #if defined(CONFIG_KEYBOARD_DM355EVM) \ | ||
36 | || defined(CONFIG_KEYBOARD_DM355EVM_MODULE) | ||
37 | #define msp_has_keyboard() true | ||
38 | #else | ||
39 | #define msp_has_keyboard() false | ||
40 | #endif | ||
41 | |||
42 | #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) | ||
43 | #define msp_has_leds() true | ||
44 | #else | ||
45 | #define msp_has_leds() false | ||
46 | #endif | ||
47 | |||
48 | #if defined(CONFIG_RTC_DRV_DM355EVM) || defined(CONFIG_RTC_DRV_DM355EVM_MODULE) | ||
49 | #define msp_has_rtc() true | ||
50 | #else | ||
51 | #define msp_has_rtc() false | ||
52 | #endif | ||
53 | |||
54 | #if defined(CONFIG_VIDEO_TVP514X) || defined(CONFIG_VIDEO_TVP514X_MODULE) | ||
55 | #define msp_has_tvp() true | ||
56 | #else | ||
57 | #define msp_has_tvp() false | ||
58 | #endif | ||
59 | |||
60 | |||
61 | /*----------------------------------------------------------------------*/ | ||
62 | |||
63 | /* REVISIT for paranoia's sake, retry reads/writes on error */ | ||
64 | |||
65 | static struct i2c_client *msp430; | ||
66 | |||
67 | /** | ||
68 | * dm355evm_msp_write - Writes a register in dm355evm_msp | ||
69 | * @value: the value to be written | ||
70 | * @reg: register address | ||
71 | * | ||
72 | * Returns result of operation - 0 is success, else negative errno | ||
73 | */ | ||
74 | int dm355evm_msp_write(u8 value, u8 reg) | ||
75 | { | ||
76 | return i2c_smbus_write_byte_data(msp430, reg, value); | ||
77 | } | ||
78 | EXPORT_SYMBOL(dm355evm_msp_write); | ||
79 | |||
80 | /** | ||
81 | * dm355evm_msp_read - Reads a register from dm355evm_msp | ||
82 | * @reg: register address | ||
83 | * | ||
84 | * Returns result of operation - value, or negative errno | ||
85 | */ | ||
86 | int dm355evm_msp_read(u8 reg) | ||
87 | { | ||
88 | return i2c_smbus_read_byte_data(msp430, reg); | ||
89 | } | ||
90 | EXPORT_SYMBOL(dm355evm_msp_read); | ||
91 | |||
92 | /*----------------------------------------------------------------------*/ | ||
93 | |||
94 | /* | ||
95 | * Many of the msp430 pins are just used as fixed-direction GPIOs. | ||
96 | * We could export a few more of them this way, if we wanted. | ||
97 | */ | ||
98 | #define MSP_GPIO(bit,reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit)) | ||
99 | |||
100 | static const u8 msp_gpios[] = { | ||
101 | /* eight leds */ | ||
102 | MSP_GPIO(0, LED), MSP_GPIO(1, LED), | ||
103 | MSP_GPIO(2, LED), MSP_GPIO(3, LED), | ||
104 | MSP_GPIO(4, LED), MSP_GPIO(5, LED), | ||
105 | MSP_GPIO(6, LED), MSP_GPIO(7, LED), | ||
106 | /* SW6 and the NTSC/nPAL jumper */ | ||
107 | MSP_GPIO(0, SWITCH1), MSP_GPIO(1, SWITCH1), | ||
108 | MSP_GPIO(2, SWITCH1), MSP_GPIO(3, SWITCH1), | ||
109 | MSP_GPIO(4, SWITCH1), | ||
110 | }; | ||
111 | |||
112 | #define MSP_GPIO_REG(offset) (msp_gpios[(offset)] >> 3) | ||
113 | #define MSP_GPIO_MASK(offset) BIT(msp_gpios[(offset)] & 0x07) | ||
114 | |||
115 | static int msp_gpio_in(struct gpio_chip *chip, unsigned offset) | ||
116 | { | ||
117 | switch (MSP_GPIO_REG(offset)) { | ||
118 | case DM355EVM_MSP_SWITCH1: | ||
119 | case DM355EVM_MSP_SWITCH2: | ||
120 | case DM355EVM_MSP_SDMMC: | ||
121 | return 0; | ||
122 | default: | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static u8 msp_led_cache; | ||
128 | |||
129 | static int msp_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
130 | { | ||
131 | int reg, status; | ||
132 | |||
133 | reg = MSP_GPIO_REG(offset); | ||
134 | status = dm355evm_msp_read(reg); | ||
135 | if (status < 0) | ||
136 | return status; | ||
137 | if (reg == DM355EVM_MSP_LED) | ||
138 | msp_led_cache = status; | ||
139 | return status & MSP_GPIO_MASK(offset); | ||
140 | } | ||
141 | |||
142 | static int msp_gpio_out(struct gpio_chip *chip, unsigned offset, int value) | ||
143 | { | ||
144 | int mask, bits; | ||
145 | |||
146 | /* NOTE: there are some other signals that could be | ||
147 | * packaged as output GPIOs, but they aren't as useful | ||
148 | * as the LEDs ... so for now we don't. | ||
149 | */ | ||
150 | if (MSP_GPIO_REG(offset) != DM355EVM_MSP_LED) | ||
151 | return -EINVAL; | ||
152 | |||
153 | mask = MSP_GPIO_MASK(offset); | ||
154 | bits = msp_led_cache; | ||
155 | |||
156 | bits &= ~mask; | ||
157 | if (value) | ||
158 | bits |= mask; | ||
159 | msp_led_cache = bits; | ||
160 | |||
161 | return dm355evm_msp_write(bits, DM355EVM_MSP_LED); | ||
162 | } | ||
163 | |||
164 | static void msp_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
165 | { | ||
166 | msp_gpio_out(chip, offset, value); | ||
167 | } | ||
168 | |||
169 | static struct gpio_chip dm355evm_msp_gpio = { | ||
170 | .label = "dm355evm_msp", | ||
171 | .owner = THIS_MODULE, | ||
172 | .direction_input = msp_gpio_in, | ||
173 | .get = msp_gpio_get, | ||
174 | .direction_output = msp_gpio_out, | ||
175 | .set = msp_gpio_set, | ||
176 | .base = -EINVAL, /* dynamic assignment */ | ||
177 | .ngpio = ARRAY_SIZE(msp_gpios), | ||
178 | .can_sleep = true, | ||
179 | }; | ||
180 | |||
181 | /*----------------------------------------------------------------------*/ | ||
182 | |||
183 | static struct device *add_child(struct i2c_client *client, const char *name, | ||
184 | void *pdata, unsigned pdata_len, | ||
185 | bool can_wakeup, int irq) | ||
186 | { | ||
187 | struct platform_device *pdev; | ||
188 | int status; | ||
189 | |||
190 | pdev = platform_device_alloc(name, -1); | ||
191 | if (!pdev) { | ||
192 | dev_dbg(&client->dev, "can't alloc dev\n"); | ||
193 | status = -ENOMEM; | ||
194 | goto err; | ||
195 | } | ||
196 | |||
197 | device_init_wakeup(&pdev->dev, can_wakeup); | ||
198 | pdev->dev.parent = &client->dev; | ||
199 | |||
200 | if (pdata) { | ||
201 | status = platform_device_add_data(pdev, pdata, pdata_len); | ||
202 | if (status < 0) { | ||
203 | dev_dbg(&pdev->dev, "can't add platform_data\n"); | ||
204 | goto err; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | if (irq) { | ||
209 | struct resource r = { | ||
210 | .start = irq, | ||
211 | .flags = IORESOURCE_IRQ, | ||
212 | }; | ||
213 | |||
214 | status = platform_device_add_resources(pdev, &r, 1); | ||
215 | if (status < 0) { | ||
216 | dev_dbg(&pdev->dev, "can't add irq\n"); | ||
217 | goto err; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | status = platform_device_add(pdev); | ||
222 | |||
223 | err: | ||
224 | if (status < 0) { | ||
225 | platform_device_put(pdev); | ||
226 | dev_err(&client->dev, "can't add %s dev\n", name); | ||
227 | return ERR_PTR(status); | ||
228 | } | ||
229 | return &pdev->dev; | ||
230 | } | ||
231 | |||
232 | static int add_children(struct i2c_client *client) | ||
233 | { | ||
234 | static const struct { | ||
235 | int offset; | ||
236 | char *label; | ||
237 | } config_inputs[] = { | ||
238 | /* 8 == right after the LEDs */ | ||
239 | { 8 + 0, "sw6_1", }, | ||
240 | { 8 + 1, "sw6_2", }, | ||
241 | { 8 + 2, "sw6_3", }, | ||
242 | { 8 + 3, "sw6_4", }, | ||
243 | { 8 + 4, "NTSC/nPAL", }, | ||
244 | }; | ||
245 | |||
246 | struct device *child; | ||
247 | int status; | ||
248 | int i; | ||
249 | |||
250 | /* GPIO-ish stuff */ | ||
251 | dm355evm_msp_gpio.dev = &client->dev; | ||
252 | status = gpiochip_add(&dm355evm_msp_gpio); | ||
253 | if (status < 0) | ||
254 | return status; | ||
255 | |||
256 | /* LED output */ | ||
257 | if (msp_has_leds()) { | ||
258 | #define GPIO_LED(l) .name = l, .active_low = true | ||
259 | static struct gpio_led evm_leds[] = { | ||
260 | { GPIO_LED("dm355evm::ds14"), | ||
261 | .default_trigger = "heartbeat", }, | ||
262 | { GPIO_LED("dm355evm::ds15"), | ||
263 | .default_trigger = "mmc0", }, | ||
264 | { GPIO_LED("dm355evm::ds16"), | ||
265 | /* could also be a CE-ATA drive */ | ||
266 | .default_trigger = "mmc1", }, | ||
267 | { GPIO_LED("dm355evm::ds17"), | ||
268 | .default_trigger = "nand-disk", }, | ||
269 | { GPIO_LED("dm355evm::ds18"), }, | ||
270 | { GPIO_LED("dm355evm::ds19"), }, | ||
271 | { GPIO_LED("dm355evm::ds20"), }, | ||
272 | { GPIO_LED("dm355evm::ds21"), }, | ||
273 | }; | ||
274 | #undef GPIO_LED | ||
275 | |||
276 | struct gpio_led_platform_data evm_led_data = { | ||
277 | .num_leds = ARRAY_SIZE(evm_leds), | ||
278 | .leds = evm_leds, | ||
279 | }; | ||
280 | |||
281 | for (i = 0; i < ARRAY_SIZE(evm_leds); i++) | ||
282 | evm_leds[i].gpio = i + dm355evm_msp_gpio.base; | ||
283 | |||
284 | /* NOTE: these are the only fully programmable LEDs | ||
285 | * on the board, since GPIO-61/ds22 (and many signals | ||
286 | * going to DC7) must be used for AEMIF address lines | ||
287 | * unless the top 1 GB of NAND is unused... | ||
288 | */ | ||
289 | child = add_child(client, "leds-gpio", | ||
290 | &evm_led_data, sizeof(evm_led_data), | ||
291 | false, 0); | ||
292 | if (IS_ERR(child)) | ||
293 | return PTR_ERR(child); | ||
294 | } | ||
295 | |||
296 | /* configuration inputs */ | ||
297 | for (i = 0; i < ARRAY_SIZE(config_inputs); i++) { | ||
298 | int gpio = dm355evm_msp_gpio.base + config_inputs[i].offset; | ||
299 | |||
300 | gpio_request(gpio, config_inputs[i].label); | ||
301 | gpio_direction_input(gpio); | ||
302 | |||
303 | /* make it easy for userspace to see these */ | ||
304 | gpio_export(gpio, false); | ||
305 | } | ||
306 | |||
307 | /* RTC is a 32 bit counter, no alarm */ | ||
308 | if (msp_has_rtc()) { | ||
309 | child = add_child(client, "rtc-dm355evm", | ||
310 | NULL, 0, false, 0); | ||
311 | if (IS_ERR(child)) | ||
312 | return PTR_ERR(child); | ||
313 | } | ||
314 | |||
315 | /* input from buttons and IR remote (uses the IRQ) */ | ||
316 | if (msp_has_keyboard()) { | ||
317 | child = add_child(client, "dm355evm_keys", | ||
318 | NULL, 0, true, client->irq); | ||
319 | if (IS_ERR(child)) | ||
320 | return PTR_ERR(child); | ||
321 | } | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | /*----------------------------------------------------------------------*/ | ||
327 | |||
328 | static void dm355evm_command(unsigned command) | ||
329 | { | ||
330 | int status; | ||
331 | |||
332 | status = dm355evm_msp_write(command, DM355EVM_MSP_COMMAND); | ||
333 | if (status < 0) | ||
334 | dev_err(&msp430->dev, "command %d failure %d\n", | ||
335 | command, status); | ||
336 | } | ||
337 | |||
338 | static void dm355evm_power_off(void) | ||
339 | { | ||
340 | dm355evm_command(MSP_COMMAND_POWEROFF); | ||
341 | } | ||
342 | |||
343 | static int dm355evm_msp_remove(struct i2c_client *client) | ||
344 | { | ||
345 | pm_power_off = NULL; | ||
346 | msp430 = NULL; | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static int | ||
351 | dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
352 | { | ||
353 | int status; | ||
354 | const char *video = msp_has_tvp() ? "TVP5146" : "imager"; | ||
355 | |||
356 | if (msp430) | ||
357 | return -EBUSY; | ||
358 | msp430 = client; | ||
359 | |||
360 | /* display revision status; doubles as sanity check */ | ||
361 | status = dm355evm_msp_read(DM355EVM_MSP_FIRMREV); | ||
362 | if (status < 0) | ||
363 | goto fail; | ||
364 | dev_info(&client->dev, "firmware v.%02X, %s as video-in\n", | ||
365 | status, video); | ||
366 | |||
367 | /* mux video input: either tvp5146 or some external imager */ | ||
368 | status = dm355evm_msp_write(msp_has_tvp() ? 0 : MSP_VIDEO_IMAGER, | ||
369 | DM355EVM_MSP_VIDEO_IN); | ||
370 | if (status < 0) | ||
371 | dev_warn(&client->dev, "error %d muxing %s as video-in\n", | ||
372 | status, video); | ||
373 | |||
374 | /* init LED cache, and turn off the LEDs */ | ||
375 | msp_led_cache = 0xff; | ||
376 | dm355evm_msp_write(msp_led_cache, DM355EVM_MSP_LED); | ||
377 | |||
378 | /* export capabilities we support */ | ||
379 | status = add_children(client); | ||
380 | if (status < 0) | ||
381 | goto fail; | ||
382 | |||
383 | /* PM hookup */ | ||
384 | pm_power_off = dm355evm_power_off; | ||
385 | |||
386 | return 0; | ||
387 | |||
388 | fail: | ||
389 | /* FIXME remove children ... */ | ||
390 | dm355evm_msp_remove(client); | ||
391 | return status; | ||
392 | } | ||
393 | |||
394 | static const struct i2c_device_id dm355evm_msp_ids[] = { | ||
395 | { "dm355evm_msp", 0 }, | ||
396 | { /* end of list */ }, | ||
397 | }; | ||
398 | MODULE_DEVICE_TABLE(i2c, dm355evm_msp_ids); | ||
399 | |||
400 | static struct i2c_driver dm355evm_msp_driver = { | ||
401 | .driver.name = "dm355evm_msp", | ||
402 | .id_table = dm355evm_msp_ids, | ||
403 | .probe = dm355evm_msp_probe, | ||
404 | .remove = dm355evm_msp_remove, | ||
405 | }; | ||
406 | |||
407 | static int __init dm355evm_msp_init(void) | ||
408 | { | ||
409 | return i2c_add_driver(&dm355evm_msp_driver); | ||
410 | } | ||
411 | subsys_initcall(dm355evm_msp_init); | ||
412 | |||
413 | static void __exit dm355evm_msp_exit(void) | ||
414 | { | ||
415 | i2c_del_driver(&dm355evm_msp_driver); | ||
416 | } | ||
417 | module_exit(dm355evm_msp_exit); | ||
418 | |||
419 | MODULE_DESCRIPTION("Interface to MSP430 firmware on DM355EVM"); | ||
420 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/mfd/menelaus.c index 4b364bae6b3e..4b364bae6b3e 100644 --- a/drivers/i2c/chips/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 6c0d1bec4b76..54ddf3772e0c 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -34,6 +34,7 @@ static int mfd_add_device(struct device *parent, int id, | |||
34 | goto fail_device; | 34 | goto fail_device; |
35 | 35 | ||
36 | pdev->dev.parent = parent; | 36 | pdev->dev.parent = parent; |
37 | platform_set_drvdata(pdev, cell->driver_data); | ||
37 | 38 | ||
38 | ret = platform_device_add_data(pdev, | 39 | ret = platform_device_add_data(pdev, |
39 | cell->platform_data, cell->data_size); | 40 | cell->platform_data, cell->data_size); |
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/mfd/tps65010.c index acf8b9d5f575..acf8b9d5f575 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/mfd/tps65010.c | |||
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index dd843c4fbcc7..b59c385cbc12 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/clk.h> | 33 | #include <linux/clk.h> |
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | 35 | ||
36 | #include <linux/regulator/machine.h> | ||
37 | |||
36 | #include <linux/i2c.h> | 38 | #include <linux/i2c.h> |
37 | #include <linux/i2c/twl4030.h> | 39 | #include <linux/i2c/twl4030.h> |
38 | 40 | ||
@@ -71,6 +73,13 @@ | |||
71 | #define twl_has_gpio() false | 73 | #define twl_has_gpio() false |
72 | #endif | 74 | #endif |
73 | 75 | ||
76 | #if defined(CONFIG_REGULATOR_TWL4030) \ | ||
77 | || defined(CONFIG_REGULATOR_TWL4030_MODULE) | ||
78 | #define twl_has_regulator() true | ||
79 | #else | ||
80 | #define twl_has_regulator() false | ||
81 | #endif | ||
82 | |||
74 | #if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) | 83 | #if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) |
75 | #define twl_has_madc() true | 84 | #define twl_has_madc() true |
76 | #else | 85 | #else |
@@ -149,6 +158,10 @@ | |||
149 | #define HIGH_PERF_SQ (1 << 3) | 158 | #define HIGH_PERF_SQ (1 << 3) |
150 | 159 | ||
151 | 160 | ||
161 | /* chip-specific feature flags, for i2c_device_id.driver_data */ | ||
162 | #define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ | ||
163 | #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ | ||
164 | |||
152 | /*----------------------------------------------------------------------*/ | 165 | /*----------------------------------------------------------------------*/ |
153 | 166 | ||
154 | /* is driver active, bound to a chip? */ | 167 | /* is driver active, bound to a chip? */ |
@@ -225,7 +238,7 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | |||
225 | * | 238 | * |
226 | * Returns the result of operation - 0 is success | 239 | * Returns the result of operation - 0 is success |
227 | */ | 240 | */ |
228 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes) | 241 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
229 | { | 242 | { |
230 | int ret; | 243 | int ret; |
231 | int sid; | 244 | int sid; |
@@ -274,7 +287,7 @@ EXPORT_SYMBOL(twl4030_i2c_write); | |||
274 | * | 287 | * |
275 | * Returns result of operation - num_bytes is success else failure. | 288 | * Returns result of operation - num_bytes is success else failure. |
276 | */ | 289 | */ |
277 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes) | 290 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
278 | { | 291 | { |
279 | int ret; | 292 | int ret; |
280 | u8 val; | 293 | u8 val; |
@@ -352,258 +365,258 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8); | |||
352 | 365 | ||
353 | /*----------------------------------------------------------------------*/ | 366 | /*----------------------------------------------------------------------*/ |
354 | 367 | ||
355 | /* | 368 | static struct device * |
356 | * NOTE: We know the first 8 IRQs after pdata->base_irq are | 369 | add_numbered_child(unsigned chip, const char *name, int num, |
357 | * for the PIH, and the next are for the PWR_INT SIH, since | 370 | void *pdata, unsigned pdata_len, |
358 | * that's how twl_init_irq() sets things up. | 371 | bool can_wakeup, int irq0, int irq1) |
359 | */ | ||
360 | |||
361 | static int add_children(struct twl4030_platform_data *pdata) | ||
362 | { | 372 | { |
363 | struct platform_device *pdev = NULL; | 373 | struct platform_device *pdev; |
364 | struct twl4030_client *twl = NULL; | 374 | struct twl4030_client *twl = &twl4030_modules[chip]; |
365 | int status = 0; | 375 | int status; |
376 | |||
377 | pdev = platform_device_alloc(name, num); | ||
378 | if (!pdev) { | ||
379 | dev_dbg(&twl->client->dev, "can't alloc dev\n"); | ||
380 | status = -ENOMEM; | ||
381 | goto err; | ||
382 | } | ||
366 | 383 | ||
367 | if (twl_has_bci() && pdata->bci) { | 384 | device_init_wakeup(&pdev->dev, can_wakeup); |
368 | twl = &twl4030_modules[3]; | 385 | pdev->dev.parent = &twl->client->dev; |
369 | 386 | ||
370 | pdev = platform_device_alloc("twl4030_bci", -1); | 387 | if (pdata) { |
371 | if (!pdev) { | 388 | status = platform_device_add_data(pdev, pdata, pdata_len); |
372 | pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME); | 389 | if (status < 0) { |
373 | status = -ENOMEM; | 390 | dev_dbg(&pdev->dev, "can't add platform_data\n"); |
374 | goto err; | 391 | goto err; |
375 | } | 392 | } |
393 | } | ||
376 | 394 | ||
377 | if (status == 0) { | 395 | if (irq0) { |
378 | pdev->dev.parent = &twl->client->dev; | 396 | struct resource r[2] = { |
379 | status = platform_device_add_data(pdev, pdata->bci, | 397 | { .start = irq0, .flags = IORESOURCE_IRQ, }, |
380 | sizeof(*pdata->bci)); | 398 | { .start = irq1, .flags = IORESOURCE_IRQ, }, |
381 | if (status < 0) { | 399 | }; |
382 | dev_dbg(&twl->client->dev, | ||
383 | "can't add bci data, %d\n", | ||
384 | status); | ||
385 | goto err; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | if (status == 0) { | ||
390 | struct resource r = { | ||
391 | .start = pdata->irq_base + 8 + 1, | ||
392 | .flags = IORESOURCE_IRQ, | ||
393 | }; | ||
394 | |||
395 | status = platform_device_add_resources(pdev, &r, 1); | ||
396 | } | ||
397 | |||
398 | if (status == 0) | ||
399 | status = platform_device_add(pdev); | ||
400 | 400 | ||
401 | status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); | ||
401 | if (status < 0) { | 402 | if (status < 0) { |
402 | platform_device_put(pdev); | 403 | dev_dbg(&pdev->dev, "can't add irqs\n"); |
403 | dev_dbg(&twl->client->dev, | ||
404 | "can't create bci dev, %d\n", | ||
405 | status); | ||
406 | goto err; | 404 | goto err; |
407 | } | 405 | } |
408 | } | 406 | } |
409 | 407 | ||
410 | if (twl_has_gpio() && pdata->gpio) { | 408 | status = platform_device_add(pdev); |
411 | twl = &twl4030_modules[1]; | ||
412 | 409 | ||
413 | pdev = platform_device_alloc("twl4030_gpio", -1); | 410 | err: |
414 | if (!pdev) { | 411 | if (status < 0) { |
415 | pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME); | 412 | platform_device_put(pdev); |
416 | status = -ENOMEM; | 413 | dev_err(&twl->client->dev, "can't add %s dev\n", name); |
417 | goto err; | 414 | return ERR_PTR(status); |
418 | } | 415 | } |
416 | return &pdev->dev; | ||
417 | } | ||
419 | 418 | ||
420 | /* more driver model init */ | 419 | static inline struct device *add_child(unsigned chip, const char *name, |
421 | if (status == 0) { | 420 | void *pdata, unsigned pdata_len, |
422 | pdev->dev.parent = &twl->client->dev; | 421 | bool can_wakeup, int irq0, int irq1) |
423 | /* device_init_wakeup(&pdev->dev, 1); */ | 422 | { |
424 | 423 | return add_numbered_child(chip, name, -1, pdata, pdata_len, | |
425 | status = platform_device_add_data(pdev, pdata->gpio, | 424 | can_wakeup, irq0, irq1); |
426 | sizeof(*pdata->gpio)); | 425 | } |
427 | if (status < 0) { | ||
428 | dev_dbg(&twl->client->dev, | ||
429 | "can't add gpio data, %d\n", | ||
430 | status); | ||
431 | goto err; | ||
432 | } | ||
433 | } | ||
434 | 426 | ||
435 | /* GPIO module IRQ */ | 427 | static struct device * |
436 | if (status == 0) { | 428 | add_regulator_linked(int num, struct regulator_init_data *pdata, |
437 | struct resource r = { | 429 | struct regulator_consumer_supply *consumers, |
438 | .start = pdata->irq_base + 0, | 430 | unsigned num_consumers) |
439 | .flags = IORESOURCE_IRQ, | 431 | { |
440 | }; | 432 | /* regulator framework demands init_data ... */ |
433 | if (!pdata) | ||
434 | return NULL; | ||
441 | 435 | ||
442 | status = platform_device_add_resources(pdev, &r, 1); | 436 | if (consumers) { |
443 | } | 437 | pdata->consumer_supplies = consumers; |
438 | pdata->num_consumer_supplies = num_consumers; | ||
439 | } | ||
444 | 440 | ||
445 | if (status == 0) | 441 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ |
446 | status = platform_device_add(pdev); | 442 | return add_numbered_child(3, "twl4030_reg", num, |
443 | pdata, sizeof(*pdata), false, 0, 0); | ||
444 | } | ||
447 | 445 | ||
448 | if (status < 0) { | 446 | static struct device * |
449 | platform_device_put(pdev); | 447 | add_regulator(int num, struct regulator_init_data *pdata) |
450 | dev_dbg(&twl->client->dev, | 448 | { |
451 | "can't create gpio dev, %d\n", | 449 | return add_regulator_linked(num, pdata, NULL, 0); |
452 | status); | 450 | } |
453 | goto err; | 451 | |
454 | } | 452 | /* |
453 | * NOTE: We know the first 8 IRQs after pdata->base_irq are | ||
454 | * for the PIH, and the next are for the PWR_INT SIH, since | ||
455 | * that's how twl_init_irq() sets things up. | ||
456 | */ | ||
457 | |||
458 | static int | ||
459 | add_children(struct twl4030_platform_data *pdata, unsigned long features) | ||
460 | { | ||
461 | struct device *child; | ||
462 | struct device *usb_transceiver = NULL; | ||
463 | |||
464 | if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { | ||
465 | child = add_child(3, "twl4030_bci", | ||
466 | pdata->bci, sizeof(*pdata->bci), | ||
467 | false, | ||
468 | /* irq0 = CHG_PRES, irq1 = BCI */ | ||
469 | pdata->irq_base + 8 + 1, pdata->irq_base + 2); | ||
470 | if (IS_ERR(child)) | ||
471 | return PTR_ERR(child); | ||
472 | } | ||
473 | |||
474 | if (twl_has_gpio() && pdata->gpio) { | ||
475 | child = add_child(1, "twl4030_gpio", | ||
476 | pdata->gpio, sizeof(*pdata->gpio), | ||
477 | false, pdata->irq_base + 0, 0); | ||
478 | if (IS_ERR(child)) | ||
479 | return PTR_ERR(child); | ||
455 | } | 480 | } |
456 | 481 | ||
457 | if (twl_has_keypad() && pdata->keypad) { | 482 | if (twl_has_keypad() && pdata->keypad) { |
458 | pdev = platform_device_alloc("twl4030_keypad", -1); | 483 | child = add_child(2, "twl4030_keypad", |
459 | if (pdev) { | 484 | pdata->keypad, sizeof(*pdata->keypad), |
460 | twl = &twl4030_modules[2]; | 485 | true, pdata->irq_base + 1, 0); |
461 | pdev->dev.parent = &twl->client->dev; | 486 | if (IS_ERR(child)) |
462 | device_init_wakeup(&pdev->dev, 1); | 487 | return PTR_ERR(child); |
463 | status = platform_device_add_data(pdev, pdata->keypad, | ||
464 | sizeof(*pdata->keypad)); | ||
465 | if (status < 0) { | ||
466 | dev_dbg(&twl->client->dev, | ||
467 | "can't add keypad data, %d\n", | ||
468 | status); | ||
469 | platform_device_put(pdev); | ||
470 | goto err; | ||
471 | } | ||
472 | status = platform_device_add(pdev); | ||
473 | if (status < 0) { | ||
474 | platform_device_put(pdev); | ||
475 | dev_dbg(&twl->client->dev, | ||
476 | "can't create keypad dev, %d\n", | ||
477 | status); | ||
478 | goto err; | ||
479 | } | ||
480 | } else { | ||
481 | pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME); | ||
482 | status = -ENOMEM; | ||
483 | goto err; | ||
484 | } | ||
485 | } | 488 | } |
486 | 489 | ||
487 | if (twl_has_madc() && pdata->madc) { | 490 | if (twl_has_madc() && pdata->madc) { |
488 | pdev = platform_device_alloc("twl4030_madc", -1); | 491 | child = add_child(2, "twl4030_madc", |
489 | if (pdev) { | 492 | pdata->madc, sizeof(*pdata->madc), |
490 | twl = &twl4030_modules[2]; | 493 | true, pdata->irq_base + 3, 0); |
491 | pdev->dev.parent = &twl->client->dev; | 494 | if (IS_ERR(child)) |
492 | device_init_wakeup(&pdev->dev, 1); | 495 | return PTR_ERR(child); |
493 | status = platform_device_add_data(pdev, pdata->madc, | ||
494 | sizeof(*pdata->madc)); | ||
495 | if (status < 0) { | ||
496 | platform_device_put(pdev); | ||
497 | dev_dbg(&twl->client->dev, | ||
498 | "can't add madc data, %d\n", | ||
499 | status); | ||
500 | goto err; | ||
501 | } | ||
502 | status = platform_device_add(pdev); | ||
503 | if (status < 0) { | ||
504 | platform_device_put(pdev); | ||
505 | dev_dbg(&twl->client->dev, | ||
506 | "can't create madc dev, %d\n", | ||
507 | status); | ||
508 | goto err; | ||
509 | } | ||
510 | } else { | ||
511 | pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME); | ||
512 | status = -ENOMEM; | ||
513 | goto err; | ||
514 | } | ||
515 | } | 496 | } |
516 | 497 | ||
517 | if (twl_has_rtc()) { | 498 | if (twl_has_rtc()) { |
518 | twl = &twl4030_modules[3]; | ||
519 | |||
520 | pdev = platform_device_alloc("twl4030_rtc", -1); | ||
521 | if (!pdev) { | ||
522 | pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME); | ||
523 | status = -ENOMEM; | ||
524 | } else { | ||
525 | pdev->dev.parent = &twl->client->dev; | ||
526 | device_init_wakeup(&pdev->dev, 1); | ||
527 | } | ||
528 | |||
529 | /* | 499 | /* |
530 | * REVISIT platform_data here currently might use of | 500 | * REVISIT platform_data here currently might expose the |
531 | * "msecure" line ... but for now we just expect board | 501 | * "msecure" line ... but for now we just expect board |
532 | * setup to tell the chip "we are secure" at all times. | 502 | * setup to tell the chip "it's always ok to SET_TIME". |
533 | * Eventually, Linux might become more aware of such | 503 | * Eventually, Linux might become more aware of such |
534 | * HW security concerns, and "least privilege". | 504 | * HW security concerns, and "least privilege". |
535 | */ | 505 | */ |
536 | 506 | child = add_child(3, "twl4030_rtc", | |
537 | /* RTC module IRQ */ | 507 | NULL, 0, |
538 | if (status == 0) { | 508 | true, pdata->irq_base + 8 + 3, 0); |
539 | struct resource r = { | 509 | if (IS_ERR(child)) |
540 | .start = pdata->irq_base + 8 + 3, | 510 | return PTR_ERR(child); |
541 | .flags = IORESOURCE_IRQ, | ||
542 | }; | ||
543 | |||
544 | status = platform_device_add_resources(pdev, &r, 1); | ||
545 | } | ||
546 | |||
547 | if (status == 0) | ||
548 | status = platform_device_add(pdev); | ||
549 | |||
550 | if (status < 0) { | ||
551 | platform_device_put(pdev); | ||
552 | dev_dbg(&twl->client->dev, | ||
553 | "can't create rtc dev, %d\n", | ||
554 | status); | ||
555 | goto err; | ||
556 | } | ||
557 | } | 511 | } |
558 | 512 | ||
559 | if (twl_has_usb() && pdata->usb) { | 513 | if (twl_has_usb() && pdata->usb) { |
560 | twl = &twl4030_modules[0]; | 514 | child = add_child(0, "twl4030_usb", |
561 | 515 | pdata->usb, sizeof(*pdata->usb), | |
562 | pdev = platform_device_alloc("twl4030_usb", -1); | 516 | true, |
563 | if (!pdev) { | 517 | /* irq0 = USB_PRES, irq1 = USB */ |
564 | pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME); | 518 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); |
565 | status = -ENOMEM; | 519 | if (IS_ERR(child)) |
566 | goto err; | 520 | return PTR_ERR(child); |
567 | } | 521 | |
568 | 522 | /* we need to connect regulators to this transceiver */ | |
569 | if (status == 0) { | 523 | usb_transceiver = child; |
570 | pdev->dev.parent = &twl->client->dev; | 524 | } |
571 | device_init_wakeup(&pdev->dev, 1); | ||
572 | status = platform_device_add_data(pdev, pdata->usb, | ||
573 | sizeof(*pdata->usb)); | ||
574 | if (status < 0) { | ||
575 | platform_device_put(pdev); | ||
576 | dev_dbg(&twl->client->dev, | ||
577 | "can't add usb data, %d\n", | ||
578 | status); | ||
579 | goto err; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if (status == 0) { | ||
584 | struct resource r = { | ||
585 | .start = pdata->irq_base + 8 + 2, | ||
586 | .flags = IORESOURCE_IRQ, | ||
587 | }; | ||
588 | 525 | ||
589 | status = platform_device_add_resources(pdev, &r, 1); | 526 | if (twl_has_regulator()) { |
590 | } | 527 | /* |
528 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); | ||
529 | if (IS_ERR(child)) | ||
530 | return PTR_ERR(child); | ||
531 | */ | ||
532 | |||
533 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); | ||
534 | if (IS_ERR(child)) | ||
535 | return PTR_ERR(child); | ||
536 | |||
537 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); | ||
538 | if (IS_ERR(child)) | ||
539 | return PTR_ERR(child); | ||
540 | |||
541 | child = add_regulator((features & TWL4030_VAUX2) | ||
542 | ? TWL4030_REG_VAUX2_4030 | ||
543 | : TWL4030_REG_VAUX2, | ||
544 | pdata->vaux2); | ||
545 | if (IS_ERR(child)) | ||
546 | return PTR_ERR(child); | ||
547 | } | ||
591 | 548 | ||
592 | if (status == 0) | 549 | if (twl_has_regulator() && usb_transceiver) { |
593 | status = platform_device_add(pdev); | 550 | static struct regulator_consumer_supply usb1v5 = { |
551 | .supply = "usb1v5", | ||
552 | }; | ||
553 | static struct regulator_consumer_supply usb1v8 = { | ||
554 | .supply = "usb1v8", | ||
555 | }; | ||
556 | static struct regulator_consumer_supply usb3v1 = { | ||
557 | .supply = "usb3v1", | ||
558 | }; | ||
559 | |||
560 | /* this is a template that gets copied */ | ||
561 | struct regulator_init_data usb_fixed = { | ||
562 | .constraints.valid_modes_mask = | ||
563 | REGULATOR_MODE_NORMAL | ||
564 | | REGULATOR_MODE_STANDBY, | ||
565 | .constraints.valid_ops_mask = | ||
566 | REGULATOR_CHANGE_MODE | ||
567 | | REGULATOR_CHANGE_STATUS, | ||
568 | }; | ||
569 | |||
570 | usb1v5.dev = usb_transceiver; | ||
571 | usb1v8.dev = usb_transceiver; | ||
572 | usb3v1.dev = usb_transceiver; | ||
573 | |||
574 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed, | ||
575 | &usb1v5, 1); | ||
576 | if (IS_ERR(child)) | ||
577 | return PTR_ERR(child); | ||
578 | |||
579 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed, | ||
580 | &usb1v8, 1); | ||
581 | if (IS_ERR(child)) | ||
582 | return PTR_ERR(child); | ||
583 | |||
584 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed, | ||
585 | &usb3v1, 1); | ||
586 | if (IS_ERR(child)) | ||
587 | return PTR_ERR(child); | ||
588 | } | ||
594 | 589 | ||
595 | if (status < 0) { | 590 | /* maybe add LDOs that are omitted on cost-reduced parts */ |
596 | platform_device_put(pdev); | 591 | if (twl_has_regulator() && !(features & TPS_SUBSET)) { |
597 | dev_dbg(&twl->client->dev, | 592 | /* |
598 | "can't create usb dev, %d\n", | 593 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); |
599 | status); | 594 | if (IS_ERR(child)) |
600 | } | 595 | return PTR_ERR(child); |
596 | */ | ||
597 | |||
598 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); | ||
599 | if (IS_ERR(child)) | ||
600 | return PTR_ERR(child); | ||
601 | |||
602 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); | ||
603 | if (IS_ERR(child)) | ||
604 | return PTR_ERR(child); | ||
605 | |||
606 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); | ||
607 | if (IS_ERR(child)) | ||
608 | return PTR_ERR(child); | ||
609 | |||
610 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); | ||
611 | if (IS_ERR(child)) | ||
612 | return PTR_ERR(child); | ||
613 | |||
614 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); | ||
615 | if (IS_ERR(child)) | ||
616 | return PTR_ERR(child); | ||
601 | } | 617 | } |
602 | 618 | ||
603 | err: | 619 | return 0; |
604 | if (status) | ||
605 | pr_err("failed to add twl4030's children (status %d)\n", status); | ||
606 | return status; | ||
607 | } | 620 | } |
608 | 621 | ||
609 | /*----------------------------------------------------------------------*/ | 622 | /*----------------------------------------------------------------------*/ |
@@ -645,12 +658,7 @@ static void __init clocks_init(void) | |||
645 | osc = clk_get(NULL, "osc_ck"); | 658 | osc = clk_get(NULL, "osc_ck"); |
646 | else | 659 | else |
647 | osc = clk_get(NULL, "osc_sys_ck"); | 660 | osc = clk_get(NULL, "osc_sys_ck"); |
648 | #else | 661 | |
649 | /* REVISIT for non-OMAP systems, pass the clock rate from | ||
650 | * board init code, using platform_data. | ||
651 | */ | ||
652 | osc = ERR_PTR(-EIO); | ||
653 | #endif | ||
654 | if (IS_ERR(osc)) { | 662 | if (IS_ERR(osc)) { |
655 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | 663 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " |
656 | "using bootloader value (unknown osc rate)\n"); | 664 | "using bootloader value (unknown osc rate)\n"); |
@@ -660,6 +668,18 @@ static void __init clocks_init(void) | |||
660 | rate = clk_get_rate(osc); | 668 | rate = clk_get_rate(osc); |
661 | clk_put(osc); | 669 | clk_put(osc); |
662 | 670 | ||
671 | #else | ||
672 | /* REVISIT for non-OMAP systems, pass the clock rate from | ||
673 | * board init code, using platform_data. | ||
674 | */ | ||
675 | osc = ERR_PTR(-EIO); | ||
676 | |||
677 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | ||
678 | "using bootloader value (unknown osc rate)\n"); | ||
679 | |||
680 | return; | ||
681 | #endif | ||
682 | |||
663 | switch (rate) { | 683 | switch (rate) { |
664 | case 19200000: | 684 | case 19200000: |
665 | ctrl = HFCLK_FREQ_19p2_MHZ; | 685 | ctrl = HFCLK_FREQ_19p2_MHZ; |
@@ -764,7 +784,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
764 | goto fail; | 784 | goto fail; |
765 | } | 785 | } |
766 | 786 | ||
767 | status = add_children(pdata); | 787 | status = add_children(pdata, id->driver_data); |
768 | fail: | 788 | fail: |
769 | if (status < 0) | 789 | if (status < 0) |
770 | twl4030_remove(client); | 790 | twl4030_remove(client); |
@@ -772,11 +792,11 @@ fail: | |||
772 | } | 792 | } |
773 | 793 | ||
774 | static const struct i2c_device_id twl4030_ids[] = { | 794 | static const struct i2c_device_id twl4030_ids[] = { |
775 | { "twl4030", 0 }, /* "Triton 2" */ | 795 | { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ |
776 | { "tps65950", 0 }, /* catalog version of twl4030 */ | 796 | { "twl5030", 0 }, /* T2 updated */ |
777 | { "tps65930", 0 }, /* fewer LDOs and DACs; no charger */ | 797 | { "tps65950", 0 }, /* catalog version of twl5030 */ |
778 | { "tps65920", 0 }, /* fewer LDOs; no codec or charger */ | 798 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ |
779 | { "twl5030", 0 }, /* T2 updated */ | 799 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ |
780 | { /* end of list */ }, | 800 | { /* end of list */ }, |
781 | }; | 801 | }; |
782 | MODULE_DEVICE_TABLE(i2c, twl4030_ids); | 802 | MODULE_DEVICE_TABLE(i2c, twl4030_ids); |
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index fae868a8d499..b10876036983 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -180,10 +180,15 @@ static struct completion irq_event; | |||
180 | static int twl4030_irq_thread(void *data) | 180 | static int twl4030_irq_thread(void *data) |
181 | { | 181 | { |
182 | long irq = (long)data; | 182 | long irq = (long)data; |
183 | irq_desc_t *desc = irq_desc + irq; | 183 | struct irq_desc *desc = irq_to_desc(irq); |
184 | static unsigned i2c_errors; | 184 | static unsigned i2c_errors; |
185 | const static unsigned max_i2c_errors = 100; | 185 | const static unsigned max_i2c_errors = 100; |
186 | 186 | ||
187 | if (!desc) { | ||
188 | pr_err("twl4030: Invalid IRQ: %ld\n", irq); | ||
189 | return -EINVAL; | ||
190 | } | ||
191 | |||
187 | current->flags |= PF_NOFREEZE; | 192 | current->flags |= PF_NOFREEZE; |
188 | 193 | ||
189 | while (!kthread_should_stop()) { | 194 | while (!kthread_should_stop()) { |
@@ -215,7 +220,13 @@ static int twl4030_irq_thread(void *data) | |||
215 | pih_isr; | 220 | pih_isr; |
216 | pih_isr >>= 1, module_irq++) { | 221 | pih_isr >>= 1, module_irq++) { |
217 | if (pih_isr & 0x1) { | 222 | if (pih_isr & 0x1) { |
218 | irq_desc_t *d = irq_desc + module_irq; | 223 | struct irq_desc *d = irq_to_desc(module_irq); |
224 | |||
225 | if (!d) { | ||
226 | pr_err("twl4030: Invalid SIH IRQ: %d\n", | ||
227 | module_irq); | ||
228 | return -EINVAL; | ||
229 | } | ||
219 | 230 | ||
220 | /* These can't be masked ... always warn | 231 | /* These can't be masked ... always warn |
221 | * if we get any surprises. | 232 | * if we get any surprises. |
@@ -452,10 +463,16 @@ static void twl4030_sih_do_edge(struct work_struct *work) | |||
452 | /* Modify only the bits we know must change */ | 463 | /* Modify only the bits we know must change */ |
453 | while (edge_change) { | 464 | while (edge_change) { |
454 | int i = fls(edge_change) - 1; | 465 | int i = fls(edge_change) - 1; |
455 | struct irq_desc *d = irq_desc + i + agent->irq_base; | 466 | struct irq_desc *d = irq_to_desc(i + agent->irq_base); |
456 | int byte = 1 + (i >> 2); | 467 | int byte = 1 + (i >> 2); |
457 | int off = (i & 0x3) * 2; | 468 | int off = (i & 0x3) * 2; |
458 | 469 | ||
470 | if (!d) { | ||
471 | pr_err("twl4030: Invalid IRQ: %d\n", | ||
472 | i + agent->irq_base); | ||
473 | return; | ||
474 | } | ||
475 | |||
459 | bytes[byte] &= ~(0x03 << off); | 476 | bytes[byte] &= ~(0x03 << off); |
460 | 477 | ||
461 | spin_lock_irq(&d->lock); | 478 | spin_lock_irq(&d->lock); |
@@ -512,9 +529,14 @@ static void twl4030_sih_unmask(unsigned irq) | |||
512 | static int twl4030_sih_set_type(unsigned irq, unsigned trigger) | 529 | static int twl4030_sih_set_type(unsigned irq, unsigned trigger) |
513 | { | 530 | { |
514 | struct sih_agent *sih = get_irq_chip_data(irq); | 531 | struct sih_agent *sih = get_irq_chip_data(irq); |
515 | struct irq_desc *desc = irq_desc + irq; | 532 | struct irq_desc *desc = irq_to_desc(irq); |
516 | unsigned long flags; | 533 | unsigned long flags; |
517 | 534 | ||
535 | if (!desc) { | ||
536 | pr_err("twl4030: Invalid IRQ: %d\n", irq); | ||
537 | return -EINVAL; | ||
538 | } | ||
539 | |||
518 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 540 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
519 | return -EINVAL; | 541 | return -EINVAL; |
520 | 542 | ||
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 0d47fb9e4b3b..3a273ccef3f2 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
@@ -63,7 +63,6 @@ | |||
63 | */ | 63 | */ |
64 | static DEFINE_MUTEX(io_mutex); | 64 | static DEFINE_MUTEX(io_mutex); |
65 | static DEFINE_MUTEX(reg_lock_mutex); | 65 | static DEFINE_MUTEX(reg_lock_mutex); |
66 | static DEFINE_MUTEX(auxadc_mutex); | ||
67 | 66 | ||
68 | /* Perform a physical read from the device. | 67 | /* Perform a physical read from the device. |
69 | */ | 68 | */ |
@@ -299,6 +298,13 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs, | |||
299 | } | 298 | } |
300 | EXPORT_SYMBOL_GPL(wm8350_block_write); | 299 | EXPORT_SYMBOL_GPL(wm8350_block_write); |
301 | 300 | ||
301 | /** | ||
302 | * wm8350_reg_lock() | ||
303 | * | ||
304 | * The WM8350 has a hardware lock which can be used to prevent writes to | ||
305 | * some registers (generally those which can cause particularly serious | ||
306 | * problems if misused). This function enables that lock. | ||
307 | */ | ||
302 | int wm8350_reg_lock(struct wm8350 *wm8350) | 308 | int wm8350_reg_lock(struct wm8350 *wm8350) |
303 | { | 309 | { |
304 | u16 key = WM8350_LOCK_KEY; | 310 | u16 key = WM8350_LOCK_KEY; |
@@ -314,6 +320,15 @@ int wm8350_reg_lock(struct wm8350 *wm8350) | |||
314 | } | 320 | } |
315 | EXPORT_SYMBOL_GPL(wm8350_reg_lock); | 321 | EXPORT_SYMBOL_GPL(wm8350_reg_lock); |
316 | 322 | ||
323 | /** | ||
324 | * wm8350_reg_unlock() | ||
325 | * | ||
326 | * The WM8350 has a hardware lock which can be used to prevent writes to | ||
327 | * some registers (generally those which can cause particularly serious | ||
328 | * problems if misused). This function disables that lock so updates | ||
329 | * can be performed. For maximum safety this should be done only when | ||
330 | * required. | ||
331 | */ | ||
317 | int wm8350_reg_unlock(struct wm8350 *wm8350) | 332 | int wm8350_reg_unlock(struct wm8350 *wm8350) |
318 | { | 333 | { |
319 | u16 key = WM8350_UNLOCK_KEY; | 334 | u16 key = WM8350_UNLOCK_KEY; |
@@ -1066,38 +1081,158 @@ int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) | |||
1066 | } | 1081 | } |
1067 | EXPORT_SYMBOL_GPL(wm8350_unmask_irq); | 1082 | EXPORT_SYMBOL_GPL(wm8350_unmask_irq); |
1068 | 1083 | ||
1084 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | ||
1085 | { | ||
1086 | u16 reg, result = 0; | ||
1087 | int tries = 5; | ||
1088 | |||
1089 | if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) | ||
1090 | return -EINVAL; | ||
1091 | if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP | ||
1092 | && (scale != 0 || vref != 0)) | ||
1093 | return -EINVAL; | ||
1094 | |||
1095 | mutex_lock(&wm8350->auxadc_mutex); | ||
1096 | |||
1097 | /* Turn on the ADC */ | ||
1098 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | ||
1099 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA); | ||
1100 | |||
1101 | if (scale || vref) { | ||
1102 | reg = scale << 13; | ||
1103 | reg |= vref << 12; | ||
1104 | wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg); | ||
1105 | } | ||
1106 | |||
1107 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | ||
1108 | reg |= 1 << channel | WM8350_AUXADC_POLL; | ||
1109 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); | ||
1110 | |||
1111 | do { | ||
1112 | schedule_timeout_interruptible(1); | ||
1113 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | ||
1114 | } while (tries-- && (reg & WM8350_AUXADC_POLL)); | ||
1115 | |||
1116 | if (!tries) | ||
1117 | dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); | ||
1118 | else | ||
1119 | result = wm8350_reg_read(wm8350, | ||
1120 | WM8350_AUX1_READBACK + channel); | ||
1121 | |||
1122 | /* Turn off the ADC */ | ||
1123 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | ||
1124 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, | ||
1125 | reg & ~WM8350_AUXADC_ENA); | ||
1126 | |||
1127 | mutex_unlock(&wm8350->auxadc_mutex); | ||
1128 | |||
1129 | return result & WM8350_AUXADC_DATA1_MASK; | ||
1130 | } | ||
1131 | EXPORT_SYMBOL_GPL(wm8350_read_auxadc); | ||
1132 | |||
1069 | /* | 1133 | /* |
1070 | * Cache is always host endian. | 1134 | * Cache is always host endian. |
1071 | */ | 1135 | */ |
1072 | static int wm8350_create_cache(struct wm8350 *wm8350, int mode) | 1136 | static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode) |
1073 | { | 1137 | { |
1074 | int i, ret = 0; | 1138 | int i, ret = 0; |
1075 | u16 value; | 1139 | u16 value; |
1076 | const u16 *reg_map; | 1140 | const u16 *reg_map; |
1077 | 1141 | ||
1078 | switch (mode) { | 1142 | switch (type) { |
1079 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 | ||
1080 | case 0: | 1143 | case 0: |
1081 | reg_map = wm8350_mode0_defaults; | 1144 | switch (mode) { |
1082 | break; | 1145 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0 |
1146 | case 0: | ||
1147 | reg_map = wm8350_mode0_defaults; | ||
1148 | break; | ||
1083 | #endif | 1149 | #endif |
1084 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 | 1150 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1 |
1085 | case 1: | 1151 | case 1: |
1086 | reg_map = wm8350_mode1_defaults; | 1152 | reg_map = wm8350_mode1_defaults; |
1087 | break; | 1153 | break; |
1088 | #endif | 1154 | #endif |
1089 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 | 1155 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2 |
1090 | case 2: | 1156 | case 2: |
1091 | reg_map = wm8350_mode2_defaults; | 1157 | reg_map = wm8350_mode2_defaults; |
1092 | break; | 1158 | break; |
1093 | #endif | 1159 | #endif |
1094 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 | 1160 | #ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3 |
1095 | case 3: | 1161 | case 3: |
1096 | reg_map = wm8350_mode3_defaults; | 1162 | reg_map = wm8350_mode3_defaults; |
1163 | break; | ||
1164 | #endif | ||
1165 | default: | ||
1166 | dev_err(wm8350->dev, | ||
1167 | "WM8350 configuration mode %d not supported\n", | ||
1168 | mode); | ||
1169 | return -EINVAL; | ||
1170 | } | ||
1171 | break; | ||
1172 | |||
1173 | case 1: | ||
1174 | switch (mode) { | ||
1175 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 | ||
1176 | case 0: | ||
1177 | reg_map = wm8351_mode0_defaults; | ||
1178 | break; | ||
1179 | #endif | ||
1180 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 | ||
1181 | case 1: | ||
1182 | reg_map = wm8351_mode1_defaults; | ||
1183 | break; | ||
1184 | #endif | ||
1185 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 | ||
1186 | case 2: | ||
1187 | reg_map = wm8351_mode2_defaults; | ||
1188 | break; | ||
1189 | #endif | ||
1190 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 | ||
1191 | case 3: | ||
1192 | reg_map = wm8351_mode3_defaults; | ||
1193 | break; | ||
1194 | #endif | ||
1195 | default: | ||
1196 | dev_err(wm8350->dev, | ||
1197 | "WM8351 configuration mode %d not supported\n", | ||
1198 | mode); | ||
1199 | return -EINVAL; | ||
1200 | } | ||
1097 | break; | 1201 | break; |
1202 | |||
1203 | case 2: | ||
1204 | switch (mode) { | ||
1205 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 | ||
1206 | case 0: | ||
1207 | reg_map = wm8352_mode0_defaults; | ||
1208 | break; | ||
1209 | #endif | ||
1210 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 | ||
1211 | case 1: | ||
1212 | reg_map = wm8352_mode1_defaults; | ||
1213 | break; | ||
1098 | #endif | 1214 | #endif |
1215 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 | ||
1216 | case 2: | ||
1217 | reg_map = wm8352_mode2_defaults; | ||
1218 | break; | ||
1219 | #endif | ||
1220 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 | ||
1221 | case 3: | ||
1222 | reg_map = wm8352_mode3_defaults; | ||
1223 | break; | ||
1224 | #endif | ||
1225 | default: | ||
1226 | dev_err(wm8350->dev, | ||
1227 | "WM8352 configuration mode %d not supported\n", | ||
1228 | mode); | ||
1229 | return -EINVAL; | ||
1230 | } | ||
1231 | break; | ||
1232 | |||
1099 | default: | 1233 | default: |
1100 | dev_err(wm8350->dev, "Configuration mode %d not supported\n", | 1234 | dev_err(wm8350->dev, |
1235 | "WM835x configuration mode %d not supported\n", | ||
1101 | mode); | 1236 | mode); |
1102 | return -EINVAL; | 1237 | return -EINVAL; |
1103 | } | 1238 | } |
@@ -1163,53 +1298,113 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
1163 | struct wm8350_platform_data *pdata) | 1298 | struct wm8350_platform_data *pdata) |
1164 | { | 1299 | { |
1165 | int ret = -EINVAL; | 1300 | int ret = -EINVAL; |
1166 | u16 id1, id2, mask, mode; | 1301 | u16 id1, id2, mask_rev; |
1302 | u16 cust_id, mode, chip_rev; | ||
1167 | 1303 | ||
1168 | /* get WM8350 revision and config mode */ | 1304 | /* get WM8350 revision and config mode */ |
1169 | wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1); | 1305 | wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1); |
1170 | wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2); | 1306 | wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2); |
1307 | wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), &mask_rev); | ||
1171 | 1308 | ||
1172 | id1 = be16_to_cpu(id1); | 1309 | id1 = be16_to_cpu(id1); |
1173 | id2 = be16_to_cpu(id2); | 1310 | id2 = be16_to_cpu(id2); |
1311 | mask_rev = be16_to_cpu(mask_rev); | ||
1174 | 1312 | ||
1175 | if (id1 == 0x6143) { | 1313 | if (id1 != 0x6143) { |
1176 | switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) { | 1314 | dev_err(wm8350->dev, |
1315 | "Device with ID %x is not a WM8350\n", id1); | ||
1316 | ret = -ENODEV; | ||
1317 | goto err; | ||
1318 | } | ||
1319 | |||
1320 | mode = id2 & WM8350_CONF_STS_MASK >> 10; | ||
1321 | cust_id = id2 & WM8350_CUST_ID_MASK; | ||
1322 | chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12; | ||
1323 | dev_info(wm8350->dev, | ||
1324 | "CONF_STS %d, CUST_ID %d, MASK_REV %d, CHIP_REV %d\n", | ||
1325 | mode, cust_id, mask_rev, chip_rev); | ||
1326 | |||
1327 | if (cust_id != 0) { | ||
1328 | dev_err(wm8350->dev, "Unsupported CUST_ID\n"); | ||
1329 | ret = -ENODEV; | ||
1330 | goto err; | ||
1331 | } | ||
1332 | |||
1333 | switch (mask_rev) { | ||
1334 | case 0: | ||
1335 | wm8350->pmic.max_dcdc = WM8350_DCDC_6; | ||
1336 | wm8350->pmic.max_isink = WM8350_ISINK_B; | ||
1337 | |||
1338 | switch (chip_rev) { | ||
1177 | case WM8350_REV_E: | 1339 | case WM8350_REV_E: |
1178 | dev_info(wm8350->dev, "Found Rev E device\n"); | 1340 | dev_info(wm8350->dev, "WM8350 Rev E\n"); |
1179 | wm8350->rev = WM8350_REV_E; | ||
1180 | break; | 1341 | break; |
1181 | case WM8350_REV_F: | 1342 | case WM8350_REV_F: |
1182 | dev_info(wm8350->dev, "Found Rev F device\n"); | 1343 | dev_info(wm8350->dev, "WM8350 Rev F\n"); |
1183 | wm8350->rev = WM8350_REV_F; | ||
1184 | break; | 1344 | break; |
1185 | case WM8350_REV_G: | 1345 | case WM8350_REV_G: |
1186 | dev_info(wm8350->dev, "Found Rev G device\n"); | 1346 | dev_info(wm8350->dev, "WM8350 Rev G\n"); |
1187 | wm8350->rev = WM8350_REV_G; | 1347 | wm8350->power.rev_g_coeff = 1; |
1348 | break; | ||
1349 | case WM8350_REV_H: | ||
1350 | dev_info(wm8350->dev, "WM8350 Rev H\n"); | ||
1351 | wm8350->power.rev_g_coeff = 1; | ||
1188 | break; | 1352 | break; |
1189 | default: | 1353 | default: |
1190 | /* For safety we refuse to run on unknown hardware */ | 1354 | /* For safety we refuse to run on unknown hardware */ |
1191 | dev_info(wm8350->dev, "Found unknown rev\n"); | 1355 | dev_err(wm8350->dev, "Unknown WM8350 CHIP_REV\n"); |
1192 | ret = -ENODEV; | 1356 | ret = -ENODEV; |
1193 | goto err; | 1357 | goto err; |
1194 | } | 1358 | } |
1195 | } else { | 1359 | break; |
1196 | dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n", | 1360 | |
1197 | id1); | 1361 | case 1: |
1362 | wm8350->pmic.max_dcdc = WM8350_DCDC_4; | ||
1363 | wm8350->pmic.max_isink = WM8350_ISINK_A; | ||
1364 | |||
1365 | switch (chip_rev) { | ||
1366 | case 0: | ||
1367 | dev_info(wm8350->dev, "WM8351 Rev A\n"); | ||
1368 | wm8350->power.rev_g_coeff = 1; | ||
1369 | break; | ||
1370 | |||
1371 | default: | ||
1372 | dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n"); | ||
1373 | ret = -ENODEV; | ||
1374 | goto err; | ||
1375 | } | ||
1376 | break; | ||
1377 | |||
1378 | case 2: | ||
1379 | wm8350->pmic.max_dcdc = WM8350_DCDC_6; | ||
1380 | wm8350->pmic.max_isink = WM8350_ISINK_B; | ||
1381 | |||
1382 | switch (chip_rev) { | ||
1383 | case 0: | ||
1384 | dev_info(wm8350->dev, "WM8352 Rev A\n"); | ||
1385 | wm8350->power.rev_g_coeff = 1; | ||
1386 | break; | ||
1387 | |||
1388 | default: | ||
1389 | dev_err(wm8350->dev, "Unknown WM8352 CHIP_REV\n"); | ||
1390 | ret = -ENODEV; | ||
1391 | goto err; | ||
1392 | } | ||
1393 | break; | ||
1394 | |||
1395 | default: | ||
1396 | dev_err(wm8350->dev, "Unknown MASK_REV\n"); | ||
1198 | ret = -ENODEV; | 1397 | ret = -ENODEV; |
1199 | goto err; | 1398 | goto err; |
1200 | } | 1399 | } |
1201 | 1400 | ||
1202 | mode = id2 & WM8350_CONF_STS_MASK >> 10; | 1401 | ret = wm8350_create_cache(wm8350, mask_rev, mode); |
1203 | mask = id2 & WM8350_CUST_ID_MASK; | ||
1204 | dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask); | ||
1205 | |||
1206 | ret = wm8350_create_cache(wm8350, mode); | ||
1207 | if (ret < 0) { | 1402 | if (ret < 0) { |
1208 | printk(KERN_ERR "wm8350: failed to create register cache\n"); | 1403 | dev_err(wm8350->dev, "Failed to create register cache\n"); |
1209 | return ret; | 1404 | return ret; |
1210 | } | 1405 | } |
1211 | 1406 | ||
1212 | if (pdata->init) { | 1407 | if (pdata && pdata->init) { |
1213 | ret = pdata->init(wm8350); | 1408 | ret = pdata->init(wm8350); |
1214 | if (ret != 0) { | 1409 | if (ret != 0) { |
1215 | dev_err(wm8350->dev, "Platform init() failed: %d\n", | 1410 | dev_err(wm8350->dev, "Platform init() failed: %d\n", |
@@ -1218,6 +1413,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
1218 | } | 1413 | } |
1219 | } | 1414 | } |
1220 | 1415 | ||
1416 | mutex_init(&wm8350->auxadc_mutex); | ||
1221 | mutex_init(&wm8350->irq_mutex); | 1417 | mutex_init(&wm8350->irq_mutex); |
1222 | INIT_WORK(&wm8350->irq_work, wm8350_irq_worker); | 1418 | INIT_WORK(&wm8350->irq_work, wm8350_irq_worker); |
1223 | if (irq) { | 1419 | if (irq) { |
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 3e0ce0e50ea2..8d8c93217572 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c | |||
@@ -1,8 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * wm8350-i2c.c -- Generic I2C driver for Wolfson WM8350 PMIC | 2 | * wm8350-i2c.c -- Generic I2C driver for Wolfson WM8350 PMIC |
3 | * | 3 | * |
4 | * This driver defines and configures the WM8350 for the Freescale i.MX32ADS. | ||
5 | * | ||
6 | * Copyright 2007, 2008 Wolfson Microelectronics PLC. | 4 | * Copyright 2007, 2008 Wolfson Microelectronics PLC. |
7 | * | 5 | * |
8 | * Author: Liam Girdwood | 6 | * Author: Liam Girdwood |
@@ -99,6 +97,8 @@ static int wm8350_i2c_remove(struct i2c_client *i2c) | |||
99 | 97 | ||
100 | static const struct i2c_device_id wm8350_i2c_id[] = { | 98 | static const struct i2c_device_id wm8350_i2c_id[] = { |
101 | { "wm8350", 0 }, | 99 | { "wm8350", 0 }, |
100 | { "wm8351", 0 }, | ||
101 | { "wm8352", 0 }, | ||
102 | { } | 102 | { } |
103 | }; | 103 | }; |
104 | MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id); | 104 | MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id); |
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index 974678db22cd..68887b817d17 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c | |||
@@ -1074,6 +1074,2102 @@ const u16 wm8350_mode3_defaults[] = { | |||
1074 | }; | 1074 | }; |
1075 | #endif | 1075 | #endif |
1076 | 1076 | ||
1077 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0 | ||
1078 | |||
1079 | #undef WM8350_HAVE_CONFIG_MODE | ||
1080 | #define WM8350_HAVE_CONFIG_MODE | ||
1081 | |||
1082 | const u16 wm8351_mode0_defaults[] = { | ||
1083 | 0x6143, /* R0 - Reset/ID */ | ||
1084 | 0x0000, /* R1 - ID */ | ||
1085 | 0x0001, /* R2 - Revision */ | ||
1086 | 0x1C02, /* R3 - System Control 1 */ | ||
1087 | 0x0004, /* R4 - System Control 2 */ | ||
1088 | 0x0000, /* R5 - System Hibernate */ | ||
1089 | 0x8A00, /* R6 - Interface Control */ | ||
1090 | 0x0000, /* R7 */ | ||
1091 | 0x8000, /* R8 - Power mgmt (1) */ | ||
1092 | 0x0000, /* R9 - Power mgmt (2) */ | ||
1093 | 0x0000, /* R10 - Power mgmt (3) */ | ||
1094 | 0x2000, /* R11 - Power mgmt (4) */ | ||
1095 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
1096 | 0x0000, /* R13 - Power mgmt (6) */ | ||
1097 | 0x0000, /* R14 - Power mgmt (7) */ | ||
1098 | 0x0000, /* R15 */ | ||
1099 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
1100 | 0x0100, /* R17 - RTC Hours/Day */ | ||
1101 | 0x0101, /* R18 - RTC Date/Month */ | ||
1102 | 0x1400, /* R19 - RTC Year */ | ||
1103 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
1104 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
1105 | 0x0000, /* R22 - Alarm Date/Month */ | ||
1106 | 0x0320, /* R23 - RTC Time Control */ | ||
1107 | 0x0000, /* R24 - System Interrupts */ | ||
1108 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
1109 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
1110 | 0x0000, /* R27 */ | ||
1111 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
1112 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
1113 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
1114 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
1115 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
1116 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
1117 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
1118 | 0x0000, /* R35 */ | ||
1119 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
1120 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
1121 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
1122 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
1123 | 0x0040, /* R40 - Clock Control 1 */ | ||
1124 | 0x0000, /* R41 - Clock Control 2 */ | ||
1125 | 0x3A00, /* R42 - FLL Control 1 */ | ||
1126 | 0x7086, /* R43 - FLL Control 2 */ | ||
1127 | 0xC226, /* R44 - FLL Control 3 */ | ||
1128 | 0x0000, /* R45 - FLL Control 4 */ | ||
1129 | 0x0000, /* R46 */ | ||
1130 | 0x0000, /* R47 */ | ||
1131 | 0x0000, /* R48 - DAC Control */ | ||
1132 | 0x0000, /* R49 */ | ||
1133 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
1134 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
1135 | 0x0000, /* R52 */ | ||
1136 | 0x0040, /* R53 - DAC LR Rate */ | ||
1137 | 0x0000, /* R54 - DAC Clock Control */ | ||
1138 | 0x0000, /* R55 */ | ||
1139 | 0x0000, /* R56 */ | ||
1140 | 0x0000, /* R57 */ | ||
1141 | 0x4000, /* R58 - DAC Mute */ | ||
1142 | 0x0000, /* R59 - DAC Mute Volume */ | ||
1143 | 0x0000, /* R60 - DAC Side */ | ||
1144 | 0x0000, /* R61 */ | ||
1145 | 0x0000, /* R62 */ | ||
1146 | 0x0000, /* R63 */ | ||
1147 | 0x8000, /* R64 - ADC Control */ | ||
1148 | 0x0000, /* R65 */ | ||
1149 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
1150 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
1151 | 0x0000, /* R68 - ADC Divider */ | ||
1152 | 0x0000, /* R69 */ | ||
1153 | 0x0040, /* R70 - ADC LR Rate */ | ||
1154 | 0x0000, /* R71 */ | ||
1155 | 0x0303, /* R72 - Input Control */ | ||
1156 | 0x0000, /* R73 - IN3 Input Control */ | ||
1157 | 0x0000, /* R74 - Mic Bias Control */ | ||
1158 | 0x0000, /* R75 */ | ||
1159 | 0x0000, /* R76 - Output Control */ | ||
1160 | 0x0000, /* R77 - Jack Detect */ | ||
1161 | 0x0000, /* R78 - Anti Pop Control */ | ||
1162 | 0x0000, /* R79 */ | ||
1163 | 0x0040, /* R80 - Left Input Volume */ | ||
1164 | 0x0040, /* R81 - Right Input Volume */ | ||
1165 | 0x0000, /* R82 */ | ||
1166 | 0x0000, /* R83 */ | ||
1167 | 0x0000, /* R84 */ | ||
1168 | 0x0000, /* R85 */ | ||
1169 | 0x0000, /* R86 */ | ||
1170 | 0x0000, /* R87 */ | ||
1171 | 0x0800, /* R88 - Left Mixer Control */ | ||
1172 | 0x1000, /* R89 - Right Mixer Control */ | ||
1173 | 0x0000, /* R90 */ | ||
1174 | 0x0000, /* R91 */ | ||
1175 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
1176 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
1177 | 0x0000, /* R94 */ | ||
1178 | 0x0000, /* R95 */ | ||
1179 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
1180 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
1181 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
1182 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
1183 | 0x0000, /* R100 - Input Mixer Volume */ | ||
1184 | 0x0000, /* R101 */ | ||
1185 | 0x0000, /* R102 */ | ||
1186 | 0x0000, /* R103 */ | ||
1187 | 0x00E4, /* R104 - OUT1L Volume */ | ||
1188 | 0x00E4, /* R105 - OUT1R Volume */ | ||
1189 | 0x00E4, /* R106 - OUT2L Volume */ | ||
1190 | 0x02E4, /* R107 - OUT2R Volume */ | ||
1191 | 0x0000, /* R108 */ | ||
1192 | 0x0000, /* R109 */ | ||
1193 | 0x0000, /* R110 */ | ||
1194 | 0x0000, /* R111 - BEEP Volume */ | ||
1195 | 0x0A00, /* R112 - AI Formating */ | ||
1196 | 0x0000, /* R113 - ADC DAC COMP */ | ||
1197 | 0x0020, /* R114 - AI ADC Control */ | ||
1198 | 0x0020, /* R115 - AI DAC Control */ | ||
1199 | 0x0000, /* R116 */ | ||
1200 | 0x0000, /* R117 */ | ||
1201 | 0x0000, /* R118 */ | ||
1202 | 0x0000, /* R119 */ | ||
1203 | 0x0000, /* R120 */ | ||
1204 | 0x0000, /* R121 */ | ||
1205 | 0x0000, /* R122 */ | ||
1206 | 0x0000, /* R123 */ | ||
1207 | 0x0000, /* R124 */ | ||
1208 | 0x0000, /* R125 */ | ||
1209 | 0x0000, /* R126 */ | ||
1210 | 0x0000, /* R127 */ | ||
1211 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
1212 | 0x0000, /* R129 - GPIO Pin pull up Control */ | ||
1213 | 0x0000, /* R130 - GPIO Pull down Control */ | ||
1214 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
1215 | 0x0000, /* R132 */ | ||
1216 | 0x0000, /* R133 - GPIO Control */ | ||
1217 | 0x0FFC, /* R134 - GPIO Configuration (i/o) */ | ||
1218 | 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ | ||
1219 | 0x0000, /* R136 */ | ||
1220 | 0x0000, /* R137 */ | ||
1221 | 0x0000, /* R138 */ | ||
1222 | 0x0000, /* R139 */ | ||
1223 | 0x0013, /* R140 - GPIO Function Select 1 */ | ||
1224 | 0x0000, /* R141 - GPIO Function Select 2 */ | ||
1225 | 0x0000, /* R142 - GPIO Function Select 3 */ | ||
1226 | 0x0003, /* R143 - GPIO Function Select 4 */ | ||
1227 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
1228 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
1229 | 0x0000, /* R146 */ | ||
1230 | 0x0000, /* R147 */ | ||
1231 | 0x0000, /* R148 */ | ||
1232 | 0x0000, /* R149 */ | ||
1233 | 0x0000, /* R150 */ | ||
1234 | 0x0000, /* R151 */ | ||
1235 | 0x7000, /* R152 - AUX1 Readback */ | ||
1236 | 0x7000, /* R153 - AUX2 Readback */ | ||
1237 | 0x7000, /* R154 - AUX3 Readback */ | ||
1238 | 0x7000, /* R155 - AUX4 Readback */ | ||
1239 | 0x0000, /* R156 - USB Voltage Readback */ | ||
1240 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
1241 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
1242 | 0x0000, /* R159 - Chip Temp Readback */ | ||
1243 | 0x0000, /* R160 */ | ||
1244 | 0x0000, /* R161 */ | ||
1245 | 0x0000, /* R162 */ | ||
1246 | 0x0000, /* R163 - Generic Comparator Control */ | ||
1247 | 0x0000, /* R164 - Generic comparator 1 */ | ||
1248 | 0x0000, /* R165 - Generic comparator 2 */ | ||
1249 | 0x0000, /* R166 - Generic comparator 3 */ | ||
1250 | 0x0000, /* R167 - Generic comparator 4 */ | ||
1251 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
1252 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
1253 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
1254 | 0x0000, /* R171 */ | ||
1255 | 0x0000, /* R172 - Current Sink Driver A */ | ||
1256 | 0x0000, /* R173 - CSA Flash control */ | ||
1257 | 0x0000, /* R174 */ | ||
1258 | 0x0000, /* R175 */ | ||
1259 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
1260 | 0x032D, /* R177 - DCDC Active options */ | ||
1261 | 0x0000, /* R178 - DCDC Sleep options */ | ||
1262 | 0x0025, /* R179 - Power-check comparator */ | ||
1263 | 0x000E, /* R180 - DCDC1 Control */ | ||
1264 | 0x0000, /* R181 - DCDC1 Timeouts */ | ||
1265 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
1266 | 0x0018, /* R183 - DCDC2 Control */ | ||
1267 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
1268 | 0x0000, /* R185 */ | ||
1269 | 0x0000, /* R186 - DCDC3 Control */ | ||
1270 | 0x0000, /* R187 - DCDC3 Timeouts */ | ||
1271 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
1272 | 0x0000, /* R189 - DCDC4 Control */ | ||
1273 | 0x0000, /* R190 - DCDC4 Timeouts */ | ||
1274 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
1275 | 0x0008, /* R192 */ | ||
1276 | 0x0000, /* R193 */ | ||
1277 | 0x0000, /* R194 */ | ||
1278 | 0x0000, /* R195 */ | ||
1279 | 0x0000, /* R196 */ | ||
1280 | 0x0006, /* R197 */ | ||
1281 | 0x0000, /* R198 */ | ||
1282 | 0x0003, /* R199 - Limit Switch Control */ | ||
1283 | 0x001C, /* R200 - LDO1 Control */ | ||
1284 | 0x0000, /* R201 - LDO1 Timeouts */ | ||
1285 | 0x001C, /* R202 - LDO1 Low Power */ | ||
1286 | 0x001B, /* R203 - LDO2 Control */ | ||
1287 | 0x0000, /* R204 - LDO2 Timeouts */ | ||
1288 | 0x001C, /* R205 - LDO2 Low Power */ | ||
1289 | 0x001B, /* R206 - LDO3 Control */ | ||
1290 | 0x0000, /* R207 - LDO3 Timeouts */ | ||
1291 | 0x001C, /* R208 - LDO3 Low Power */ | ||
1292 | 0x001B, /* R209 - LDO4 Control */ | ||
1293 | 0x0000, /* R210 - LDO4 Timeouts */ | ||
1294 | 0x001C, /* R211 - LDO4 Low Power */ | ||
1295 | 0x0000, /* R212 */ | ||
1296 | 0x0000, /* R213 */ | ||
1297 | 0x0000, /* R214 */ | ||
1298 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
1299 | 0x001F, /* R216 - Main Bandgap Control */ | ||
1300 | 0x0000, /* R217 - OSC Control */ | ||
1301 | 0x9000, /* R218 - RTC Tick Control */ | ||
1302 | 0x0000, /* R219 - Security1 */ | ||
1303 | 0x4000, /* R220 */ | ||
1304 | 0x0000, /* R221 */ | ||
1305 | 0x0000, /* R222 */ | ||
1306 | 0x0000, /* R223 */ | ||
1307 | 0x0000, /* R224 - Signal overrides */ | ||
1308 | 0x0000, /* R225 - DCDC/LDO status */ | ||
1309 | 0x0000, /* R226 - Charger Overides/status */ | ||
1310 | 0x0000, /* R227 - misc overrides */ | ||
1311 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
1312 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
1313 | 0xE000, /* R230 - GPIO Pin Status */ | ||
1314 | 0x0000, /* R231 - comparotor overrides */ | ||
1315 | 0x0000, /* R232 */ | ||
1316 | 0x0000, /* R233 - State Machine status */ | ||
1317 | 0x1200, /* R234 - FLL Test 1 */ | ||
1318 | 0x0000, /* R235 */ | ||
1319 | 0x8000, /* R236 */ | ||
1320 | 0x0000, /* R237 */ | ||
1321 | 0x0000, /* R238 */ | ||
1322 | 0x0000, /* R239 */ | ||
1323 | 0x0003, /* R240 */ | ||
1324 | 0x0000, /* R241 */ | ||
1325 | 0x0000, /* R242 */ | ||
1326 | 0x0004, /* R243 */ | ||
1327 | 0x0300, /* R244 */ | ||
1328 | 0x0000, /* R245 */ | ||
1329 | 0x0200, /* R246 */ | ||
1330 | 0x0000, /* R247 */ | ||
1331 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
1332 | 0x1000, /* R249 */ | ||
1333 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
1334 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
1335 | }; | ||
1336 | #endif | ||
1337 | |||
1338 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1 | ||
1339 | |||
1340 | #undef WM8350_HAVE_CONFIG_MODE | ||
1341 | #define WM8350_HAVE_CONFIG_MODE | ||
1342 | |||
1343 | const u16 wm8351_mode1_defaults[] = { | ||
1344 | 0x6143, /* R0 - Reset/ID */ | ||
1345 | 0x0000, /* R1 - ID */ | ||
1346 | 0x0001, /* R2 - Revision */ | ||
1347 | 0x1C02, /* R3 - System Control 1 */ | ||
1348 | 0x0204, /* R4 - System Control 2 */ | ||
1349 | 0x0000, /* R5 - System Hibernate */ | ||
1350 | 0x8A00, /* R6 - Interface Control */ | ||
1351 | 0x0000, /* R7 */ | ||
1352 | 0x8000, /* R8 - Power mgmt (1) */ | ||
1353 | 0x0000, /* R9 - Power mgmt (2) */ | ||
1354 | 0x0000, /* R10 - Power mgmt (3) */ | ||
1355 | 0x2000, /* R11 - Power mgmt (4) */ | ||
1356 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
1357 | 0x0000, /* R13 - Power mgmt (6) */ | ||
1358 | 0x0000, /* R14 - Power mgmt (7) */ | ||
1359 | 0x0000, /* R15 */ | ||
1360 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
1361 | 0x0100, /* R17 - RTC Hours/Day */ | ||
1362 | 0x0101, /* R18 - RTC Date/Month */ | ||
1363 | 0x1400, /* R19 - RTC Year */ | ||
1364 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
1365 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
1366 | 0x0000, /* R22 - Alarm Date/Month */ | ||
1367 | 0x0320, /* R23 - RTC Time Control */ | ||
1368 | 0x0000, /* R24 - System Interrupts */ | ||
1369 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
1370 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
1371 | 0x0000, /* R27 */ | ||
1372 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
1373 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
1374 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
1375 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
1376 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
1377 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
1378 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
1379 | 0x0000, /* R35 */ | ||
1380 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
1381 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
1382 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
1383 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
1384 | 0x0040, /* R40 - Clock Control 1 */ | ||
1385 | 0x0000, /* R41 - Clock Control 2 */ | ||
1386 | 0x3A00, /* R42 - FLL Control 1 */ | ||
1387 | 0x7086, /* R43 - FLL Control 2 */ | ||
1388 | 0xC226, /* R44 - FLL Control 3 */ | ||
1389 | 0x0000, /* R45 - FLL Control 4 */ | ||
1390 | 0x0000, /* R46 */ | ||
1391 | 0x0000, /* R47 */ | ||
1392 | 0x0000, /* R48 - DAC Control */ | ||
1393 | 0x0000, /* R49 */ | ||
1394 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
1395 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
1396 | 0x0000, /* R52 */ | ||
1397 | 0x0040, /* R53 - DAC LR Rate */ | ||
1398 | 0x0000, /* R54 - DAC Clock Control */ | ||
1399 | 0x0000, /* R55 */ | ||
1400 | 0x0000, /* R56 */ | ||
1401 | 0x0000, /* R57 */ | ||
1402 | 0x4000, /* R58 - DAC Mute */ | ||
1403 | 0x0000, /* R59 - DAC Mute Volume */ | ||
1404 | 0x0000, /* R60 - DAC Side */ | ||
1405 | 0x0000, /* R61 */ | ||
1406 | 0x0000, /* R62 */ | ||
1407 | 0x0000, /* R63 */ | ||
1408 | 0x8000, /* R64 - ADC Control */ | ||
1409 | 0x0000, /* R65 */ | ||
1410 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
1411 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
1412 | 0x0000, /* R68 - ADC Divider */ | ||
1413 | 0x0000, /* R69 */ | ||
1414 | 0x0040, /* R70 - ADC LR Rate */ | ||
1415 | 0x0000, /* R71 */ | ||
1416 | 0x0303, /* R72 - Input Control */ | ||
1417 | 0x0000, /* R73 - IN3 Input Control */ | ||
1418 | 0x0000, /* R74 - Mic Bias Control */ | ||
1419 | 0x0000, /* R75 */ | ||
1420 | 0x0000, /* R76 - Output Control */ | ||
1421 | 0x0000, /* R77 - Jack Detect */ | ||
1422 | 0x0000, /* R78 - Anti Pop Control */ | ||
1423 | 0x0000, /* R79 */ | ||
1424 | 0x0040, /* R80 - Left Input Volume */ | ||
1425 | 0x0040, /* R81 - Right Input Volume */ | ||
1426 | 0x0000, /* R82 */ | ||
1427 | 0x0000, /* R83 */ | ||
1428 | 0x0000, /* R84 */ | ||
1429 | 0x0000, /* R85 */ | ||
1430 | 0x0000, /* R86 */ | ||
1431 | 0x0000, /* R87 */ | ||
1432 | 0x0800, /* R88 - Left Mixer Control */ | ||
1433 | 0x1000, /* R89 - Right Mixer Control */ | ||
1434 | 0x0000, /* R90 */ | ||
1435 | 0x0000, /* R91 */ | ||
1436 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
1437 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
1438 | 0x0000, /* R94 */ | ||
1439 | 0x0000, /* R95 */ | ||
1440 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
1441 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
1442 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
1443 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
1444 | 0x0000, /* R100 - Input Mixer Volume */ | ||
1445 | 0x0000, /* R101 */ | ||
1446 | 0x0000, /* R102 */ | ||
1447 | 0x0000, /* R103 */ | ||
1448 | 0x00E4, /* R104 - OUT1L Volume */ | ||
1449 | 0x00E4, /* R105 - OUT1R Volume */ | ||
1450 | 0x00E4, /* R106 - OUT2L Volume */ | ||
1451 | 0x02E4, /* R107 - OUT2R Volume */ | ||
1452 | 0x0000, /* R108 */ | ||
1453 | 0x0000, /* R109 */ | ||
1454 | 0x0000, /* R110 */ | ||
1455 | 0x0000, /* R111 - BEEP Volume */ | ||
1456 | 0x0A00, /* R112 - AI Formating */ | ||
1457 | 0x0000, /* R113 - ADC DAC COMP */ | ||
1458 | 0x0020, /* R114 - AI ADC Control */ | ||
1459 | 0x0020, /* R115 - AI DAC Control */ | ||
1460 | 0x0000, /* R116 */ | ||
1461 | 0x0000, /* R117 */ | ||
1462 | 0x0000, /* R118 */ | ||
1463 | 0x0000, /* R119 */ | ||
1464 | 0x0000, /* R120 */ | ||
1465 | 0x0000, /* R121 */ | ||
1466 | 0x0000, /* R122 */ | ||
1467 | 0x0000, /* R123 */ | ||
1468 | 0x0000, /* R124 */ | ||
1469 | 0x0000, /* R125 */ | ||
1470 | 0x0000, /* R126 */ | ||
1471 | 0x0000, /* R127 */ | ||
1472 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
1473 | 0x0000, /* R129 - GPIO Pin pull up Control */ | ||
1474 | 0x0000, /* R130 - GPIO Pull down Control */ | ||
1475 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
1476 | 0x0000, /* R132 */ | ||
1477 | 0x0000, /* R133 - GPIO Control */ | ||
1478 | 0x0CFB, /* R134 - GPIO Configuration (i/o) */ | ||
1479 | 0x0C1F, /* R135 - GPIO Pin Polarity / Type */ | ||
1480 | 0x0000, /* R136 */ | ||
1481 | 0x0000, /* R137 */ | ||
1482 | 0x0000, /* R138 */ | ||
1483 | 0x0000, /* R139 */ | ||
1484 | 0x0300, /* R140 - GPIO Function Select 1 */ | ||
1485 | 0x1110, /* R141 - GPIO Function Select 2 */ | ||
1486 | 0x0013, /* R142 - GPIO Function Select 3 */ | ||
1487 | 0x0003, /* R143 - GPIO Function Select 4 */ | ||
1488 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
1489 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
1490 | 0x0000, /* R146 */ | ||
1491 | 0x0000, /* R147 */ | ||
1492 | 0x0000, /* R148 */ | ||
1493 | 0x0000, /* R149 */ | ||
1494 | 0x0000, /* R150 */ | ||
1495 | 0x0000, /* R151 */ | ||
1496 | 0x7000, /* R152 - AUX1 Readback */ | ||
1497 | 0x7000, /* R153 - AUX2 Readback */ | ||
1498 | 0x7000, /* R154 - AUX3 Readback */ | ||
1499 | 0x7000, /* R155 - AUX4 Readback */ | ||
1500 | 0x0000, /* R156 - USB Voltage Readback */ | ||
1501 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
1502 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
1503 | 0x0000, /* R159 - Chip Temp Readback */ | ||
1504 | 0x0000, /* R160 */ | ||
1505 | 0x0000, /* R161 */ | ||
1506 | 0x0000, /* R162 */ | ||
1507 | 0x0000, /* R163 - Generic Comparator Control */ | ||
1508 | 0x0000, /* R164 - Generic comparator 1 */ | ||
1509 | 0x0000, /* R165 - Generic comparator 2 */ | ||
1510 | 0x0000, /* R166 - Generic comparator 3 */ | ||
1511 | 0x0000, /* R167 - Generic comparator 4 */ | ||
1512 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
1513 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
1514 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
1515 | 0x0000, /* R171 */ | ||
1516 | 0x0000, /* R172 - Current Sink Driver A */ | ||
1517 | 0x0000, /* R173 - CSA Flash control */ | ||
1518 | 0x0000, /* R174 */ | ||
1519 | 0x0000, /* R175 */ | ||
1520 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
1521 | 0x032D, /* R177 - DCDC Active options */ | ||
1522 | 0x0000, /* R178 - DCDC Sleep options */ | ||
1523 | 0x0025, /* R179 - Power-check comparator */ | ||
1524 | 0x000E, /* R180 - DCDC1 Control */ | ||
1525 | 0x0C00, /* R181 - DCDC1 Timeouts */ | ||
1526 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
1527 | 0x0018, /* R183 - DCDC2 Control */ | ||
1528 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
1529 | 0x0000, /* R185 */ | ||
1530 | 0x0026, /* R186 - DCDC3 Control */ | ||
1531 | 0x0400, /* R187 - DCDC3 Timeouts */ | ||
1532 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
1533 | 0x0062, /* R189 - DCDC4 Control */ | ||
1534 | 0x0800, /* R190 - DCDC4 Timeouts */ | ||
1535 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
1536 | 0x0008, /* R192 */ | ||
1537 | 0x0000, /* R193 */ | ||
1538 | 0x0000, /* R194 */ | ||
1539 | 0x000A, /* R195 */ | ||
1540 | 0x1000, /* R196 */ | ||
1541 | 0x0006, /* R197 */ | ||
1542 | 0x0000, /* R198 */ | ||
1543 | 0x0003, /* R199 - Limit Switch Control */ | ||
1544 | 0x0006, /* R200 - LDO1 Control */ | ||
1545 | 0x0000, /* R201 - LDO1 Timeouts */ | ||
1546 | 0x001C, /* R202 - LDO1 Low Power */ | ||
1547 | 0x0010, /* R203 - LDO2 Control */ | ||
1548 | 0x0C00, /* R204 - LDO2 Timeouts */ | ||
1549 | 0x001C, /* R205 - LDO2 Low Power */ | ||
1550 | 0x001F, /* R206 - LDO3 Control */ | ||
1551 | 0x0800, /* R207 - LDO3 Timeouts */ | ||
1552 | 0x001C, /* R208 - LDO3 Low Power */ | ||
1553 | 0x000A, /* R209 - LDO4 Control */ | ||
1554 | 0x0800, /* R210 - LDO4 Timeouts */ | ||
1555 | 0x001C, /* R211 - LDO4 Low Power */ | ||
1556 | 0x0000, /* R212 */ | ||
1557 | 0x0000, /* R213 */ | ||
1558 | 0x0000, /* R214 */ | ||
1559 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
1560 | 0x001F, /* R216 - Main Bandgap Control */ | ||
1561 | 0x0000, /* R217 - OSC Control */ | ||
1562 | 0x9000, /* R218 - RTC Tick Control */ | ||
1563 | 0x0000, /* R219 - Security1 */ | ||
1564 | 0x4000, /* R220 */ | ||
1565 | 0x0000, /* R221 */ | ||
1566 | 0x0000, /* R222 */ | ||
1567 | 0x0000, /* R223 */ | ||
1568 | 0x0000, /* R224 - Signal overrides */ | ||
1569 | 0x0000, /* R225 - DCDC/LDO status */ | ||
1570 | 0x0000, /* R226 - Charger Overides/status */ | ||
1571 | 0x0000, /* R227 - misc overrides */ | ||
1572 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
1573 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
1574 | 0xE000, /* R230 - GPIO Pin Status */ | ||
1575 | 0x0000, /* R231 - comparotor overrides */ | ||
1576 | 0x0000, /* R232 */ | ||
1577 | 0x0000, /* R233 - State Machine status */ | ||
1578 | 0x1200, /* R234 - FLL Test 1 */ | ||
1579 | 0x0000, /* R235 */ | ||
1580 | 0x8000, /* R236 */ | ||
1581 | 0x0000, /* R237 */ | ||
1582 | 0x0000, /* R238 */ | ||
1583 | 0x0000, /* R239 */ | ||
1584 | 0x0003, /* R240 */ | ||
1585 | 0x0000, /* R241 */ | ||
1586 | 0x0000, /* R242 */ | ||
1587 | 0x0004, /* R243 */ | ||
1588 | 0x0300, /* R244 */ | ||
1589 | 0x0000, /* R245 */ | ||
1590 | 0x0200, /* R246 */ | ||
1591 | 0x1000, /* R247 */ | ||
1592 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
1593 | 0x1000, /* R249 */ | ||
1594 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
1595 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
1596 | }; | ||
1597 | #endif | ||
1598 | |||
1599 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2 | ||
1600 | |||
1601 | #undef WM8350_HAVE_CONFIG_MODE | ||
1602 | #define WM8350_HAVE_CONFIG_MODE | ||
1603 | |||
1604 | const u16 wm8351_mode2_defaults[] = { | ||
1605 | 0x6143, /* R0 - Reset/ID */ | ||
1606 | 0x0000, /* R1 - ID */ | ||
1607 | 0x0001, /* R2 - Revision */ | ||
1608 | 0x1C02, /* R3 - System Control 1 */ | ||
1609 | 0x0214, /* R4 - System Control 2 */ | ||
1610 | 0x0000, /* R5 - System Hibernate */ | ||
1611 | 0x8A00, /* R6 - Interface Control */ | ||
1612 | 0x0000, /* R7 */ | ||
1613 | 0x8000, /* R8 - Power mgmt (1) */ | ||
1614 | 0x0000, /* R9 - Power mgmt (2) */ | ||
1615 | 0x0000, /* R10 - Power mgmt (3) */ | ||
1616 | 0x2000, /* R11 - Power mgmt (4) */ | ||
1617 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
1618 | 0x0000, /* R13 - Power mgmt (6) */ | ||
1619 | 0x0000, /* R14 - Power mgmt (7) */ | ||
1620 | 0x0000, /* R15 */ | ||
1621 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
1622 | 0x0100, /* R17 - RTC Hours/Day */ | ||
1623 | 0x0101, /* R18 - RTC Date/Month */ | ||
1624 | 0x1400, /* R19 - RTC Year */ | ||
1625 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
1626 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
1627 | 0x0000, /* R22 - Alarm Date/Month */ | ||
1628 | 0x0320, /* R23 - RTC Time Control */ | ||
1629 | 0x0000, /* R24 - System Interrupts */ | ||
1630 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
1631 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
1632 | 0x0000, /* R27 */ | ||
1633 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
1634 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
1635 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
1636 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
1637 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
1638 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
1639 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
1640 | 0x0000, /* R35 */ | ||
1641 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
1642 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
1643 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
1644 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
1645 | 0x0040, /* R40 - Clock Control 1 */ | ||
1646 | 0x0000, /* R41 - Clock Control 2 */ | ||
1647 | 0x3A00, /* R42 - FLL Control 1 */ | ||
1648 | 0x7086, /* R43 - FLL Control 2 */ | ||
1649 | 0xC226, /* R44 - FLL Control 3 */ | ||
1650 | 0x0000, /* R45 - FLL Control 4 */ | ||
1651 | 0x0000, /* R46 */ | ||
1652 | 0x0000, /* R47 */ | ||
1653 | 0x0000, /* R48 - DAC Control */ | ||
1654 | 0x0000, /* R49 */ | ||
1655 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
1656 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
1657 | 0x0000, /* R52 */ | ||
1658 | 0x0040, /* R53 - DAC LR Rate */ | ||
1659 | 0x0000, /* R54 - DAC Clock Control */ | ||
1660 | 0x0000, /* R55 */ | ||
1661 | 0x0000, /* R56 */ | ||
1662 | 0x0000, /* R57 */ | ||
1663 | 0x4000, /* R58 - DAC Mute */ | ||
1664 | 0x0000, /* R59 - DAC Mute Volume */ | ||
1665 | 0x0000, /* R60 - DAC Side */ | ||
1666 | 0x0000, /* R61 */ | ||
1667 | 0x0000, /* R62 */ | ||
1668 | 0x0000, /* R63 */ | ||
1669 | 0x8000, /* R64 - ADC Control */ | ||
1670 | 0x0000, /* R65 */ | ||
1671 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
1672 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
1673 | 0x0000, /* R68 - ADC Divider */ | ||
1674 | 0x0000, /* R69 */ | ||
1675 | 0x0040, /* R70 - ADC LR Rate */ | ||
1676 | 0x0000, /* R71 */ | ||
1677 | 0x0303, /* R72 - Input Control */ | ||
1678 | 0x0000, /* R73 - IN3 Input Control */ | ||
1679 | 0x0000, /* R74 - Mic Bias Control */ | ||
1680 | 0x0000, /* R75 */ | ||
1681 | 0x0000, /* R76 - Output Control */ | ||
1682 | 0x0000, /* R77 - Jack Detect */ | ||
1683 | 0x0000, /* R78 - Anti Pop Control */ | ||
1684 | 0x0000, /* R79 */ | ||
1685 | 0x0040, /* R80 - Left Input Volume */ | ||
1686 | 0x0040, /* R81 - Right Input Volume */ | ||
1687 | 0x0000, /* R82 */ | ||
1688 | 0x0000, /* R83 */ | ||
1689 | 0x0000, /* R84 */ | ||
1690 | 0x0000, /* R85 */ | ||
1691 | 0x0000, /* R86 */ | ||
1692 | 0x0000, /* R87 */ | ||
1693 | 0x0800, /* R88 - Left Mixer Control */ | ||
1694 | 0x1000, /* R89 - Right Mixer Control */ | ||
1695 | 0x0000, /* R90 */ | ||
1696 | 0x0000, /* R91 */ | ||
1697 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
1698 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
1699 | 0x0000, /* R94 */ | ||
1700 | 0x0000, /* R95 */ | ||
1701 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
1702 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
1703 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
1704 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
1705 | 0x0000, /* R100 - Input Mixer Volume */ | ||
1706 | 0x0000, /* R101 */ | ||
1707 | 0x0000, /* R102 */ | ||
1708 | 0x0000, /* R103 */ | ||
1709 | 0x00E4, /* R104 - OUT1L Volume */ | ||
1710 | 0x00E4, /* R105 - OUT1R Volume */ | ||
1711 | 0x00E4, /* R106 - OUT2L Volume */ | ||
1712 | 0x02E4, /* R107 - OUT2R Volume */ | ||
1713 | 0x0000, /* R108 */ | ||
1714 | 0x0000, /* R109 */ | ||
1715 | 0x0000, /* R110 */ | ||
1716 | 0x0000, /* R111 - BEEP Volume */ | ||
1717 | 0x0A00, /* R112 - AI Formating */ | ||
1718 | 0x0000, /* R113 - ADC DAC COMP */ | ||
1719 | 0x0020, /* R114 - AI ADC Control */ | ||
1720 | 0x0020, /* R115 - AI DAC Control */ | ||
1721 | 0x0000, /* R116 */ | ||
1722 | 0x0000, /* R117 */ | ||
1723 | 0x0000, /* R118 */ | ||
1724 | 0x0000, /* R119 */ | ||
1725 | 0x0000, /* R120 */ | ||
1726 | 0x0000, /* R121 */ | ||
1727 | 0x0000, /* R122 */ | ||
1728 | 0x0000, /* R123 */ | ||
1729 | 0x0000, /* R124 */ | ||
1730 | 0x0000, /* R125 */ | ||
1731 | 0x0000, /* R126 */ | ||
1732 | 0x0000, /* R127 */ | ||
1733 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
1734 | 0x0000, /* R129 - GPIO Pin pull up Control */ | ||
1735 | 0x0110, /* R130 - GPIO Pull down Control */ | ||
1736 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
1737 | 0x0000, /* R132 */ | ||
1738 | 0x0000, /* R133 - GPIO Control */ | ||
1739 | 0x09FA, /* R134 - GPIO Configuration (i/o) */ | ||
1740 | 0x0DF6, /* R135 - GPIO Pin Polarity / Type */ | ||
1741 | 0x0000, /* R136 */ | ||
1742 | 0x0000, /* R137 */ | ||
1743 | 0x0000, /* R138 */ | ||
1744 | 0x0000, /* R139 */ | ||
1745 | 0x1310, /* R140 - GPIO Function Select 1 */ | ||
1746 | 0x0003, /* R141 - GPIO Function Select 2 */ | ||
1747 | 0x2000, /* R142 - GPIO Function Select 3 */ | ||
1748 | 0x0000, /* R143 - GPIO Function Select 4 */ | ||
1749 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
1750 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
1751 | 0x0000, /* R146 */ | ||
1752 | 0x0000, /* R147 */ | ||
1753 | 0x0000, /* R148 */ | ||
1754 | 0x0000, /* R149 */ | ||
1755 | 0x0000, /* R150 */ | ||
1756 | 0x0000, /* R151 */ | ||
1757 | 0x7000, /* R152 - AUX1 Readback */ | ||
1758 | 0x7000, /* R153 - AUX2 Readback */ | ||
1759 | 0x7000, /* R154 - AUX3 Readback */ | ||
1760 | 0x7000, /* R155 - AUX4 Readback */ | ||
1761 | 0x0000, /* R156 - USB Voltage Readback */ | ||
1762 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
1763 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
1764 | 0x0000, /* R159 - Chip Temp Readback */ | ||
1765 | 0x0000, /* R160 */ | ||
1766 | 0x0000, /* R161 */ | ||
1767 | 0x0000, /* R162 */ | ||
1768 | 0x0000, /* R163 - Generic Comparator Control */ | ||
1769 | 0x0000, /* R164 - Generic comparator 1 */ | ||
1770 | 0x0000, /* R165 - Generic comparator 2 */ | ||
1771 | 0x0000, /* R166 - Generic comparator 3 */ | ||
1772 | 0x0000, /* R167 - Generic comparator 4 */ | ||
1773 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
1774 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
1775 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
1776 | 0x0000, /* R171 */ | ||
1777 | 0x0000, /* R172 - Current Sink Driver A */ | ||
1778 | 0x0000, /* R173 - CSA Flash control */ | ||
1779 | 0x0000, /* R174 */ | ||
1780 | 0x0000, /* R175 */ | ||
1781 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
1782 | 0x032D, /* R177 - DCDC Active options */ | ||
1783 | 0x0000, /* R178 - DCDC Sleep options */ | ||
1784 | 0x0025, /* R179 - Power-check comparator */ | ||
1785 | 0x001A, /* R180 - DCDC1 Control */ | ||
1786 | 0x0800, /* R181 - DCDC1 Timeouts */ | ||
1787 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
1788 | 0x0018, /* R183 - DCDC2 Control */ | ||
1789 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
1790 | 0x0000, /* R185 */ | ||
1791 | 0x0056, /* R186 - DCDC3 Control */ | ||
1792 | 0x0400, /* R187 - DCDC3 Timeouts */ | ||
1793 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
1794 | 0x0026, /* R189 - DCDC4 Control */ | ||
1795 | 0x0C00, /* R190 - DCDC4 Timeouts */ | ||
1796 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
1797 | 0x0008, /* R192 */ | ||
1798 | 0x0000, /* R193 */ | ||
1799 | 0x0000, /* R194 */ | ||
1800 | 0x0026, /* R195 */ | ||
1801 | 0x0C00, /* R196 */ | ||
1802 | 0x0006, /* R197 */ | ||
1803 | 0x0000, /* R198 */ | ||
1804 | 0x0003, /* R199 - Limit Switch Control */ | ||
1805 | 0x001C, /* R200 - LDO1 Control */ | ||
1806 | 0x0400, /* R201 - LDO1 Timeouts */ | ||
1807 | 0x001C, /* R202 - LDO1 Low Power */ | ||
1808 | 0x0010, /* R203 - LDO2 Control */ | ||
1809 | 0x0C00, /* R204 - LDO2 Timeouts */ | ||
1810 | 0x001C, /* R205 - LDO2 Low Power */ | ||
1811 | 0x0015, /* R206 - LDO3 Control */ | ||
1812 | 0x0000, /* R207 - LDO3 Timeouts */ | ||
1813 | 0x001C, /* R208 - LDO3 Low Power */ | ||
1814 | 0x001A, /* R209 - LDO4 Control */ | ||
1815 | 0x0000, /* R210 - LDO4 Timeouts */ | ||
1816 | 0x001C, /* R211 - LDO4 Low Power */ | ||
1817 | 0x0000, /* R212 */ | ||
1818 | 0x0000, /* R213 */ | ||
1819 | 0x0000, /* R214 */ | ||
1820 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
1821 | 0x001F, /* R216 - Main Bandgap Control */ | ||
1822 | 0x0000, /* R217 - OSC Control */ | ||
1823 | 0x9000, /* R218 - RTC Tick Control */ | ||
1824 | 0x0000, /* R219 - Security1 */ | ||
1825 | 0x4000, /* R220 */ | ||
1826 | 0x0000, /* R221 */ | ||
1827 | 0x0000, /* R222 */ | ||
1828 | 0x0000, /* R223 */ | ||
1829 | 0x0000, /* R224 - Signal overrides */ | ||
1830 | 0x0000, /* R225 - DCDC/LDO status */ | ||
1831 | 0x0000, /* R226 - Charger Overides/status */ | ||
1832 | 0x0000, /* R227 - misc overrides */ | ||
1833 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
1834 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
1835 | 0xE000, /* R230 - GPIO Pin Status */ | ||
1836 | 0x0000, /* R231 - comparotor overrides */ | ||
1837 | 0x0000, /* R232 */ | ||
1838 | 0x0000, /* R233 - State Machine status */ | ||
1839 | 0x1200, /* R234 - FLL Test 1 */ | ||
1840 | 0x0000, /* R235 */ | ||
1841 | 0x8000, /* R236 */ | ||
1842 | 0x0000, /* R237 */ | ||
1843 | 0x0000, /* R238 */ | ||
1844 | 0x0000, /* R239 */ | ||
1845 | 0x0003, /* R240 */ | ||
1846 | 0x0000, /* R241 */ | ||
1847 | 0x0000, /* R242 */ | ||
1848 | 0x0004, /* R243 */ | ||
1849 | 0x0300, /* R244 */ | ||
1850 | 0x0000, /* R245 */ | ||
1851 | 0x0200, /* R246 */ | ||
1852 | 0x0000, /* R247 */ | ||
1853 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
1854 | 0x1000, /* R249 */ | ||
1855 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
1856 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
1857 | }; | ||
1858 | #endif | ||
1859 | |||
1860 | #ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3 | ||
1861 | |||
1862 | #undef WM8350_HAVE_CONFIG_MODE | ||
1863 | #define WM8350_HAVE_CONFIG_MODE | ||
1864 | |||
1865 | const u16 wm8351_mode3_defaults[] = { | ||
1866 | 0x6143, /* R0 - Reset/ID */ | ||
1867 | 0x0000, /* R1 - ID */ | ||
1868 | 0x0001, /* R2 - Revision */ | ||
1869 | 0x1C02, /* R3 - System Control 1 */ | ||
1870 | 0x0204, /* R4 - System Control 2 */ | ||
1871 | 0x0000, /* R5 - System Hibernate */ | ||
1872 | 0x8A00, /* R6 - Interface Control */ | ||
1873 | 0x0000, /* R7 */ | ||
1874 | 0x8000, /* R8 - Power mgmt (1) */ | ||
1875 | 0x0000, /* R9 - Power mgmt (2) */ | ||
1876 | 0x0000, /* R10 - Power mgmt (3) */ | ||
1877 | 0x2000, /* R11 - Power mgmt (4) */ | ||
1878 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
1879 | 0x0000, /* R13 - Power mgmt (6) */ | ||
1880 | 0x0000, /* R14 - Power mgmt (7) */ | ||
1881 | 0x0000, /* R15 */ | ||
1882 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
1883 | 0x0100, /* R17 - RTC Hours/Day */ | ||
1884 | 0x0101, /* R18 - RTC Date/Month */ | ||
1885 | 0x1400, /* R19 - RTC Year */ | ||
1886 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
1887 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
1888 | 0x0000, /* R22 - Alarm Date/Month */ | ||
1889 | 0x0320, /* R23 - RTC Time Control */ | ||
1890 | 0x0000, /* R24 - System Interrupts */ | ||
1891 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
1892 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
1893 | 0x0000, /* R27 */ | ||
1894 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
1895 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
1896 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
1897 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
1898 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
1899 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
1900 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
1901 | 0x0000, /* R35 */ | ||
1902 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
1903 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
1904 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
1905 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
1906 | 0x0040, /* R40 - Clock Control 1 */ | ||
1907 | 0x0000, /* R41 - Clock Control 2 */ | ||
1908 | 0x3A00, /* R42 - FLL Control 1 */ | ||
1909 | 0x7086, /* R43 - FLL Control 2 */ | ||
1910 | 0xC226, /* R44 - FLL Control 3 */ | ||
1911 | 0x0000, /* R45 - FLL Control 4 */ | ||
1912 | 0x0000, /* R46 */ | ||
1913 | 0x0000, /* R47 */ | ||
1914 | 0x0000, /* R48 - DAC Control */ | ||
1915 | 0x0000, /* R49 */ | ||
1916 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
1917 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
1918 | 0x0000, /* R52 */ | ||
1919 | 0x0040, /* R53 - DAC LR Rate */ | ||
1920 | 0x0000, /* R54 - DAC Clock Control */ | ||
1921 | 0x0000, /* R55 */ | ||
1922 | 0x0000, /* R56 */ | ||
1923 | 0x0000, /* R57 */ | ||
1924 | 0x4000, /* R58 - DAC Mute */ | ||
1925 | 0x0000, /* R59 - DAC Mute Volume */ | ||
1926 | 0x0000, /* R60 - DAC Side */ | ||
1927 | 0x0000, /* R61 */ | ||
1928 | 0x0000, /* R62 */ | ||
1929 | 0x0000, /* R63 */ | ||
1930 | 0x8000, /* R64 - ADC Control */ | ||
1931 | 0x0000, /* R65 */ | ||
1932 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
1933 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
1934 | 0x0000, /* R68 - ADC Divider */ | ||
1935 | 0x0000, /* R69 */ | ||
1936 | 0x0040, /* R70 - ADC LR Rate */ | ||
1937 | 0x0000, /* R71 */ | ||
1938 | 0x0303, /* R72 - Input Control */ | ||
1939 | 0x0000, /* R73 - IN3 Input Control */ | ||
1940 | 0x0000, /* R74 - Mic Bias Control */ | ||
1941 | 0x0000, /* R75 */ | ||
1942 | 0x0000, /* R76 - Output Control */ | ||
1943 | 0x0000, /* R77 - Jack Detect */ | ||
1944 | 0x0000, /* R78 - Anti Pop Control */ | ||
1945 | 0x0000, /* R79 */ | ||
1946 | 0x0040, /* R80 - Left Input Volume */ | ||
1947 | 0x0040, /* R81 - Right Input Volume */ | ||
1948 | 0x0000, /* R82 */ | ||
1949 | 0x0000, /* R83 */ | ||
1950 | 0x0000, /* R84 */ | ||
1951 | 0x0000, /* R85 */ | ||
1952 | 0x0000, /* R86 */ | ||
1953 | 0x0000, /* R87 */ | ||
1954 | 0x0800, /* R88 - Left Mixer Control */ | ||
1955 | 0x1000, /* R89 - Right Mixer Control */ | ||
1956 | 0x0000, /* R90 */ | ||
1957 | 0x0000, /* R91 */ | ||
1958 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
1959 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
1960 | 0x0000, /* R94 */ | ||
1961 | 0x0000, /* R95 */ | ||
1962 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
1963 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
1964 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
1965 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
1966 | 0x0000, /* R100 - Input Mixer Volume */ | ||
1967 | 0x0000, /* R101 */ | ||
1968 | 0x0000, /* R102 */ | ||
1969 | 0x0000, /* R103 */ | ||
1970 | 0x00E4, /* R104 - OUT1L Volume */ | ||
1971 | 0x00E4, /* R105 - OUT1R Volume */ | ||
1972 | 0x00E4, /* R106 - OUT2L Volume */ | ||
1973 | 0x02E4, /* R107 - OUT2R Volume */ | ||
1974 | 0x0000, /* R108 */ | ||
1975 | 0x0000, /* R109 */ | ||
1976 | 0x0000, /* R110 */ | ||
1977 | 0x0000, /* R111 - BEEP Volume */ | ||
1978 | 0x0A00, /* R112 - AI Formating */ | ||
1979 | 0x0000, /* R113 - ADC DAC COMP */ | ||
1980 | 0x0020, /* R114 - AI ADC Control */ | ||
1981 | 0x0020, /* R115 - AI DAC Control */ | ||
1982 | 0x0000, /* R116 */ | ||
1983 | 0x0000, /* R117 */ | ||
1984 | 0x0000, /* R118 */ | ||
1985 | 0x0000, /* R119 */ | ||
1986 | 0x0000, /* R120 */ | ||
1987 | 0x0000, /* R121 */ | ||
1988 | 0x0000, /* R122 */ | ||
1989 | 0x0000, /* R123 */ | ||
1990 | 0x0000, /* R124 */ | ||
1991 | 0x0000, /* R125 */ | ||
1992 | 0x0000, /* R126 */ | ||
1993 | 0x0000, /* R127 */ | ||
1994 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
1995 | 0x0010, /* R129 - GPIO Pin pull up Control */ | ||
1996 | 0x0000, /* R130 - GPIO Pull down Control */ | ||
1997 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
1998 | 0x0000, /* R132 */ | ||
1999 | 0x0000, /* R133 - GPIO Control */ | ||
2000 | 0x0BFB, /* R134 - GPIO Configuration (i/o) */ | ||
2001 | 0x0FFD, /* R135 - GPIO Pin Polarity / Type */ | ||
2002 | 0x0000, /* R136 */ | ||
2003 | 0x0000, /* R137 */ | ||
2004 | 0x0000, /* R138 */ | ||
2005 | 0x0000, /* R139 */ | ||
2006 | 0x0310, /* R140 - GPIO Function Select 1 */ | ||
2007 | 0x0001, /* R141 - GPIO Function Select 2 */ | ||
2008 | 0x2300, /* R142 - GPIO Function Select 3 */ | ||
2009 | 0x0003, /* R143 - GPIO Function Select 4 */ | ||
2010 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
2011 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
2012 | 0x0000, /* R146 */ | ||
2013 | 0x0000, /* R147 */ | ||
2014 | 0x0000, /* R148 */ | ||
2015 | 0x0000, /* R149 */ | ||
2016 | 0x0000, /* R150 */ | ||
2017 | 0x0000, /* R151 */ | ||
2018 | 0x7000, /* R152 - AUX1 Readback */ | ||
2019 | 0x7000, /* R153 - AUX2 Readback */ | ||
2020 | 0x7000, /* R154 - AUX3 Readback */ | ||
2021 | 0x7000, /* R155 - AUX4 Readback */ | ||
2022 | 0x0000, /* R156 - USB Voltage Readback */ | ||
2023 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
2024 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
2025 | 0x0000, /* R159 - Chip Temp Readback */ | ||
2026 | 0x0000, /* R160 */ | ||
2027 | 0x0000, /* R161 */ | ||
2028 | 0x0000, /* R162 */ | ||
2029 | 0x0000, /* R163 - Generic Comparator Control */ | ||
2030 | 0x0000, /* R164 - Generic comparator 1 */ | ||
2031 | 0x0000, /* R165 - Generic comparator 2 */ | ||
2032 | 0x0000, /* R166 - Generic comparator 3 */ | ||
2033 | 0x0000, /* R167 - Generic comparator 4 */ | ||
2034 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
2035 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
2036 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
2037 | 0x0000, /* R171 */ | ||
2038 | 0x0000, /* R172 - Current Sink Driver A */ | ||
2039 | 0x0000, /* R173 - CSA Flash control */ | ||
2040 | 0x0000, /* R174 */ | ||
2041 | 0x0000, /* R175 */ | ||
2042 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
2043 | 0x032D, /* R177 - DCDC Active options */ | ||
2044 | 0x0000, /* R178 - DCDC Sleep options */ | ||
2045 | 0x0025, /* R179 - Power-check comparator */ | ||
2046 | 0x000E, /* R180 - DCDC1 Control */ | ||
2047 | 0x0400, /* R181 - DCDC1 Timeouts */ | ||
2048 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
2049 | 0x0018, /* R183 - DCDC2 Control */ | ||
2050 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
2051 | 0x0000, /* R185 */ | ||
2052 | 0x0026, /* R186 - DCDC3 Control */ | ||
2053 | 0x0800, /* R187 - DCDC3 Timeouts */ | ||
2054 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
2055 | 0x0062, /* R189 - DCDC4 Control */ | ||
2056 | 0x1400, /* R190 - DCDC4 Timeouts */ | ||
2057 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
2058 | 0x0008, /* R192 */ | ||
2059 | 0x0000, /* R193 */ | ||
2060 | 0x0000, /* R194 */ | ||
2061 | 0x0026, /* R195 */ | ||
2062 | 0x0400, /* R196 */ | ||
2063 | 0x0006, /* R197 */ | ||
2064 | 0x0000, /* R198 */ | ||
2065 | 0x0003, /* R199 - Limit Switch Control */ | ||
2066 | 0x0006, /* R200 - LDO1 Control */ | ||
2067 | 0x0C00, /* R201 - LDO1 Timeouts */ | ||
2068 | 0x001C, /* R202 - LDO1 Low Power */ | ||
2069 | 0x0016, /* R203 - LDO2 Control */ | ||
2070 | 0x0000, /* R204 - LDO2 Timeouts */ | ||
2071 | 0x001C, /* R205 - LDO2 Low Power */ | ||
2072 | 0x0019, /* R206 - LDO3 Control */ | ||
2073 | 0x0000, /* R207 - LDO3 Timeouts */ | ||
2074 | 0x001C, /* R208 - LDO3 Low Power */ | ||
2075 | 0x001A, /* R209 - LDO4 Control */ | ||
2076 | 0x1000, /* R210 - LDO4 Timeouts */ | ||
2077 | 0x001C, /* R211 - LDO4 Low Power */ | ||
2078 | 0x0000, /* R212 */ | ||
2079 | 0x0000, /* R213 */ | ||
2080 | 0x0000, /* R214 */ | ||
2081 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
2082 | 0x001F, /* R216 - Main Bandgap Control */ | ||
2083 | 0x0000, /* R217 - OSC Control */ | ||
2084 | 0x9000, /* R218 - RTC Tick Control */ | ||
2085 | 0x0000, /* R219 - Security1 */ | ||
2086 | 0x4000, /* R220 */ | ||
2087 | 0x0000, /* R221 */ | ||
2088 | 0x0000, /* R222 */ | ||
2089 | 0x0000, /* R223 */ | ||
2090 | 0x0000, /* R224 - Signal overrides */ | ||
2091 | 0x0000, /* R225 - DCDC/LDO status */ | ||
2092 | 0x0000, /* R226 - Charger Overides/status */ | ||
2093 | 0x0000, /* R227 - misc overrides */ | ||
2094 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
2095 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
2096 | 0xE000, /* R230 - GPIO Pin Status */ | ||
2097 | 0x0000, /* R231 - comparotor overrides */ | ||
2098 | 0x0000, /* R232 */ | ||
2099 | 0x0000, /* R233 - State Machine status */ | ||
2100 | 0x1200, /* R234 - FLL Test 1 */ | ||
2101 | 0x0000, /* R235 */ | ||
2102 | 0x8000, /* R236 */ | ||
2103 | 0x0000, /* R237 */ | ||
2104 | 0x0000, /* R238 */ | ||
2105 | 0x0000, /* R239 */ | ||
2106 | 0x0003, /* R240 */ | ||
2107 | 0x0000, /* R241 */ | ||
2108 | 0x0000, /* R242 */ | ||
2109 | 0x0004, /* R243 */ | ||
2110 | 0x0300, /* R244 */ | ||
2111 | 0x0000, /* R245 */ | ||
2112 | 0x0200, /* R246 */ | ||
2113 | 0x0000, /* R247 */ | ||
2114 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
2115 | 0x1000, /* R249 */ | ||
2116 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
2117 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
2118 | }; | ||
2119 | #endif | ||
2120 | |||
2121 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0 | ||
2122 | |||
2123 | #undef WM8350_HAVE_CONFIG_MODE | ||
2124 | #define WM8350_HAVE_CONFIG_MODE | ||
2125 | |||
2126 | const u16 wm8352_mode0_defaults[] = { | ||
2127 | 0x6143, /* R0 - Reset/ID */ | ||
2128 | 0x0000, /* R1 - ID */ | ||
2129 | 0x0002, /* R2 - Revision */ | ||
2130 | 0x1C02, /* R3 - System Control 1 */ | ||
2131 | 0x0004, /* R4 - System Control 2 */ | ||
2132 | 0x0000, /* R5 - System Hibernate */ | ||
2133 | 0x8A00, /* R6 - Interface Control */ | ||
2134 | 0x0000, /* R7 */ | ||
2135 | 0x8000, /* R8 - Power mgmt (1) */ | ||
2136 | 0x0000, /* R9 - Power mgmt (2) */ | ||
2137 | 0x0000, /* R10 - Power mgmt (3) */ | ||
2138 | 0x2000, /* R11 - Power mgmt (4) */ | ||
2139 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
2140 | 0x0000, /* R13 - Power mgmt (6) */ | ||
2141 | 0x0000, /* R14 - Power mgmt (7) */ | ||
2142 | 0x0000, /* R15 */ | ||
2143 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
2144 | 0x0100, /* R17 - RTC Hours/Day */ | ||
2145 | 0x0101, /* R18 - RTC Date/Month */ | ||
2146 | 0x1400, /* R19 - RTC Year */ | ||
2147 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
2148 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
2149 | 0x0000, /* R22 - Alarm Date/Month */ | ||
2150 | 0x0320, /* R23 - RTC Time Control */ | ||
2151 | 0x0000, /* R24 - System Interrupts */ | ||
2152 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
2153 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
2154 | 0x0000, /* R27 */ | ||
2155 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
2156 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
2157 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
2158 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
2159 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
2160 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
2161 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
2162 | 0x0000, /* R35 */ | ||
2163 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
2164 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
2165 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
2166 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
2167 | 0x0040, /* R40 - Clock Control 1 */ | ||
2168 | 0x0000, /* R41 - Clock Control 2 */ | ||
2169 | 0x3A00, /* R42 - FLL Control 1 */ | ||
2170 | 0x7086, /* R43 - FLL Control 2 */ | ||
2171 | 0xC226, /* R44 - FLL Control 3 */ | ||
2172 | 0x0000, /* R45 - FLL Control 4 */ | ||
2173 | 0x0000, /* R46 */ | ||
2174 | 0x0000, /* R47 */ | ||
2175 | 0x0000, /* R48 - DAC Control */ | ||
2176 | 0x0000, /* R49 */ | ||
2177 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
2178 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
2179 | 0x0000, /* R52 */ | ||
2180 | 0x0040, /* R53 - DAC LR Rate */ | ||
2181 | 0x0000, /* R54 - DAC Clock Control */ | ||
2182 | 0x0000, /* R55 */ | ||
2183 | 0x0000, /* R56 */ | ||
2184 | 0x0000, /* R57 */ | ||
2185 | 0x4000, /* R58 - DAC Mute */ | ||
2186 | 0x0000, /* R59 - DAC Mute Volume */ | ||
2187 | 0x0000, /* R60 - DAC Side */ | ||
2188 | 0x0000, /* R61 */ | ||
2189 | 0x0000, /* R62 */ | ||
2190 | 0x0000, /* R63 */ | ||
2191 | 0x8000, /* R64 - ADC Control */ | ||
2192 | 0x0000, /* R65 */ | ||
2193 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
2194 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
2195 | 0x0000, /* R68 - ADC Divider */ | ||
2196 | 0x0000, /* R69 */ | ||
2197 | 0x0040, /* R70 - ADC LR Rate */ | ||
2198 | 0x0000, /* R71 */ | ||
2199 | 0x0303, /* R72 - Input Control */ | ||
2200 | 0x0000, /* R73 - IN3 Input Control */ | ||
2201 | 0x0000, /* R74 - Mic Bias Control */ | ||
2202 | 0x0000, /* R75 */ | ||
2203 | 0x0000, /* R76 - Output Control */ | ||
2204 | 0x0000, /* R77 - Jack Detect */ | ||
2205 | 0x0000, /* R78 - Anti Pop Control */ | ||
2206 | 0x0000, /* R79 */ | ||
2207 | 0x0040, /* R80 - Left Input Volume */ | ||
2208 | 0x0040, /* R81 - Right Input Volume */ | ||
2209 | 0x0000, /* R82 */ | ||
2210 | 0x0000, /* R83 */ | ||
2211 | 0x0000, /* R84 */ | ||
2212 | 0x0000, /* R85 */ | ||
2213 | 0x0000, /* R86 */ | ||
2214 | 0x0000, /* R87 */ | ||
2215 | 0x0800, /* R88 - Left Mixer Control */ | ||
2216 | 0x1000, /* R89 - Right Mixer Control */ | ||
2217 | 0x0000, /* R90 */ | ||
2218 | 0x0000, /* R91 */ | ||
2219 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
2220 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
2221 | 0x0000, /* R94 */ | ||
2222 | 0x0000, /* R95 */ | ||
2223 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
2224 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
2225 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
2226 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
2227 | 0x0000, /* R100 - Input Mixer Volume */ | ||
2228 | 0x0000, /* R101 */ | ||
2229 | 0x0000, /* R102 */ | ||
2230 | 0x0000, /* R103 */ | ||
2231 | 0x00E4, /* R104 - OUT1L Volume */ | ||
2232 | 0x00E4, /* R105 - OUT1R Volume */ | ||
2233 | 0x00E4, /* R106 - OUT2L Volume */ | ||
2234 | 0x02E4, /* R107 - OUT2R Volume */ | ||
2235 | 0x0000, /* R108 */ | ||
2236 | 0x0000, /* R109 */ | ||
2237 | 0x0000, /* R110 */ | ||
2238 | 0x0000, /* R111 - BEEP Volume */ | ||
2239 | 0x0A00, /* R112 - AI Formating */ | ||
2240 | 0x0000, /* R113 - ADC DAC COMP */ | ||
2241 | 0x0020, /* R114 - AI ADC Control */ | ||
2242 | 0x0020, /* R115 - AI DAC Control */ | ||
2243 | 0x0000, /* R116 */ | ||
2244 | 0x0000, /* R117 */ | ||
2245 | 0x0000, /* R118 */ | ||
2246 | 0x0000, /* R119 */ | ||
2247 | 0x0000, /* R120 */ | ||
2248 | 0x0000, /* R121 */ | ||
2249 | 0x0000, /* R122 */ | ||
2250 | 0x0000, /* R123 */ | ||
2251 | 0x0000, /* R124 */ | ||
2252 | 0x0000, /* R125 */ | ||
2253 | 0x0000, /* R126 */ | ||
2254 | 0x0000, /* R127 */ | ||
2255 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
2256 | 0x0000, /* R129 - GPIO Pin pull up Control */ | ||
2257 | 0x0000, /* R130 - GPIO Pull down Control */ | ||
2258 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
2259 | 0x0000, /* R132 */ | ||
2260 | 0x0000, /* R133 - GPIO Control */ | ||
2261 | 0x0FFC, /* R134 - GPIO Configuration (i/o) */ | ||
2262 | 0x0FFC, /* R135 - GPIO Pin Polarity / Type */ | ||
2263 | 0x0000, /* R136 */ | ||
2264 | 0x0000, /* R137 */ | ||
2265 | 0x0000, /* R138 */ | ||
2266 | 0x0000, /* R139 */ | ||
2267 | 0x0013, /* R140 - GPIO Function Select 1 */ | ||
2268 | 0x0000, /* R141 - GPIO Function Select 2 */ | ||
2269 | 0x0000, /* R142 - GPIO Function Select 3 */ | ||
2270 | 0x0003, /* R143 - GPIO Function Select 4 */ | ||
2271 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
2272 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
2273 | 0x0000, /* R146 */ | ||
2274 | 0x0000, /* R147 */ | ||
2275 | 0x0000, /* R148 */ | ||
2276 | 0x0000, /* R149 */ | ||
2277 | 0x0000, /* R150 */ | ||
2278 | 0x0000, /* R151 */ | ||
2279 | 0x7000, /* R152 - AUX1 Readback */ | ||
2280 | 0x7000, /* R153 - AUX2 Readback */ | ||
2281 | 0x7000, /* R154 - AUX3 Readback */ | ||
2282 | 0x7000, /* R155 - AUX4 Readback */ | ||
2283 | 0x0000, /* R156 - USB Voltage Readback */ | ||
2284 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
2285 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
2286 | 0x0000, /* R159 - Chip Temp Readback */ | ||
2287 | 0x0000, /* R160 */ | ||
2288 | 0x0000, /* R161 */ | ||
2289 | 0x0000, /* R162 */ | ||
2290 | 0x0000, /* R163 - Generic Comparator Control */ | ||
2291 | 0x0000, /* R164 - Generic comparator 1 */ | ||
2292 | 0x0000, /* R165 - Generic comparator 2 */ | ||
2293 | 0x0000, /* R166 - Generic comparator 3 */ | ||
2294 | 0x0000, /* R167 - Generic comparator 4 */ | ||
2295 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
2296 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
2297 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
2298 | 0x0000, /* R171 */ | ||
2299 | 0x0000, /* R172 - Current Sink Driver A */ | ||
2300 | 0x0000, /* R173 - CSA Flash control */ | ||
2301 | 0x0000, /* R174 - Current Sink Driver B */ | ||
2302 | 0x0000, /* R175 - CSB Flash control */ | ||
2303 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
2304 | 0x032D, /* R177 - DCDC Active options */ | ||
2305 | 0x0000, /* R178 - DCDC Sleep options */ | ||
2306 | 0x0025, /* R179 - Power-check comparator */ | ||
2307 | 0x000E, /* R180 - DCDC1 Control */ | ||
2308 | 0x0000, /* R181 - DCDC1 Timeouts */ | ||
2309 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
2310 | 0x0018, /* R183 - DCDC2 Control */ | ||
2311 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
2312 | 0x0000, /* R185 */ | ||
2313 | 0x0000, /* R186 - DCDC3 Control */ | ||
2314 | 0x0000, /* R187 - DCDC3 Timeouts */ | ||
2315 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
2316 | 0x0000, /* R189 - DCDC4 Control */ | ||
2317 | 0x0000, /* R190 - DCDC4 Timeouts */ | ||
2318 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
2319 | 0x0008, /* R192 - DCDC5 Control */ | ||
2320 | 0x0000, /* R193 - DCDC5 Timeouts */ | ||
2321 | 0x0000, /* R194 */ | ||
2322 | 0x0000, /* R195 - DCDC6 Control */ | ||
2323 | 0x0000, /* R196 - DCDC6 Timeouts */ | ||
2324 | 0x0006, /* R197 - DCDC6 Low Power */ | ||
2325 | 0x0000, /* R198 */ | ||
2326 | 0x0003, /* R199 - Limit Switch Control */ | ||
2327 | 0x001C, /* R200 - LDO1 Control */ | ||
2328 | 0x0000, /* R201 - LDO1 Timeouts */ | ||
2329 | 0x001C, /* R202 - LDO1 Low Power */ | ||
2330 | 0x001B, /* R203 - LDO2 Control */ | ||
2331 | 0x0000, /* R204 - LDO2 Timeouts */ | ||
2332 | 0x001C, /* R205 - LDO2 Low Power */ | ||
2333 | 0x001B, /* R206 - LDO3 Control */ | ||
2334 | 0x0000, /* R207 - LDO3 Timeouts */ | ||
2335 | 0x001C, /* R208 - LDO3 Low Power */ | ||
2336 | 0x001B, /* R209 - LDO4 Control */ | ||
2337 | 0x0000, /* R210 - LDO4 Timeouts */ | ||
2338 | 0x001C, /* R211 - LDO4 Low Power */ | ||
2339 | 0x0000, /* R212 */ | ||
2340 | 0x0000, /* R213 */ | ||
2341 | 0x0000, /* R214 */ | ||
2342 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
2343 | 0x001F, /* R216 - Main Bandgap Control */ | ||
2344 | 0x0000, /* R217 - OSC Control */ | ||
2345 | 0x9000, /* R218 - RTC Tick Control */ | ||
2346 | 0x0000, /* R219 - Security1 */ | ||
2347 | 0x4000, /* R220 */ | ||
2348 | 0x0000, /* R221 */ | ||
2349 | 0x0000, /* R222 */ | ||
2350 | 0x0000, /* R223 */ | ||
2351 | 0x0000, /* R224 - Signal overrides */ | ||
2352 | 0x0000, /* R225 - DCDC/LDO status */ | ||
2353 | 0x0000, /* R226 - Charger Overides/status */ | ||
2354 | 0x0000, /* R227 - misc overrides */ | ||
2355 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
2356 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
2357 | 0xE000, /* R230 - GPIO Pin Status */ | ||
2358 | 0x0000, /* R231 - comparotor overrides */ | ||
2359 | 0x0000, /* R232 */ | ||
2360 | 0x0000, /* R233 - State Machine status */ | ||
2361 | 0x1200, /* R234 */ | ||
2362 | 0x0000, /* R235 */ | ||
2363 | 0x8000, /* R236 */ | ||
2364 | 0x0000, /* R237 */ | ||
2365 | 0x0000, /* R238 */ | ||
2366 | 0x0000, /* R239 */ | ||
2367 | 0x0003, /* R240 */ | ||
2368 | 0x0000, /* R241 */ | ||
2369 | 0x0000, /* R242 */ | ||
2370 | 0x0004, /* R243 */ | ||
2371 | 0x0300, /* R244 */ | ||
2372 | 0x0000, /* R245 */ | ||
2373 | 0x0200, /* R246 */ | ||
2374 | 0x0000, /* R247 */ | ||
2375 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
2376 | 0x5000, /* R249 */ | ||
2377 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
2378 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
2379 | 0x5100, /* R252 */ | ||
2380 | 0x1000, /* R253 - DCDC6 Test Controls */ | ||
2381 | }; | ||
2382 | #endif | ||
2383 | |||
2384 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1 | ||
2385 | |||
2386 | #undef WM8350_HAVE_CONFIG_MODE | ||
2387 | #define WM8350_HAVE_CONFIG_MODE | ||
2388 | |||
2389 | const u16 wm8352_mode1_defaults[] = { | ||
2390 | 0x6143, /* R0 - Reset/ID */ | ||
2391 | 0x0000, /* R1 - ID */ | ||
2392 | 0x0002, /* R2 - Revision */ | ||
2393 | 0x1C02, /* R3 - System Control 1 */ | ||
2394 | 0x0204, /* R4 - System Control 2 */ | ||
2395 | 0x0000, /* R5 - System Hibernate */ | ||
2396 | 0x8A00, /* R6 - Interface Control */ | ||
2397 | 0x0000, /* R7 */ | ||
2398 | 0x8000, /* R8 - Power mgmt (1) */ | ||
2399 | 0x0000, /* R9 - Power mgmt (2) */ | ||
2400 | 0x0000, /* R10 - Power mgmt (3) */ | ||
2401 | 0x2000, /* R11 - Power mgmt (4) */ | ||
2402 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
2403 | 0x0000, /* R13 - Power mgmt (6) */ | ||
2404 | 0x0000, /* R14 - Power mgmt (7) */ | ||
2405 | 0x0000, /* R15 */ | ||
2406 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
2407 | 0x0100, /* R17 - RTC Hours/Day */ | ||
2408 | 0x0101, /* R18 - RTC Date/Month */ | ||
2409 | 0x1400, /* R19 - RTC Year */ | ||
2410 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
2411 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
2412 | 0x0000, /* R22 - Alarm Date/Month */ | ||
2413 | 0x0320, /* R23 - RTC Time Control */ | ||
2414 | 0x0000, /* R24 - System Interrupts */ | ||
2415 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
2416 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
2417 | 0x0000, /* R27 */ | ||
2418 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
2419 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
2420 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
2421 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
2422 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
2423 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
2424 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
2425 | 0x0000, /* R35 */ | ||
2426 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
2427 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
2428 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
2429 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
2430 | 0x0040, /* R40 - Clock Control 1 */ | ||
2431 | 0x0000, /* R41 - Clock Control 2 */ | ||
2432 | 0x3A00, /* R42 - FLL Control 1 */ | ||
2433 | 0x7086, /* R43 - FLL Control 2 */ | ||
2434 | 0xC226, /* R44 - FLL Control 3 */ | ||
2435 | 0x0000, /* R45 - FLL Control 4 */ | ||
2436 | 0x0000, /* R46 */ | ||
2437 | 0x0000, /* R47 */ | ||
2438 | 0x0000, /* R48 - DAC Control */ | ||
2439 | 0x0000, /* R49 */ | ||
2440 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
2441 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
2442 | 0x0000, /* R52 */ | ||
2443 | 0x0040, /* R53 - DAC LR Rate */ | ||
2444 | 0x0000, /* R54 - DAC Clock Control */ | ||
2445 | 0x0000, /* R55 */ | ||
2446 | 0x0000, /* R56 */ | ||
2447 | 0x0000, /* R57 */ | ||
2448 | 0x4000, /* R58 - DAC Mute */ | ||
2449 | 0x0000, /* R59 - DAC Mute Volume */ | ||
2450 | 0x0000, /* R60 - DAC Side */ | ||
2451 | 0x0000, /* R61 */ | ||
2452 | 0x0000, /* R62 */ | ||
2453 | 0x0000, /* R63 */ | ||
2454 | 0x8000, /* R64 - ADC Control */ | ||
2455 | 0x0000, /* R65 */ | ||
2456 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
2457 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
2458 | 0x0000, /* R68 - ADC Divider */ | ||
2459 | 0x0000, /* R69 */ | ||
2460 | 0x0040, /* R70 - ADC LR Rate */ | ||
2461 | 0x0000, /* R71 */ | ||
2462 | 0x0303, /* R72 - Input Control */ | ||
2463 | 0x0000, /* R73 - IN3 Input Control */ | ||
2464 | 0x0000, /* R74 - Mic Bias Control */ | ||
2465 | 0x0000, /* R75 */ | ||
2466 | 0x0000, /* R76 - Output Control */ | ||
2467 | 0x0000, /* R77 - Jack Detect */ | ||
2468 | 0x0000, /* R78 - Anti Pop Control */ | ||
2469 | 0x0000, /* R79 */ | ||
2470 | 0x0040, /* R80 - Left Input Volume */ | ||
2471 | 0x0040, /* R81 - Right Input Volume */ | ||
2472 | 0x0000, /* R82 */ | ||
2473 | 0x0000, /* R83 */ | ||
2474 | 0x0000, /* R84 */ | ||
2475 | 0x0000, /* R85 */ | ||
2476 | 0x0000, /* R86 */ | ||
2477 | 0x0000, /* R87 */ | ||
2478 | 0x0800, /* R88 - Left Mixer Control */ | ||
2479 | 0x1000, /* R89 - Right Mixer Control */ | ||
2480 | 0x0000, /* R90 */ | ||
2481 | 0x0000, /* R91 */ | ||
2482 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
2483 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
2484 | 0x0000, /* R94 */ | ||
2485 | 0x0000, /* R95 */ | ||
2486 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
2487 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
2488 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
2489 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
2490 | 0x0000, /* R100 - Input Mixer Volume */ | ||
2491 | 0x0000, /* R101 */ | ||
2492 | 0x0000, /* R102 */ | ||
2493 | 0x0000, /* R103 */ | ||
2494 | 0x00E4, /* R104 - OUT1L Volume */ | ||
2495 | 0x00E4, /* R105 - OUT1R Volume */ | ||
2496 | 0x00E4, /* R106 - OUT2L Volume */ | ||
2497 | 0x02E4, /* R107 - OUT2R Volume */ | ||
2498 | 0x0000, /* R108 */ | ||
2499 | 0x0000, /* R109 */ | ||
2500 | 0x0000, /* R110 */ | ||
2501 | 0x0000, /* R111 - BEEP Volume */ | ||
2502 | 0x0A00, /* R112 - AI Formating */ | ||
2503 | 0x0000, /* R113 - ADC DAC COMP */ | ||
2504 | 0x0020, /* R114 - AI ADC Control */ | ||
2505 | 0x0020, /* R115 - AI DAC Control */ | ||
2506 | 0x0000, /* R116 */ | ||
2507 | 0x0000, /* R117 */ | ||
2508 | 0x0000, /* R118 */ | ||
2509 | 0x0000, /* R119 */ | ||
2510 | 0x0000, /* R120 */ | ||
2511 | 0x0000, /* R121 */ | ||
2512 | 0x0000, /* R122 */ | ||
2513 | 0x0000, /* R123 */ | ||
2514 | 0x0000, /* R124 */ | ||
2515 | 0x0000, /* R125 */ | ||
2516 | 0x0000, /* R126 */ | ||
2517 | 0x0000, /* R127 */ | ||
2518 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
2519 | 0x0000, /* R129 - GPIO Pin pull up Control */ | ||
2520 | 0x0000, /* R130 - GPIO Pull down Control */ | ||
2521 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
2522 | 0x0000, /* R132 */ | ||
2523 | 0x0000, /* R133 - GPIO Control */ | ||
2524 | 0x0BFB, /* R134 - GPIO Configuration (i/o) */ | ||
2525 | 0x0FFF, /* R135 - GPIO Pin Polarity / Type */ | ||
2526 | 0x0000, /* R136 */ | ||
2527 | 0x0000, /* R137 */ | ||
2528 | 0x0000, /* R138 */ | ||
2529 | 0x0000, /* R139 */ | ||
2530 | 0x0300, /* R140 - GPIO Function Select 1 */ | ||
2531 | 0x0000, /* R141 - GPIO Function Select 2 */ | ||
2532 | 0x2300, /* R142 - GPIO Function Select 3 */ | ||
2533 | 0x0003, /* R143 - GPIO Function Select 4 */ | ||
2534 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
2535 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
2536 | 0x0000, /* R146 */ | ||
2537 | 0x0000, /* R147 */ | ||
2538 | 0x0000, /* R148 */ | ||
2539 | 0x0000, /* R149 */ | ||
2540 | 0x0000, /* R150 */ | ||
2541 | 0x0000, /* R151 */ | ||
2542 | 0x7000, /* R152 - AUX1 Readback */ | ||
2543 | 0x7000, /* R153 - AUX2 Readback */ | ||
2544 | 0x7000, /* R154 - AUX3 Readback */ | ||
2545 | 0x7000, /* R155 - AUX4 Readback */ | ||
2546 | 0x0000, /* R156 - USB Voltage Readback */ | ||
2547 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
2548 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
2549 | 0x0000, /* R159 - Chip Temp Readback */ | ||
2550 | 0x0000, /* R160 */ | ||
2551 | 0x0000, /* R161 */ | ||
2552 | 0x0000, /* R162 */ | ||
2553 | 0x0000, /* R163 - Generic Comparator Control */ | ||
2554 | 0x0000, /* R164 - Generic comparator 1 */ | ||
2555 | 0x0000, /* R165 - Generic comparator 2 */ | ||
2556 | 0x0000, /* R166 - Generic comparator 3 */ | ||
2557 | 0x0000, /* R167 - Generic comparator 4 */ | ||
2558 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
2559 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
2560 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
2561 | 0x0000, /* R171 */ | ||
2562 | 0x0000, /* R172 - Current Sink Driver A */ | ||
2563 | 0x0000, /* R173 - CSA Flash control */ | ||
2564 | 0x0000, /* R174 - Current Sink Driver B */ | ||
2565 | 0x0000, /* R175 - CSB Flash control */ | ||
2566 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
2567 | 0x032D, /* R177 - DCDC Active options */ | ||
2568 | 0x0000, /* R178 - DCDC Sleep options */ | ||
2569 | 0x0025, /* R179 - Power-check comparator */ | ||
2570 | 0x0062, /* R180 - DCDC1 Control */ | ||
2571 | 0x0400, /* R181 - DCDC1 Timeouts */ | ||
2572 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
2573 | 0x0018, /* R183 - DCDC2 Control */ | ||
2574 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
2575 | 0x0000, /* R185 */ | ||
2576 | 0x0006, /* R186 - DCDC3 Control */ | ||
2577 | 0x0800, /* R187 - DCDC3 Timeouts */ | ||
2578 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
2579 | 0x0006, /* R189 - DCDC4 Control */ | ||
2580 | 0x0C00, /* R190 - DCDC4 Timeouts */ | ||
2581 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
2582 | 0x0008, /* R192 - DCDC5 Control */ | ||
2583 | 0x0000, /* R193 - DCDC5 Timeouts */ | ||
2584 | 0x0000, /* R194 */ | ||
2585 | 0x0026, /* R195 - DCDC6 Control */ | ||
2586 | 0x1000, /* R196 - DCDC6 Timeouts */ | ||
2587 | 0x0006, /* R197 - DCDC6 Low Power */ | ||
2588 | 0x0000, /* R198 */ | ||
2589 | 0x0003, /* R199 - Limit Switch Control */ | ||
2590 | 0x0002, /* R200 - LDO1 Control */ | ||
2591 | 0x0000, /* R201 - LDO1 Timeouts */ | ||
2592 | 0x001C, /* R202 - LDO1 Low Power */ | ||
2593 | 0x001A, /* R203 - LDO2 Control */ | ||
2594 | 0x0000, /* R204 - LDO2 Timeouts */ | ||
2595 | 0x001C, /* R205 - LDO2 Low Power */ | ||
2596 | 0x001F, /* R206 - LDO3 Control */ | ||
2597 | 0x0000, /* R207 - LDO3 Timeouts */ | ||
2598 | 0x001C, /* R208 - LDO3 Low Power */ | ||
2599 | 0x001F, /* R209 - LDO4 Control */ | ||
2600 | 0x0000, /* R210 - LDO4 Timeouts */ | ||
2601 | 0x001C, /* R211 - LDO4 Low Power */ | ||
2602 | 0x0000, /* R212 */ | ||
2603 | 0x0000, /* R213 */ | ||
2604 | 0x0000, /* R214 */ | ||
2605 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
2606 | 0x001F, /* R216 - Main Bandgap Control */ | ||
2607 | 0x0000, /* R217 - OSC Control */ | ||
2608 | 0x9000, /* R218 - RTC Tick Control */ | ||
2609 | 0x0000, /* R219 - Security1 */ | ||
2610 | 0x4000, /* R220 */ | ||
2611 | 0x0000, /* R221 */ | ||
2612 | 0x0000, /* R222 */ | ||
2613 | 0x0000, /* R223 */ | ||
2614 | 0x0000, /* R224 - Signal overrides */ | ||
2615 | 0x0000, /* R225 - DCDC/LDO status */ | ||
2616 | 0x0000, /* R226 - Charger Overides/status */ | ||
2617 | 0x0000, /* R227 - misc overrides */ | ||
2618 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
2619 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
2620 | 0xE000, /* R230 - GPIO Pin Status */ | ||
2621 | 0x0000, /* R231 - comparotor overrides */ | ||
2622 | 0x0000, /* R232 */ | ||
2623 | 0x0000, /* R233 - State Machine status */ | ||
2624 | 0x1200, /* R234 */ | ||
2625 | 0x0000, /* R235 */ | ||
2626 | 0x8000, /* R236 */ | ||
2627 | 0x0000, /* R237 */ | ||
2628 | 0x0000, /* R238 */ | ||
2629 | 0x0000, /* R239 */ | ||
2630 | 0x0003, /* R240 */ | ||
2631 | 0x0000, /* R241 */ | ||
2632 | 0x0000, /* R242 */ | ||
2633 | 0x0004, /* R243 */ | ||
2634 | 0x0300, /* R244 */ | ||
2635 | 0x0000, /* R245 */ | ||
2636 | 0x0200, /* R246 */ | ||
2637 | 0x0000, /* R247 */ | ||
2638 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
2639 | 0x5000, /* R249 */ | ||
2640 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
2641 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
2642 | 0x5100, /* R252 */ | ||
2643 | 0x1000, /* R253 - DCDC6 Test Controls */ | ||
2644 | }; | ||
2645 | #endif | ||
2646 | |||
2647 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2 | ||
2648 | |||
2649 | #undef WM8350_HAVE_CONFIG_MODE | ||
2650 | #define WM8350_HAVE_CONFIG_MODE | ||
2651 | |||
2652 | const u16 wm8352_mode2_defaults[] = { | ||
2653 | 0x6143, /* R0 - Reset/ID */ | ||
2654 | 0x0000, /* R1 - ID */ | ||
2655 | 0x0002, /* R2 - Revision */ | ||
2656 | 0x1C02, /* R3 - System Control 1 */ | ||
2657 | 0x0204, /* R4 - System Control 2 */ | ||
2658 | 0x0000, /* R5 - System Hibernate */ | ||
2659 | 0x8A00, /* R6 - Interface Control */ | ||
2660 | 0x0000, /* R7 */ | ||
2661 | 0x8000, /* R8 - Power mgmt (1) */ | ||
2662 | 0x0000, /* R9 - Power mgmt (2) */ | ||
2663 | 0x0000, /* R10 - Power mgmt (3) */ | ||
2664 | 0x2000, /* R11 - Power mgmt (4) */ | ||
2665 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
2666 | 0x0000, /* R13 - Power mgmt (6) */ | ||
2667 | 0x0000, /* R14 - Power mgmt (7) */ | ||
2668 | 0x0000, /* R15 */ | ||
2669 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
2670 | 0x0100, /* R17 - RTC Hours/Day */ | ||
2671 | 0x0101, /* R18 - RTC Date/Month */ | ||
2672 | 0x1400, /* R19 - RTC Year */ | ||
2673 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
2674 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
2675 | 0x0000, /* R22 - Alarm Date/Month */ | ||
2676 | 0x0320, /* R23 - RTC Time Control */ | ||
2677 | 0x0000, /* R24 - System Interrupts */ | ||
2678 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
2679 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
2680 | 0x0000, /* R27 */ | ||
2681 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
2682 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
2683 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
2684 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
2685 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
2686 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
2687 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
2688 | 0x0000, /* R35 */ | ||
2689 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
2690 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
2691 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
2692 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
2693 | 0x0040, /* R40 - Clock Control 1 */ | ||
2694 | 0x0000, /* R41 - Clock Control 2 */ | ||
2695 | 0x3A00, /* R42 - FLL Control 1 */ | ||
2696 | 0x7086, /* R43 - FLL Control 2 */ | ||
2697 | 0xC226, /* R44 - FLL Control 3 */ | ||
2698 | 0x0000, /* R45 - FLL Control 4 */ | ||
2699 | 0x0000, /* R46 */ | ||
2700 | 0x0000, /* R47 */ | ||
2701 | 0x0000, /* R48 - DAC Control */ | ||
2702 | 0x0000, /* R49 */ | ||
2703 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
2704 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
2705 | 0x0000, /* R52 */ | ||
2706 | 0x0040, /* R53 - DAC LR Rate */ | ||
2707 | 0x0000, /* R54 - DAC Clock Control */ | ||
2708 | 0x0000, /* R55 */ | ||
2709 | 0x0000, /* R56 */ | ||
2710 | 0x0000, /* R57 */ | ||
2711 | 0x4000, /* R58 - DAC Mute */ | ||
2712 | 0x0000, /* R59 - DAC Mute Volume */ | ||
2713 | 0x0000, /* R60 - DAC Side */ | ||
2714 | 0x0000, /* R61 */ | ||
2715 | 0x0000, /* R62 */ | ||
2716 | 0x0000, /* R63 */ | ||
2717 | 0x8000, /* R64 - ADC Control */ | ||
2718 | 0x0000, /* R65 */ | ||
2719 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
2720 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
2721 | 0x0000, /* R68 - ADC Divider */ | ||
2722 | 0x0000, /* R69 */ | ||
2723 | 0x0040, /* R70 - ADC LR Rate */ | ||
2724 | 0x0000, /* R71 */ | ||
2725 | 0x0303, /* R72 - Input Control */ | ||
2726 | 0x0000, /* R73 - IN3 Input Control */ | ||
2727 | 0x0000, /* R74 - Mic Bias Control */ | ||
2728 | 0x0000, /* R75 */ | ||
2729 | 0x0000, /* R76 - Output Control */ | ||
2730 | 0x0000, /* R77 - Jack Detect */ | ||
2731 | 0x0000, /* R78 - Anti Pop Control */ | ||
2732 | 0x0000, /* R79 */ | ||
2733 | 0x0040, /* R80 - Left Input Volume */ | ||
2734 | 0x0040, /* R81 - Right Input Volume */ | ||
2735 | 0x0000, /* R82 */ | ||
2736 | 0x0000, /* R83 */ | ||
2737 | 0x0000, /* R84 */ | ||
2738 | 0x0000, /* R85 */ | ||
2739 | 0x0000, /* R86 */ | ||
2740 | 0x0000, /* R87 */ | ||
2741 | 0x0800, /* R88 - Left Mixer Control */ | ||
2742 | 0x1000, /* R89 - Right Mixer Control */ | ||
2743 | 0x0000, /* R90 */ | ||
2744 | 0x0000, /* R91 */ | ||
2745 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
2746 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
2747 | 0x0000, /* R94 */ | ||
2748 | 0x0000, /* R95 */ | ||
2749 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
2750 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
2751 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
2752 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
2753 | 0x0000, /* R100 - Input Mixer Volume */ | ||
2754 | 0x0000, /* R101 */ | ||
2755 | 0x0000, /* R102 */ | ||
2756 | 0x0000, /* R103 */ | ||
2757 | 0x00E4, /* R104 - OUT1L Volume */ | ||
2758 | 0x00E4, /* R105 - OUT1R Volume */ | ||
2759 | 0x00E4, /* R106 - OUT2L Volume */ | ||
2760 | 0x02E4, /* R107 - OUT2R Volume */ | ||
2761 | 0x0000, /* R108 */ | ||
2762 | 0x0000, /* R109 */ | ||
2763 | 0x0000, /* R110 */ | ||
2764 | 0x0000, /* R111 - BEEP Volume */ | ||
2765 | 0x0A00, /* R112 - AI Formating */ | ||
2766 | 0x0000, /* R113 - ADC DAC COMP */ | ||
2767 | 0x0020, /* R114 - AI ADC Control */ | ||
2768 | 0x0020, /* R115 - AI DAC Control */ | ||
2769 | 0x0000, /* R116 */ | ||
2770 | 0x0000, /* R117 */ | ||
2771 | 0x0000, /* R118 */ | ||
2772 | 0x0000, /* R119 */ | ||
2773 | 0x0000, /* R120 */ | ||
2774 | 0x0000, /* R121 */ | ||
2775 | 0x0000, /* R122 */ | ||
2776 | 0x0000, /* R123 */ | ||
2777 | 0x0000, /* R124 */ | ||
2778 | 0x0000, /* R125 */ | ||
2779 | 0x0000, /* R126 */ | ||
2780 | 0x0000, /* R127 */ | ||
2781 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
2782 | 0x0000, /* R129 - GPIO Pin pull up Control */ | ||
2783 | 0x0110, /* R130 - GPIO Pull down Control */ | ||
2784 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
2785 | 0x0000, /* R132 */ | ||
2786 | 0x0000, /* R133 - GPIO Control */ | ||
2787 | 0x09DA, /* R134 - GPIO Configuration (i/o) */ | ||
2788 | 0x0DD6, /* R135 - GPIO Pin Polarity / Type */ | ||
2789 | 0x0000, /* R136 */ | ||
2790 | 0x0000, /* R137 */ | ||
2791 | 0x0000, /* R138 */ | ||
2792 | 0x0000, /* R139 */ | ||
2793 | 0x1310, /* R140 - GPIO Function Select 1 */ | ||
2794 | 0x0033, /* R141 - GPIO Function Select 2 */ | ||
2795 | 0x2000, /* R142 - GPIO Function Select 3 */ | ||
2796 | 0x0000, /* R143 - GPIO Function Select 4 */ | ||
2797 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
2798 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
2799 | 0x0000, /* R146 */ | ||
2800 | 0x0000, /* R147 */ | ||
2801 | 0x0000, /* R148 */ | ||
2802 | 0x0000, /* R149 */ | ||
2803 | 0x0000, /* R150 */ | ||
2804 | 0x0000, /* R151 */ | ||
2805 | 0x7000, /* R152 - AUX1 Readback */ | ||
2806 | 0x7000, /* R153 - AUX2 Readback */ | ||
2807 | 0x7000, /* R154 - AUX3 Readback */ | ||
2808 | 0x7000, /* R155 - AUX4 Readback */ | ||
2809 | 0x0000, /* R156 - USB Voltage Readback */ | ||
2810 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
2811 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
2812 | 0x0000, /* R159 - Chip Temp Readback */ | ||
2813 | 0x0000, /* R160 */ | ||
2814 | 0x0000, /* R161 */ | ||
2815 | 0x0000, /* R162 */ | ||
2816 | 0x0000, /* R163 - Generic Comparator Control */ | ||
2817 | 0x0000, /* R164 - Generic comparator 1 */ | ||
2818 | 0x0000, /* R165 - Generic comparator 2 */ | ||
2819 | 0x0000, /* R166 - Generic comparator 3 */ | ||
2820 | 0x0000, /* R167 - Generic comparator 4 */ | ||
2821 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
2822 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
2823 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
2824 | 0x0000, /* R171 */ | ||
2825 | 0x0000, /* R172 - Current Sink Driver A */ | ||
2826 | 0x0000, /* R173 - CSA Flash control */ | ||
2827 | 0x0000, /* R174 - Current Sink Driver B */ | ||
2828 | 0x0000, /* R175 - CSB Flash control */ | ||
2829 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
2830 | 0x032D, /* R177 - DCDC Active options */ | ||
2831 | 0x0000, /* R178 - DCDC Sleep options */ | ||
2832 | 0x0025, /* R179 - Power-check comparator */ | ||
2833 | 0x000E, /* R180 - DCDC1 Control */ | ||
2834 | 0x0800, /* R181 - DCDC1 Timeouts */ | ||
2835 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
2836 | 0x0018, /* R183 - DCDC2 Control */ | ||
2837 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
2838 | 0x0000, /* R185 */ | ||
2839 | 0x0056, /* R186 - DCDC3 Control */ | ||
2840 | 0x1800, /* R187 - DCDC3 Timeouts */ | ||
2841 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
2842 | 0x000E, /* R189 - DCDC4 Control */ | ||
2843 | 0x1000, /* R190 - DCDC4 Timeouts */ | ||
2844 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
2845 | 0x0008, /* R192 - DCDC5 Control */ | ||
2846 | 0x0000, /* R193 - DCDC5 Timeouts */ | ||
2847 | 0x0000, /* R194 */ | ||
2848 | 0x0026, /* R195 - DCDC6 Control */ | ||
2849 | 0x0C00, /* R196 - DCDC6 Timeouts */ | ||
2850 | 0x0006, /* R197 - DCDC6 Low Power */ | ||
2851 | 0x0000, /* R198 */ | ||
2852 | 0x0003, /* R199 - Limit Switch Control */ | ||
2853 | 0x001C, /* R200 - LDO1 Control */ | ||
2854 | 0x0000, /* R201 - LDO1 Timeouts */ | ||
2855 | 0x001C, /* R202 - LDO1 Low Power */ | ||
2856 | 0x0006, /* R203 - LDO2 Control */ | ||
2857 | 0x0400, /* R204 - LDO2 Timeouts */ | ||
2858 | 0x001C, /* R205 - LDO2 Low Power */ | ||
2859 | 0x001C, /* R206 - LDO3 Control */ | ||
2860 | 0x1400, /* R207 - LDO3 Timeouts */ | ||
2861 | 0x001C, /* R208 - LDO3 Low Power */ | ||
2862 | 0x001A, /* R209 - LDO4 Control */ | ||
2863 | 0x0000, /* R210 - LDO4 Timeouts */ | ||
2864 | 0x001C, /* R211 - LDO4 Low Power */ | ||
2865 | 0x0000, /* R212 */ | ||
2866 | 0x0000, /* R213 */ | ||
2867 | 0x0000, /* R214 */ | ||
2868 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
2869 | 0x001F, /* R216 - Main Bandgap Control */ | ||
2870 | 0x0000, /* R217 - OSC Control */ | ||
2871 | 0x9000, /* R218 - RTC Tick Control */ | ||
2872 | 0x0000, /* R219 - Security1 */ | ||
2873 | 0x4000, /* R220 */ | ||
2874 | 0x0000, /* R221 */ | ||
2875 | 0x0000, /* R222 */ | ||
2876 | 0x0000, /* R223 */ | ||
2877 | 0x0000, /* R224 - Signal overrides */ | ||
2878 | 0x0000, /* R225 - DCDC/LDO status */ | ||
2879 | 0x0000, /* R226 - Charger Overides/status */ | ||
2880 | 0x0000, /* R227 - misc overrides */ | ||
2881 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
2882 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
2883 | 0xE000, /* R230 - GPIO Pin Status */ | ||
2884 | 0x0000, /* R231 - comparotor overrides */ | ||
2885 | 0x0000, /* R232 */ | ||
2886 | 0x0000, /* R233 - State Machine status */ | ||
2887 | 0x1200, /* R234 */ | ||
2888 | 0x0000, /* R235 */ | ||
2889 | 0x8000, /* R236 */ | ||
2890 | 0x0000, /* R237 */ | ||
2891 | 0x0000, /* R238 */ | ||
2892 | 0x0000, /* R239 */ | ||
2893 | 0x0003, /* R240 */ | ||
2894 | 0x0000, /* R241 */ | ||
2895 | 0x0000, /* R242 */ | ||
2896 | 0x0004, /* R243 */ | ||
2897 | 0x0300, /* R244 */ | ||
2898 | 0x0000, /* R245 */ | ||
2899 | 0x0200, /* R246 */ | ||
2900 | 0x0000, /* R247 */ | ||
2901 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
2902 | 0x5000, /* R249 */ | ||
2903 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
2904 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
2905 | 0x5100, /* R252 */ | ||
2906 | 0x1000, /* R253 - DCDC6 Test Controls */ | ||
2907 | }; | ||
2908 | #endif | ||
2909 | |||
2910 | #ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3 | ||
2911 | |||
2912 | #undef WM8350_HAVE_CONFIG_MODE | ||
2913 | #define WM8350_HAVE_CONFIG_MODE | ||
2914 | |||
2915 | const u16 wm8352_mode3_defaults[] = { | ||
2916 | 0x6143, /* R0 - Reset/ID */ | ||
2917 | 0x0000, /* R1 - ID */ | ||
2918 | 0x0002, /* R2 - Revision */ | ||
2919 | 0x1C02, /* R3 - System Control 1 */ | ||
2920 | 0x0204, /* R4 - System Control 2 */ | ||
2921 | 0x0000, /* R5 - System Hibernate */ | ||
2922 | 0x8A00, /* R6 - Interface Control */ | ||
2923 | 0x0000, /* R7 */ | ||
2924 | 0x8000, /* R8 - Power mgmt (1) */ | ||
2925 | 0x0000, /* R9 - Power mgmt (2) */ | ||
2926 | 0x0000, /* R10 - Power mgmt (3) */ | ||
2927 | 0x2000, /* R11 - Power mgmt (4) */ | ||
2928 | 0x0E00, /* R12 - Power mgmt (5) */ | ||
2929 | 0x0000, /* R13 - Power mgmt (6) */ | ||
2930 | 0x0000, /* R14 - Power mgmt (7) */ | ||
2931 | 0x0000, /* R15 */ | ||
2932 | 0x0000, /* R16 - RTC Seconds/Minutes */ | ||
2933 | 0x0100, /* R17 - RTC Hours/Day */ | ||
2934 | 0x0101, /* R18 - RTC Date/Month */ | ||
2935 | 0x1400, /* R19 - RTC Year */ | ||
2936 | 0x0000, /* R20 - Alarm Seconds/Minutes */ | ||
2937 | 0x0000, /* R21 - Alarm Hours/Day */ | ||
2938 | 0x0000, /* R22 - Alarm Date/Month */ | ||
2939 | 0x0320, /* R23 - RTC Time Control */ | ||
2940 | 0x0000, /* R24 - System Interrupts */ | ||
2941 | 0x0000, /* R25 - Interrupt Status 1 */ | ||
2942 | 0x0000, /* R26 - Interrupt Status 2 */ | ||
2943 | 0x0000, /* R27 */ | ||
2944 | 0x0000, /* R28 - Under Voltage Interrupt status */ | ||
2945 | 0x0000, /* R29 - Over Current Interrupt status */ | ||
2946 | 0x0000, /* R30 - GPIO Interrupt Status */ | ||
2947 | 0x0000, /* R31 - Comparator Interrupt Status */ | ||
2948 | 0x3FFF, /* R32 - System Interrupts Mask */ | ||
2949 | 0x0000, /* R33 - Interrupt Status 1 Mask */ | ||
2950 | 0x0000, /* R34 - Interrupt Status 2 Mask */ | ||
2951 | 0x0000, /* R35 */ | ||
2952 | 0x0000, /* R36 - Under Voltage Interrupt status Mask */ | ||
2953 | 0x0000, /* R37 - Over Current Interrupt status Mask */ | ||
2954 | 0x0000, /* R38 - GPIO Interrupt Status Mask */ | ||
2955 | 0x0000, /* R39 - Comparator Interrupt Status Mask */ | ||
2956 | 0x0040, /* R40 - Clock Control 1 */ | ||
2957 | 0x0000, /* R41 - Clock Control 2 */ | ||
2958 | 0x3A00, /* R42 - FLL Control 1 */ | ||
2959 | 0x7086, /* R43 - FLL Control 2 */ | ||
2960 | 0xC226, /* R44 - FLL Control 3 */ | ||
2961 | 0x0000, /* R45 - FLL Control 4 */ | ||
2962 | 0x0000, /* R46 */ | ||
2963 | 0x0000, /* R47 */ | ||
2964 | 0x0000, /* R48 - DAC Control */ | ||
2965 | 0x0000, /* R49 */ | ||
2966 | 0x00C0, /* R50 - DAC Digital Volume L */ | ||
2967 | 0x00C0, /* R51 - DAC Digital Volume R */ | ||
2968 | 0x0000, /* R52 */ | ||
2969 | 0x0040, /* R53 - DAC LR Rate */ | ||
2970 | 0x0000, /* R54 - DAC Clock Control */ | ||
2971 | 0x0000, /* R55 */ | ||
2972 | 0x0000, /* R56 */ | ||
2973 | 0x0000, /* R57 */ | ||
2974 | 0x4000, /* R58 - DAC Mute */ | ||
2975 | 0x0000, /* R59 - DAC Mute Volume */ | ||
2976 | 0x0000, /* R60 - DAC Side */ | ||
2977 | 0x0000, /* R61 */ | ||
2978 | 0x0000, /* R62 */ | ||
2979 | 0x0000, /* R63 */ | ||
2980 | 0x8000, /* R64 - ADC Control */ | ||
2981 | 0x0000, /* R65 */ | ||
2982 | 0x00C0, /* R66 - ADC Digital Volume L */ | ||
2983 | 0x00C0, /* R67 - ADC Digital Volume R */ | ||
2984 | 0x0000, /* R68 - ADC Divider */ | ||
2985 | 0x0000, /* R69 */ | ||
2986 | 0x0040, /* R70 - ADC LR Rate */ | ||
2987 | 0x0000, /* R71 */ | ||
2988 | 0x0303, /* R72 - Input Control */ | ||
2989 | 0x0000, /* R73 - IN3 Input Control */ | ||
2990 | 0x0000, /* R74 - Mic Bias Control */ | ||
2991 | 0x0000, /* R75 */ | ||
2992 | 0x0000, /* R76 - Output Control */ | ||
2993 | 0x0000, /* R77 - Jack Detect */ | ||
2994 | 0x0000, /* R78 - Anti Pop Control */ | ||
2995 | 0x0000, /* R79 */ | ||
2996 | 0x0040, /* R80 - Left Input Volume */ | ||
2997 | 0x0040, /* R81 - Right Input Volume */ | ||
2998 | 0x0000, /* R82 */ | ||
2999 | 0x0000, /* R83 */ | ||
3000 | 0x0000, /* R84 */ | ||
3001 | 0x0000, /* R85 */ | ||
3002 | 0x0000, /* R86 */ | ||
3003 | 0x0000, /* R87 */ | ||
3004 | 0x0800, /* R88 - Left Mixer Control */ | ||
3005 | 0x1000, /* R89 - Right Mixer Control */ | ||
3006 | 0x0000, /* R90 */ | ||
3007 | 0x0000, /* R91 */ | ||
3008 | 0x0000, /* R92 - OUT3 Mixer Control */ | ||
3009 | 0x0000, /* R93 - OUT4 Mixer Control */ | ||
3010 | 0x0000, /* R94 */ | ||
3011 | 0x0000, /* R95 */ | ||
3012 | 0x0000, /* R96 - Output Left Mixer Volume */ | ||
3013 | 0x0000, /* R97 - Output Right Mixer Volume */ | ||
3014 | 0x0000, /* R98 - Input Mixer Volume L */ | ||
3015 | 0x0000, /* R99 - Input Mixer Volume R */ | ||
3016 | 0x0000, /* R100 - Input Mixer Volume */ | ||
3017 | 0x0000, /* R101 */ | ||
3018 | 0x0000, /* R102 */ | ||
3019 | 0x0000, /* R103 */ | ||
3020 | 0x00E4, /* R104 - OUT1L Volume */ | ||
3021 | 0x00E4, /* R105 - OUT1R Volume */ | ||
3022 | 0x00E4, /* R106 - OUT2L Volume */ | ||
3023 | 0x02E4, /* R107 - OUT2R Volume */ | ||
3024 | 0x0000, /* R108 */ | ||
3025 | 0x0000, /* R109 */ | ||
3026 | 0x0000, /* R110 */ | ||
3027 | 0x0000, /* R111 - BEEP Volume */ | ||
3028 | 0x0A00, /* R112 - AI Formating */ | ||
3029 | 0x0000, /* R113 - ADC DAC COMP */ | ||
3030 | 0x0020, /* R114 - AI ADC Control */ | ||
3031 | 0x0020, /* R115 - AI DAC Control */ | ||
3032 | 0x0000, /* R116 */ | ||
3033 | 0x0000, /* R117 */ | ||
3034 | 0x0000, /* R118 */ | ||
3035 | 0x0000, /* R119 */ | ||
3036 | 0x0000, /* R120 */ | ||
3037 | 0x0000, /* R121 */ | ||
3038 | 0x0000, /* R122 */ | ||
3039 | 0x0000, /* R123 */ | ||
3040 | 0x0000, /* R124 */ | ||
3041 | 0x0000, /* R125 */ | ||
3042 | 0x0000, /* R126 */ | ||
3043 | 0x0000, /* R127 */ | ||
3044 | 0x1FFF, /* R128 - GPIO Debounce */ | ||
3045 | 0x0010, /* R129 - GPIO Pin pull up Control */ | ||
3046 | 0x0000, /* R130 - GPIO Pull down Control */ | ||
3047 | 0x0000, /* R131 - GPIO Interrupt Mode */ | ||
3048 | 0x0000, /* R132 */ | ||
3049 | 0x0000, /* R133 - GPIO Control */ | ||
3050 | 0x0BFB, /* R134 - GPIO Configuration (i/o) */ | ||
3051 | 0x0FFD, /* R135 - GPIO Pin Polarity / Type */ | ||
3052 | 0x0000, /* R136 */ | ||
3053 | 0x0000, /* R137 */ | ||
3054 | 0x0000, /* R138 */ | ||
3055 | 0x0000, /* R139 */ | ||
3056 | 0x0310, /* R140 - GPIO Function Select 1 */ | ||
3057 | 0x0001, /* R141 - GPIO Function Select 2 */ | ||
3058 | 0x2300, /* R142 - GPIO Function Select 3 */ | ||
3059 | 0x0003, /* R143 - GPIO Function Select 4 */ | ||
3060 | 0x0000, /* R144 - Digitiser Control (1) */ | ||
3061 | 0x0002, /* R145 - Digitiser Control (2) */ | ||
3062 | 0x0000, /* R146 */ | ||
3063 | 0x0000, /* R147 */ | ||
3064 | 0x0000, /* R148 */ | ||
3065 | 0x0000, /* R149 */ | ||
3066 | 0x0000, /* R150 */ | ||
3067 | 0x0000, /* R151 */ | ||
3068 | 0x7000, /* R152 - AUX1 Readback */ | ||
3069 | 0x7000, /* R153 - AUX2 Readback */ | ||
3070 | 0x7000, /* R154 - AUX3 Readback */ | ||
3071 | 0x7000, /* R155 - AUX4 Readback */ | ||
3072 | 0x0000, /* R156 - USB Voltage Readback */ | ||
3073 | 0x0000, /* R157 - LINE Voltage Readback */ | ||
3074 | 0x0000, /* R158 - BATT Voltage Readback */ | ||
3075 | 0x0000, /* R159 - Chip Temp Readback */ | ||
3076 | 0x0000, /* R160 */ | ||
3077 | 0x0000, /* R161 */ | ||
3078 | 0x0000, /* R162 */ | ||
3079 | 0x0000, /* R163 - Generic Comparator Control */ | ||
3080 | 0x0000, /* R164 - Generic comparator 1 */ | ||
3081 | 0x0000, /* R165 - Generic comparator 2 */ | ||
3082 | 0x0000, /* R166 - Generic comparator 3 */ | ||
3083 | 0x0000, /* R167 - Generic comparator 4 */ | ||
3084 | 0xA00F, /* R168 - Battery Charger Control 1 */ | ||
3085 | 0x0B06, /* R169 - Battery Charger Control 2 */ | ||
3086 | 0x0000, /* R170 - Battery Charger Control 3 */ | ||
3087 | 0x0000, /* R171 */ | ||
3088 | 0x0000, /* R172 - Current Sink Driver A */ | ||
3089 | 0x0000, /* R173 - CSA Flash control */ | ||
3090 | 0x0000, /* R174 - Current Sink Driver B */ | ||
3091 | 0x0000, /* R175 - CSB Flash control */ | ||
3092 | 0x0000, /* R176 - DCDC/LDO requested */ | ||
3093 | 0x032D, /* R177 - DCDC Active options */ | ||
3094 | 0x0000, /* R178 - DCDC Sleep options */ | ||
3095 | 0x0025, /* R179 - Power-check comparator */ | ||
3096 | 0x0006, /* R180 - DCDC1 Control */ | ||
3097 | 0x0400, /* R181 - DCDC1 Timeouts */ | ||
3098 | 0x1006, /* R182 - DCDC1 Low Power */ | ||
3099 | 0x0018, /* R183 - DCDC2 Control */ | ||
3100 | 0x0000, /* R184 - DCDC2 Timeouts */ | ||
3101 | 0x0000, /* R185 */ | ||
3102 | 0x0050, /* R186 - DCDC3 Control */ | ||
3103 | 0x0C00, /* R187 - DCDC3 Timeouts */ | ||
3104 | 0x0006, /* R188 - DCDC3 Low Power */ | ||
3105 | 0x000E, /* R189 - DCDC4 Control */ | ||
3106 | 0x0400, /* R190 - DCDC4 Timeouts */ | ||
3107 | 0x0006, /* R191 - DCDC4 Low Power */ | ||
3108 | 0x0008, /* R192 - DCDC5 Control */ | ||
3109 | 0x0000, /* R193 - DCDC5 Timeouts */ | ||
3110 | 0x0000, /* R194 */ | ||
3111 | 0x0029, /* R195 - DCDC6 Control */ | ||
3112 | 0x0800, /* R196 - DCDC6 Timeouts */ | ||
3113 | 0x0006, /* R197 - DCDC6 Low Power */ | ||
3114 | 0x0000, /* R198 */ | ||
3115 | 0x0003, /* R199 - Limit Switch Control */ | ||
3116 | 0x001D, /* R200 - LDO1 Control */ | ||
3117 | 0x1000, /* R201 - LDO1 Timeouts */ | ||
3118 | 0x001C, /* R202 - LDO1 Low Power */ | ||
3119 | 0x0017, /* R203 - LDO2 Control */ | ||
3120 | 0x1000, /* R204 - LDO2 Timeouts */ | ||
3121 | 0x001C, /* R205 - LDO2 Low Power */ | ||
3122 | 0x0006, /* R206 - LDO3 Control */ | ||
3123 | 0x1000, /* R207 - LDO3 Timeouts */ | ||
3124 | 0x001C, /* R208 - LDO3 Low Power */ | ||
3125 | 0x0010, /* R209 - LDO4 Control */ | ||
3126 | 0x1000, /* R210 - LDO4 Timeouts */ | ||
3127 | 0x001C, /* R211 - LDO4 Low Power */ | ||
3128 | 0x0000, /* R212 */ | ||
3129 | 0x0000, /* R213 */ | ||
3130 | 0x0000, /* R214 */ | ||
3131 | 0x0000, /* R215 - VCC_FAULT Masks */ | ||
3132 | 0x001F, /* R216 - Main Bandgap Control */ | ||
3133 | 0x0000, /* R217 - OSC Control */ | ||
3134 | 0x9000, /* R218 - RTC Tick Control */ | ||
3135 | 0x0000, /* R219 - Security1 */ | ||
3136 | 0x4000, /* R220 */ | ||
3137 | 0x0000, /* R221 */ | ||
3138 | 0x0000, /* R222 */ | ||
3139 | 0x0000, /* R223 */ | ||
3140 | 0x0000, /* R224 - Signal overrides */ | ||
3141 | 0x0000, /* R225 - DCDC/LDO status */ | ||
3142 | 0x0000, /* R226 - Charger Overides/status */ | ||
3143 | 0x0000, /* R227 - misc overrides */ | ||
3144 | 0x0000, /* R228 - Supply overrides/status 1 */ | ||
3145 | 0x0000, /* R229 - Supply overrides/status 2 */ | ||
3146 | 0xE000, /* R230 - GPIO Pin Status */ | ||
3147 | 0x0000, /* R231 - comparotor overrides */ | ||
3148 | 0x0000, /* R232 */ | ||
3149 | 0x0000, /* R233 - State Machine status */ | ||
3150 | 0x1200, /* R234 */ | ||
3151 | 0x0000, /* R235 */ | ||
3152 | 0x8000, /* R236 */ | ||
3153 | 0x0000, /* R237 */ | ||
3154 | 0x0000, /* R238 */ | ||
3155 | 0x0000, /* R239 */ | ||
3156 | 0x0003, /* R240 */ | ||
3157 | 0x0000, /* R241 */ | ||
3158 | 0x0000, /* R242 */ | ||
3159 | 0x0004, /* R243 */ | ||
3160 | 0x0300, /* R244 */ | ||
3161 | 0x0000, /* R245 */ | ||
3162 | 0x0200, /* R246 */ | ||
3163 | 0x0000, /* R247 */ | ||
3164 | 0x1000, /* R248 - DCDC1 Test Controls */ | ||
3165 | 0x5000, /* R249 */ | ||
3166 | 0x1000, /* R250 - DCDC3 Test Controls */ | ||
3167 | 0x1000, /* R251 - DCDC4 Test Controls */ | ||
3168 | 0x5100, /* R252 */ | ||
3169 | 0x1000, /* R253 - DCDC6 Test Controls */ | ||
3170 | }; | ||
3171 | #endif | ||
3172 | |||
1077 | /* The register defaults for the config mode used must be compiled in but | 3173 | /* The register defaults for the config mode used must be compiled in but |
1078 | * due to the impact on kernel size it is possible to disable | 3174 | * due to the impact on kernel size it is possible to disable |
1079 | */ | 3175 | */ |
@@ -1307,14 +3403,14 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = { | |||
1307 | { 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */ | 3403 | { 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */ |
1308 | { 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */ | 3404 | { 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */ |
1309 | { 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */ | 3405 | { 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */ |
1310 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R219 */ | 3406 | { 0xFFFF, 0xFFFF, 0x0000 }, /* R219 - Security */ |
1311 | { 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */ | 3407 | { 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */ |
1312 | { 0x0000, 0x0000, 0x0000 }, /* R221 */ | 3408 | { 0x0000, 0x0000, 0x0000 }, /* R221 */ |
1313 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */ | 3409 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */ |
1314 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */ | 3410 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */ |
1315 | { 0x0000, 0x0000, 0x0000 }, /* R224 */ | 3411 | { 0x0000, 0x0000, 0x0000 }, /* R224 */ |
1316 | { 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */ | 3412 | { 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */ |
1317 | { 0x0000, 0x0000, 0x0000 }, /* R226 */ | 3413 | { 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */ |
1318 | { 0x0000, 0x0000, 0xFFFF }, /* R227 */ | 3414 | { 0x0000, 0x0000, 0xFFFF }, /* R227 */ |
1319 | { 0x0000, 0x0000, 0x0000 }, /* R228 */ | 3415 | { 0x0000, 0x0000, 0x0000 }, /* R228 */ |
1320 | { 0x0000, 0x0000, 0x0000 }, /* R229 */ | 3416 | { 0x0000, 0x0000, 0x0000 }, /* R229 */ |
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 6a0cedb5bb8a..cf30d06a0104 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/bug.h> | 15 | #include <linux/bug.h> |
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/mfd/core.h> | ||
18 | #include <linux/mfd/wm8400-private.h> | 19 | #include <linux/mfd/wm8400-private.h> |
19 | #include <linux/mfd/wm8400-audio.h> | 20 | #include <linux/mfd/wm8400-audio.h> |
20 | 21 | ||
@@ -239,6 +240,16 @@ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400) | |||
239 | } | 240 | } |
240 | EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache); | 241 | EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache); |
241 | 242 | ||
243 | static int wm8400_register_codec(struct wm8400 *wm8400) | ||
244 | { | ||
245 | struct mfd_cell cell = { | ||
246 | .name = "wm8400-codec", | ||
247 | .driver_data = wm8400, | ||
248 | }; | ||
249 | |||
250 | return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0); | ||
251 | } | ||
252 | |||
242 | /* | 253 | /* |
243 | * wm8400_init - Generic initialisation | 254 | * wm8400_init - Generic initialisation |
244 | * | 255 | * |
@@ -296,24 +307,32 @@ static int wm8400_init(struct wm8400 *wm8400, | |||
296 | reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT; | 307 | reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT; |
297 | dev_info(wm8400->dev, "WM8400 revision %x\n", reg); | 308 | dev_info(wm8400->dev, "WM8400 revision %x\n", reg); |
298 | 309 | ||
310 | ret = wm8400_register_codec(wm8400); | ||
311 | if (ret != 0) { | ||
312 | dev_err(wm8400->dev, "Failed to register codec\n"); | ||
313 | goto err_children; | ||
314 | } | ||
315 | |||
299 | if (pdata && pdata->platform_init) { | 316 | if (pdata && pdata->platform_init) { |
300 | ret = pdata->platform_init(wm8400->dev); | 317 | ret = pdata->platform_init(wm8400->dev); |
301 | if (ret != 0) | 318 | if (ret != 0) { |
302 | dev_err(wm8400->dev, "Platform init failed: %d\n", | 319 | dev_err(wm8400->dev, "Platform init failed: %d\n", |
303 | ret); | 320 | ret); |
321 | goto err_children; | ||
322 | } | ||
304 | } else | 323 | } else |
305 | dev_warn(wm8400->dev, "No platform initialisation supplied\n"); | 324 | dev_warn(wm8400->dev, "No platform initialisation supplied\n"); |
306 | 325 | ||
326 | return 0; | ||
327 | |||
328 | err_children: | ||
329 | mfd_remove_devices(wm8400->dev); | ||
307 | return ret; | 330 | return ret; |
308 | } | 331 | } |
309 | 332 | ||
310 | static void wm8400_release(struct wm8400 *wm8400) | 333 | static void wm8400_release(struct wm8400 *wm8400) |
311 | { | 334 | { |
312 | int i; | 335 | mfd_remove_devices(wm8400->dev); |
313 | |||
314 | for (i = 0; i < ARRAY_SIZE(wm8400->regulators); i++) | ||
315 | if (wm8400->regulators[i].name) | ||
316 | platform_device_unregister(&wm8400->regulators[i]); | ||
317 | } | 336 | } |
318 | 337 | ||
319 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 338 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 22a7e8ba211d..de966a6fb7e6 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c | |||
@@ -146,8 +146,6 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode) | |||
146 | 146 | ||
147 | if (ret) { | 147 | if (ret) { |
148 | ret->i_mode = mode; | 148 | ret->i_mode = mode; |
149 | ret->i_uid = ret->i_gid = 0; | ||
150 | ret->i_blocks = 0; | ||
151 | ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; | 149 | ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; |
152 | } | 150 | } |
153 | return ret; | 151 | return ret; |
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 517fce48d94a..5b396ff6c83f 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/mm.h> | 66 | #include <linux/mm.h> |
67 | #include <linux/highmem.h> | 67 | #include <linux/highmem.h> |
68 | #include <linux/sockios.h> | 68 | #include <linux/sockios.h> |
69 | #include <linux/firmware.h> | ||
69 | 70 | ||
70 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 71 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
71 | #include <linux/if_vlan.h> | 72 | #include <linux/if_vlan.h> |
@@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); | |||
186 | #define MAX_RODATA_LEN 8*1024 | 187 | #define MAX_RODATA_LEN 8*1024 |
187 | #define MAX_DATA_LEN 2*1024 | 188 | #define MAX_DATA_LEN 2*1024 |
188 | 189 | ||
189 | #include "acenic_firmware.h" | ||
190 | |||
191 | #ifndef tigon2FwReleaseLocal | 190 | #ifndef tigon2FwReleaseLocal |
192 | #define tigon2FwReleaseLocal 0 | 191 | #define tigon2FwReleaseLocal 0 |
193 | #endif | 192 | #endif |
@@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; | |||
417 | MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>"); | 416 | MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>"); |
418 | MODULE_LICENSE("GPL"); | 417 | MODULE_LICENSE("GPL"); |
419 | MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); | 418 | MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); |
419 | #ifndef CONFIG_ACENIC_OMIT_TIGON_I | ||
420 | MODULE_FIRMWARE("acenic/tg1.bin"); | ||
421 | #endif | ||
422 | MODULE_FIRMWARE("acenic/tg2.bin"); | ||
420 | 423 | ||
421 | module_param_array_named(link, link_state, int, NULL, 0); | 424 | module_param_array_named(link, link_state, int, NULL, 0); |
422 | module_param_array(trace, int, NULL, 0); | 425 | module_param_array(trace, int, NULL, 0); |
@@ -943,8 +946,8 @@ static int __devinit ace_init(struct net_device *dev) | |||
943 | case 4: | 946 | case 4: |
944 | case 5: | 947 | case 5: |
945 | printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", | 948 | printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", |
946 | tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor, | 949 | tig_ver, ap->firmware_major, ap->firmware_minor, |
947 | tigonFwReleaseFix); | 950 | ap->firmware_fix); |
948 | writel(0, ®s->LocalCtrl); | 951 | writel(0, ®s->LocalCtrl); |
949 | ap->version = 1; | 952 | ap->version = 1; |
950 | ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; | 953 | ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; |
@@ -952,8 +955,8 @@ static int __devinit ace_init(struct net_device *dev) | |||
952 | #endif | 955 | #endif |
953 | case 6: | 956 | case 6: |
954 | printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", | 957 | printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", |
955 | tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor, | 958 | tig_ver, ap->firmware_major, ap->firmware_minor, |
956 | tigon2FwReleaseFix); | 959 | ap->firmware_fix); |
957 | writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); | 960 | writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); |
958 | readl(®s->CpuBCtrl); /* PCI write posting */ | 961 | readl(®s->CpuBCtrl); /* PCI write posting */ |
959 | /* | 962 | /* |
@@ -1205,7 +1208,9 @@ static int __devinit ace_init(struct net_device *dev) | |||
1205 | memset(ap->info, 0, sizeof(struct ace_info)); | 1208 | memset(ap->info, 0, sizeof(struct ace_info)); |
1206 | memset(ap->skb, 0, sizeof(struct ace_skb)); | 1209 | memset(ap->skb, 0, sizeof(struct ace_skb)); |
1207 | 1210 | ||
1208 | ace_load_firmware(dev); | 1211 | if (ace_load_firmware(dev)) |
1212 | goto init_error; | ||
1213 | |||
1209 | ap->fw_running = 0; | 1214 | ap->fw_running = 0; |
1210 | 1215 | ||
1211 | tmp_ptr = ap->info_dma; | 1216 | tmp_ptr = ap->info_dma; |
@@ -1441,10 +1446,7 @@ static int __devinit ace_init(struct net_device *dev) | |||
1441 | if (ap->version >= 2) | 1446 | if (ap->version >= 2) |
1442 | writel(tmp, ®s->TuneFastLink); | 1447 | writel(tmp, ®s->TuneFastLink); |
1443 | 1448 | ||
1444 | if (ACE_IS_TIGON_I(ap)) | 1449 | writel(ap->firmware_start, ®s->Pc); |
1445 | writel(tigonFwStartAddr, ®s->Pc); | ||
1446 | if (ap->version == 2) | ||
1447 | writel(tigon2FwStartAddr, ®s->Pc); | ||
1448 | 1450 | ||
1449 | writel(0, ®s->Mb0Lo); | 1451 | writel(0, ®s->Mb0Lo); |
1450 | 1452 | ||
@@ -2761,8 +2763,8 @@ static void ace_get_drvinfo(struct net_device *dev, | |||
2761 | 2763 | ||
2762 | strlcpy(info->driver, "acenic", sizeof(info->driver)); | 2764 | strlcpy(info->driver, "acenic", sizeof(info->driver)); |
2763 | snprintf(info->version, sizeof(info->version), "%i.%i.%i", | 2765 | snprintf(info->version, sizeof(info->version), "%i.%i.%i", |
2764 | tigonFwReleaseMajor, tigonFwReleaseMinor, | 2766 | ap->firmware_major, ap->firmware_minor, |
2765 | tigonFwReleaseFix); | 2767 | ap->firmware_fix); |
2766 | 2768 | ||
2767 | if (ap->pdev) | 2769 | if (ap->pdev) |
2768 | strlcpy(info->bus_info, pci_name(ap->pdev), | 2770 | strlcpy(info->bus_info, pci_name(ap->pdev), |
@@ -2869,11 +2871,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev) | |||
2869 | } | 2871 | } |
2870 | 2872 | ||
2871 | 2873 | ||
2872 | static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, | 2874 | static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src, |
2873 | u32 dest, int size) | 2875 | u32 dest, int size) |
2874 | { | 2876 | { |
2875 | void __iomem *tdest; | 2877 | void __iomem *tdest; |
2876 | u32 *wsrc; | ||
2877 | short tsize, i; | 2878 | short tsize, i; |
2878 | 2879 | ||
2879 | if (size <= 0) | 2880 | if (size <= 0) |
@@ -2885,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, | |||
2885 | tdest = (void __iomem *) ®s->Window + | 2886 | tdest = (void __iomem *) ®s->Window + |
2886 | (dest & (ACE_WINDOW_SIZE - 1)); | 2887 | (dest & (ACE_WINDOW_SIZE - 1)); |
2887 | writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); | 2888 | writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); |
2888 | /* | ||
2889 | * This requires byte swapping on big endian, however | ||
2890 | * writel does that for us | ||
2891 | */ | ||
2892 | wsrc = src; | ||
2893 | for (i = 0; i < (tsize / 4); i++) { | 2889 | for (i = 0; i < (tsize / 4); i++) { |
2894 | writel(wsrc[i], tdest + i*4); | 2890 | /* Firmware is big-endian */ |
2891 | writel(be32_to_cpup(src), tdest); | ||
2892 | src++; | ||
2893 | tdest += 4; | ||
2894 | dest += 4; | ||
2895 | size -= 4; | ||
2895 | } | 2896 | } |
2896 | dest += tsize; | ||
2897 | src += tsize; | ||
2898 | size -= tsize; | ||
2899 | } | 2897 | } |
2900 | |||
2901 | return; | ||
2902 | } | 2898 | } |
2903 | 2899 | ||
2904 | 2900 | ||
@@ -2937,8 +2933,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz | |||
2937 | */ | 2933 | */ |
2938 | static int __devinit ace_load_firmware(struct net_device *dev) | 2934 | static int __devinit ace_load_firmware(struct net_device *dev) |
2939 | { | 2935 | { |
2936 | const struct firmware *fw; | ||
2937 | const char *fw_name = "acenic/tg2.bin"; | ||
2940 | struct ace_private *ap = netdev_priv(dev); | 2938 | struct ace_private *ap = netdev_priv(dev); |
2941 | struct ace_regs __iomem *regs = ap->regs; | 2939 | struct ace_regs __iomem *regs = ap->regs; |
2940 | const __be32 *fw_data; | ||
2941 | u32 load_addr; | ||
2942 | int ret; | ||
2942 | 2943 | ||
2943 | if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { | 2944 | if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { |
2944 | printk(KERN_ERR "%s: trying to download firmware while the " | 2945 | printk(KERN_ERR "%s: trying to download firmware while the " |
@@ -2946,28 +2947,52 @@ static int __devinit ace_load_firmware(struct net_device *dev) | |||
2946 | return -EFAULT; | 2947 | return -EFAULT; |
2947 | } | 2948 | } |
2948 | 2949 | ||
2950 | if (ACE_IS_TIGON_I(ap)) | ||
2951 | fw_name = "acenic/tg1.bin"; | ||
2952 | |||
2953 | ret = request_firmware(&fw, fw_name, &ap->pdev->dev); | ||
2954 | if (ret) { | ||
2955 | printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", | ||
2956 | ap->name, fw_name); | ||
2957 | return ret; | ||
2958 | } | ||
2959 | |||
2960 | fw_data = (void *)fw->data; | ||
2961 | |||
2962 | /* Firmware blob starts with version numbers, followed by | ||
2963 | load and start address. Remainder is the blob to be loaded | ||
2964 | contiguously from load address. We don't bother to represent | ||
2965 | the BSS/SBSS sections any more, since we were clearing the | ||
2966 | whole thing anyway. */ | ||
2967 | ap->firmware_major = fw->data[0]; | ||
2968 | ap->firmware_minor = fw->data[1]; | ||
2969 | ap->firmware_fix = fw->data[2]; | ||
2970 | |||
2971 | ap->firmware_start = be32_to_cpu(fw_data[1]); | ||
2972 | if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) { | ||
2973 | printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", | ||
2974 | ap->name, ap->firmware_start, fw_name); | ||
2975 | ret = -EINVAL; | ||
2976 | goto out; | ||
2977 | } | ||
2978 | |||
2979 | load_addr = be32_to_cpu(fw_data[2]); | ||
2980 | if (load_addr < 0x4000 || load_addr >= 0x80000) { | ||
2981 | printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", | ||
2982 | ap->name, load_addr, fw_name); | ||
2983 | ret = -EINVAL; | ||
2984 | goto out; | ||
2985 | } | ||
2986 | |||
2949 | /* | 2987 | /* |
2950 | * Do not try to clear more than 512KB or we end up seeing | 2988 | * Do not try to clear more than 512KiB or we end up seeing |
2951 | * funny things on NICs with only 512KB SRAM | 2989 | * funny things on NICs with only 512KiB SRAM |
2952 | */ | 2990 | */ |
2953 | ace_clear(regs, 0x2000, 0x80000-0x2000); | 2991 | ace_clear(regs, 0x2000, 0x80000-0x2000); |
2954 | if (ACE_IS_TIGON_I(ap)) { | 2992 | ace_copy(regs, &fw_data[3], load_addr, fw->size-12); |
2955 | ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen); | 2993 | out: |
2956 | ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen); | 2994 | release_firmware(fw); |
2957 | ace_copy(regs, tigonFwRodata, tigonFwRodataAddr, | 2995 | return ret; |
2958 | tigonFwRodataLen); | ||
2959 | ace_clear(regs, tigonFwBssAddr, tigonFwBssLen); | ||
2960 | ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen); | ||
2961 | }else if (ap->version == 2) { | ||
2962 | ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen); | ||
2963 | ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen); | ||
2964 | ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen); | ||
2965 | ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr, | ||
2966 | tigon2FwRodataLen); | ||
2967 | ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen); | ||
2968 | } | ||
2969 | |||
2970 | return 0; | ||
2971 | } | 2996 | } |
2972 | 2997 | ||
2973 | 2998 | ||
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index 4487f32759a4..c987c9b5a137 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h | |||
@@ -694,6 +694,10 @@ struct ace_private | |||
694 | u32 last_tx, last_std_rx, last_mini_rx; | 694 | u32 last_tx, last_std_rx, last_mini_rx; |
695 | #endif | 695 | #endif |
696 | int pci_using_dac; | 696 | int pci_using_dac; |
697 | u8 firmware_major; | ||
698 | u8 firmware_minor; | ||
699 | u8 firmware_fix; | ||
700 | u32 firmware_start; | ||
697 | }; | 701 | }; |
698 | 702 | ||
699 | 703 | ||
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 9f38b16ccbbd..134b2d60b479 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -658,12 +658,12 @@ static int e100_self_test(struct nic *nic) | |||
658 | e100_disable_irq(nic); | 658 | e100_disable_irq(nic); |
659 | 659 | ||
660 | /* Check results of self-test */ | 660 | /* Check results of self-test */ |
661 | if(nic->mem->selftest.result != 0) { | 661 | if (nic->mem->selftest.result != 0) { |
662 | DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", | 662 | DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", |
663 | nic->mem->selftest.result); | 663 | nic->mem->selftest.result); |
664 | return -ETIMEDOUT; | 664 | return -ETIMEDOUT; |
665 | } | 665 | } |
666 | if(nic->mem->selftest.signature == 0) { | 666 | if (nic->mem->selftest.signature == 0) { |
667 | DPRINTK(HW, ERR, "Self-test failed: timed out\n"); | 667 | DPRINTK(HW, ERR, "Self-test failed: timed out\n"); |
668 | return -ETIMEDOUT; | 668 | return -ETIMEDOUT; |
669 | } | 669 | } |
@@ -684,13 +684,13 @@ static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 da | |||
684 | cmd_addr_data[2] = op_ewds << (addr_len - 2); | 684 | cmd_addr_data[2] = op_ewds << (addr_len - 2); |
685 | 685 | ||
686 | /* Bit-bang cmds to write word to eeprom */ | 686 | /* Bit-bang cmds to write word to eeprom */ |
687 | for(j = 0; j < 3; j++) { | 687 | for (j = 0; j < 3; j++) { |
688 | 688 | ||
689 | /* Chip select */ | 689 | /* Chip select */ |
690 | iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); | 690 | iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo); |
691 | e100_write_flush(nic); udelay(4); | 691 | e100_write_flush(nic); udelay(4); |
692 | 692 | ||
693 | for(i = 31; i >= 0; i--) { | 693 | for (i = 31; i >= 0; i--) { |
694 | ctrl = (cmd_addr_data[j] & (1 << i)) ? | 694 | ctrl = (cmd_addr_data[j] & (1 << i)) ? |
695 | eecs | eedi : eecs; | 695 | eecs | eedi : eecs; |
696 | iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); | 696 | iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); |
@@ -723,7 +723,7 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) | |||
723 | e100_write_flush(nic); udelay(4); | 723 | e100_write_flush(nic); udelay(4); |
724 | 724 | ||
725 | /* Bit-bang to read word from eeprom */ | 725 | /* Bit-bang to read word from eeprom */ |
726 | for(i = 31; i >= 0; i--) { | 726 | for (i = 31; i >= 0; i--) { |
727 | ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; | 727 | ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; |
728 | iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); | 728 | iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo); |
729 | e100_write_flush(nic); udelay(4); | 729 | e100_write_flush(nic); udelay(4); |
@@ -734,7 +734,7 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) | |||
734 | /* Eeprom drives a dummy zero to EEDO after receiving | 734 | /* Eeprom drives a dummy zero to EEDO after receiving |
735 | * complete address. Use this to adjust addr_len. */ | 735 | * complete address. Use this to adjust addr_len. */ |
736 | ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); | 736 | ctrl = ioread8(&nic->csr->eeprom_ctrl_lo); |
737 | if(!(ctrl & eedo) && i > 16) { | 737 | if (!(ctrl & eedo) && i > 16) { |
738 | *addr_len -= (i - 16); | 738 | *addr_len -= (i - 16); |
739 | i = 17; | 739 | i = 17; |
740 | } | 740 | } |
@@ -758,9 +758,9 @@ static int e100_eeprom_load(struct nic *nic) | |||
758 | e100_eeprom_read(nic, &addr_len, 0); | 758 | e100_eeprom_read(nic, &addr_len, 0); |
759 | nic->eeprom_wc = 1 << addr_len; | 759 | nic->eeprom_wc = 1 << addr_len; |
760 | 760 | ||
761 | for(addr = 0; addr < nic->eeprom_wc; addr++) { | 761 | for (addr = 0; addr < nic->eeprom_wc; addr++) { |
762 | nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); | 762 | nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); |
763 | if(addr < nic->eeprom_wc - 1) | 763 | if (addr < nic->eeprom_wc - 1) |
764 | checksum += le16_to_cpu(nic->eeprom[addr]); | 764 | checksum += le16_to_cpu(nic->eeprom[addr]); |
765 | } | 765 | } |
766 | 766 | ||
@@ -784,15 +784,15 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) | |||
784 | e100_eeprom_read(nic, &addr_len, 0); | 784 | e100_eeprom_read(nic, &addr_len, 0); |
785 | nic->eeprom_wc = 1 << addr_len; | 785 | nic->eeprom_wc = 1 << addr_len; |
786 | 786 | ||
787 | if(start + count >= nic->eeprom_wc) | 787 | if (start + count >= nic->eeprom_wc) |
788 | return -EINVAL; | 788 | return -EINVAL; |
789 | 789 | ||
790 | for(addr = start; addr < start + count; addr++) | 790 | for (addr = start; addr < start + count; addr++) |
791 | e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); | 791 | e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); |
792 | 792 | ||
793 | /* The checksum, stored in the last word, is calculated such that | 793 | /* The checksum, stored in the last word, is calculated such that |
794 | * the sum of words should be 0xBABA */ | 794 | * the sum of words should be 0xBABA */ |
795 | for(addr = 0; addr < nic->eeprom_wc - 1; addr++) | 795 | for (addr = 0; addr < nic->eeprom_wc - 1; addr++) |
796 | checksum += le16_to_cpu(nic->eeprom[addr]); | 796 | checksum += le16_to_cpu(nic->eeprom[addr]); |
797 | nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); | 797 | nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum); |
798 | e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, | 798 | e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, |
@@ -812,19 +812,19 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) | |||
812 | spin_lock_irqsave(&nic->cmd_lock, flags); | 812 | spin_lock_irqsave(&nic->cmd_lock, flags); |
813 | 813 | ||
814 | /* Previous command is accepted when SCB clears */ | 814 | /* Previous command is accepted when SCB clears */ |
815 | for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { | 815 | for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { |
816 | if(likely(!ioread8(&nic->csr->scb.cmd_lo))) | 816 | if (likely(!ioread8(&nic->csr->scb.cmd_lo))) |
817 | break; | 817 | break; |
818 | cpu_relax(); | 818 | cpu_relax(); |
819 | if(unlikely(i > E100_WAIT_SCB_FAST)) | 819 | if (unlikely(i > E100_WAIT_SCB_FAST)) |
820 | udelay(5); | 820 | udelay(5); |
821 | } | 821 | } |
822 | if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { | 822 | if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) { |
823 | err = -EAGAIN; | 823 | err = -EAGAIN; |
824 | goto err_unlock; | 824 | goto err_unlock; |
825 | } | 825 | } |
826 | 826 | ||
827 | if(unlikely(cmd != cuc_resume)) | 827 | if (unlikely(cmd != cuc_resume)) |
828 | iowrite32(dma_addr, &nic->csr->scb.gen_ptr); | 828 | iowrite32(dma_addr, &nic->csr->scb.gen_ptr); |
829 | iowrite8(cmd, &nic->csr->scb.cmd_lo); | 829 | iowrite8(cmd, &nic->csr->scb.cmd_lo); |
830 | 830 | ||
@@ -843,7 +843,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, | |||
843 | 843 | ||
844 | spin_lock_irqsave(&nic->cb_lock, flags); | 844 | spin_lock_irqsave(&nic->cb_lock, flags); |
845 | 845 | ||
846 | if(unlikely(!nic->cbs_avail)) { | 846 | if (unlikely(!nic->cbs_avail)) { |
847 | err = -ENOMEM; | 847 | err = -ENOMEM; |
848 | goto err_unlock; | 848 | goto err_unlock; |
849 | } | 849 | } |
@@ -853,7 +853,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, | |||
853 | nic->cbs_avail--; | 853 | nic->cbs_avail--; |
854 | cb->skb = skb; | 854 | cb->skb = skb; |
855 | 855 | ||
856 | if(unlikely(!nic->cbs_avail)) | 856 | if (unlikely(!nic->cbs_avail)) |
857 | err = -ENOSPC; | 857 | err = -ENOSPC; |
858 | 858 | ||
859 | cb_prepare(nic, cb, skb); | 859 | cb_prepare(nic, cb, skb); |
@@ -864,15 +864,15 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb, | |||
864 | wmb(); | 864 | wmb(); |
865 | cb->prev->command &= cpu_to_le16(~cb_s); | 865 | cb->prev->command &= cpu_to_le16(~cb_s); |
866 | 866 | ||
867 | while(nic->cb_to_send != nic->cb_to_use) { | 867 | while (nic->cb_to_send != nic->cb_to_use) { |
868 | if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd, | 868 | if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd, |
869 | nic->cb_to_send->dma_addr))) { | 869 | nic->cb_to_send->dma_addr))) { |
870 | /* Ok, here's where things get sticky. It's | 870 | /* Ok, here's where things get sticky. It's |
871 | * possible that we can't schedule the command | 871 | * possible that we can't schedule the command |
872 | * because the controller is too busy, so | 872 | * because the controller is too busy, so |
873 | * let's just queue the command and try again | 873 | * let's just queue the command and try again |
874 | * when another command is scheduled. */ | 874 | * when another command is scheduled. */ |
875 | if(err == -ENOSPC) { | 875 | if (err == -ENOSPC) { |
876 | //request a reset | 876 | //request a reset |
877 | schedule_work(&nic->tx_timeout_task); | 877 | schedule_work(&nic->tx_timeout_task); |
878 | } | 878 | } |
@@ -945,7 +945,7 @@ static void e100_get_defaults(struct nic *nic) | |||
945 | 945 | ||
946 | /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ | 946 | /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ |
947 | nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; | 947 | nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision; |
948 | if(nic->mac == mac_unknown) | 948 | if (nic->mac == mac_unknown) |
949 | nic->mac = mac_82557_D100_A; | 949 | nic->mac = mac_82557_D100_A; |
950 | 950 | ||
951 | nic->params.rfds = rfds; | 951 | nic->params.rfds = rfds; |
@@ -1008,23 +1008,23 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) | |||
1008 | config->adaptive_ifs = nic->adaptive_ifs; | 1008 | config->adaptive_ifs = nic->adaptive_ifs; |
1009 | config->loopback = nic->loopback; | 1009 | config->loopback = nic->loopback; |
1010 | 1010 | ||
1011 | if(nic->mii.force_media && nic->mii.full_duplex) | 1011 | if (nic->mii.force_media && nic->mii.full_duplex) |
1012 | config->full_duplex_force = 0x1; /* 1=force, 0=auto */ | 1012 | config->full_duplex_force = 0x1; /* 1=force, 0=auto */ |
1013 | 1013 | ||
1014 | if(nic->flags & promiscuous || nic->loopback) { | 1014 | if (nic->flags & promiscuous || nic->loopback) { |
1015 | config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ | 1015 | config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ |
1016 | config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ | 1016 | config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ |
1017 | config->promiscuous_mode = 0x1; /* 1=on, 0=off */ | 1017 | config->promiscuous_mode = 0x1; /* 1=on, 0=off */ |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | if(nic->flags & multicast_all) | 1020 | if (nic->flags & multicast_all) |
1021 | config->multicast_all = 0x1; /* 1=accept, 0=no */ | 1021 | config->multicast_all = 0x1; /* 1=accept, 0=no */ |
1022 | 1022 | ||
1023 | /* disable WoL when up */ | 1023 | /* disable WoL when up */ |
1024 | if(netif_running(nic->netdev) || !(nic->flags & wol_magic)) | 1024 | if (netif_running(nic->netdev) || !(nic->flags & wol_magic)) |
1025 | config->magic_packet_disable = 0x1; /* 1=off, 0=on */ | 1025 | config->magic_packet_disable = 0x1; /* 1=off, 0=on */ |
1026 | 1026 | ||
1027 | if(nic->mac >= mac_82558_D101_A4) { | 1027 | if (nic->mac >= mac_82558_D101_A4) { |
1028 | config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ | 1028 | config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ |
1029 | config->mwi_enable = 0x1; /* 1=enable, 0=disable */ | 1029 | config->mwi_enable = 0x1; /* 1=enable, 0=disable */ |
1030 | config->standard_tcb = 0x0; /* 1=standard, 0=extended */ | 1030 | config->standard_tcb = 0x0; /* 1=standard, 0=extended */ |
@@ -1369,21 +1369,21 @@ static int e100_phy_init(struct nic *nic) | |||
1369 | u16 bmcr, stat, id_lo, id_hi, cong; | 1369 | u16 bmcr, stat, id_lo, id_hi, cong; |
1370 | 1370 | ||
1371 | /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ | 1371 | /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ |
1372 | for(addr = 0; addr < 32; addr++) { | 1372 | for (addr = 0; addr < 32; addr++) { |
1373 | nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; | 1373 | nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; |
1374 | bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); | 1374 | bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); |
1375 | stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); | 1375 | stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); |
1376 | stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); | 1376 | stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); |
1377 | if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) | 1377 | if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) |
1378 | break; | 1378 | break; |
1379 | } | 1379 | } |
1380 | DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); | 1380 | DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); |
1381 | if(addr == 32) | 1381 | if (addr == 32) |
1382 | return -EAGAIN; | 1382 | return -EAGAIN; |
1383 | 1383 | ||
1384 | /* Selected the phy and isolate the rest */ | 1384 | /* Selected the phy and isolate the rest */ |
1385 | for(addr = 0; addr < 32; addr++) { | 1385 | for (addr = 0; addr < 32; addr++) { |
1386 | if(addr != nic->mii.phy_id) { | 1386 | if (addr != nic->mii.phy_id) { |
1387 | mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); | 1387 | mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); |
1388 | } else { | 1388 | } else { |
1389 | bmcr = mdio_read(netdev, addr, MII_BMCR); | 1389 | bmcr = mdio_read(netdev, addr, MII_BMCR); |
@@ -1400,7 +1400,7 @@ static int e100_phy_init(struct nic *nic) | |||
1400 | 1400 | ||
1401 | /* Handle National tx phys */ | 1401 | /* Handle National tx phys */ |
1402 | #define NCS_PHY_MODEL_MASK 0xFFF0FFFF | 1402 | #define NCS_PHY_MODEL_MASK 0xFFF0FFFF |
1403 | if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { | 1403 | if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { |
1404 | /* Disable congestion control */ | 1404 | /* Disable congestion control */ |
1405 | cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); | 1405 | cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); |
1406 | cong |= NSC_CONG_TXREADY; | 1406 | cong |= NSC_CONG_TXREADY; |
@@ -1408,7 +1408,7 @@ static int e100_phy_init(struct nic *nic) | |||
1408 | mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); | 1408 | mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); |
1409 | } | 1409 | } |
1410 | 1410 | ||
1411 | if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && | 1411 | if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && |
1412 | (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && | 1412 | (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && |
1413 | !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { | 1413 | !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { |
1414 | /* enable/disable MDI/MDI-X auto-switching. */ | 1414 | /* enable/disable MDI/MDI-X auto-switching. */ |
@@ -1426,25 +1426,25 @@ static int e100_hw_init(struct nic *nic) | |||
1426 | e100_hw_reset(nic); | 1426 | e100_hw_reset(nic); |
1427 | 1427 | ||
1428 | DPRINTK(HW, ERR, "e100_hw_init\n"); | 1428 | DPRINTK(HW, ERR, "e100_hw_init\n"); |
1429 | if(!in_interrupt() && (err = e100_self_test(nic))) | 1429 | if (!in_interrupt() && (err = e100_self_test(nic))) |
1430 | return err; | 1430 | return err; |
1431 | 1431 | ||
1432 | if((err = e100_phy_init(nic))) | 1432 | if ((err = e100_phy_init(nic))) |
1433 | return err; | 1433 | return err; |
1434 | if((err = e100_exec_cmd(nic, cuc_load_base, 0))) | 1434 | if ((err = e100_exec_cmd(nic, cuc_load_base, 0))) |
1435 | return err; | 1435 | return err; |
1436 | if((err = e100_exec_cmd(nic, ruc_load_base, 0))) | 1436 | if ((err = e100_exec_cmd(nic, ruc_load_base, 0))) |
1437 | return err; | 1437 | return err; |
1438 | if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) | 1438 | if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode))) |
1439 | return err; | 1439 | return err; |
1440 | if((err = e100_exec_cb(nic, NULL, e100_configure))) | 1440 | if ((err = e100_exec_cb(nic, NULL, e100_configure))) |
1441 | return err; | 1441 | return err; |
1442 | if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) | 1442 | if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) |
1443 | return err; | 1443 | return err; |
1444 | if((err = e100_exec_cmd(nic, cuc_dump_addr, | 1444 | if ((err = e100_exec_cmd(nic, cuc_dump_addr, |
1445 | nic->dma_addr + offsetof(struct mem, stats)))) | 1445 | nic->dma_addr + offsetof(struct mem, stats)))) |
1446 | return err; | 1446 | return err; |
1447 | if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) | 1447 | if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) |
1448 | return err; | 1448 | return err; |
1449 | 1449 | ||
1450 | e100_disable_irq(nic); | 1450 | e100_disable_irq(nic); |
@@ -1460,7 +1460,7 @@ static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) | |||
1460 | 1460 | ||
1461 | cb->command = cpu_to_le16(cb_multi); | 1461 | cb->command = cpu_to_le16(cb_multi); |
1462 | cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); | 1462 | cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); |
1463 | for(i = 0; list && i < count; i++, list = list->next) | 1463 | for (i = 0; list && i < count; i++, list = list->next) |
1464 | memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, | 1464 | memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, |
1465 | ETH_ALEN); | 1465 | ETH_ALEN); |
1466 | } | 1466 | } |
@@ -1472,12 +1472,12 @@ static void e100_set_multicast_list(struct net_device *netdev) | |||
1472 | DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", | 1472 | DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", |
1473 | netdev->mc_count, netdev->flags); | 1473 | netdev->mc_count, netdev->flags); |
1474 | 1474 | ||
1475 | if(netdev->flags & IFF_PROMISC) | 1475 | if (netdev->flags & IFF_PROMISC) |
1476 | nic->flags |= promiscuous; | 1476 | nic->flags |= promiscuous; |
1477 | else | 1477 | else |
1478 | nic->flags &= ~promiscuous; | 1478 | nic->flags &= ~promiscuous; |
1479 | 1479 | ||
1480 | if(netdev->flags & IFF_ALLMULTI || | 1480 | if (netdev->flags & IFF_ALLMULTI || |
1481 | netdev->mc_count > E100_MAX_MULTICAST_ADDRS) | 1481 | netdev->mc_count > E100_MAX_MULTICAST_ADDRS) |
1482 | nic->flags |= multicast_all; | 1482 | nic->flags |= multicast_all; |
1483 | else | 1483 | else |
@@ -1500,7 +1500,7 @@ static void e100_update_stats(struct nic *nic) | |||
1500 | * complete, so we're always waiting for results of the | 1500 | * complete, so we're always waiting for results of the |
1501 | * previous command. */ | 1501 | * previous command. */ |
1502 | 1502 | ||
1503 | if(*complete == cpu_to_le32(cuc_dump_reset_complete)) { | 1503 | if (*complete == cpu_to_le32(cuc_dump_reset_complete)) { |
1504 | *complete = 0; | 1504 | *complete = 0; |
1505 | nic->tx_frames = le32_to_cpu(s->tx_good_frames); | 1505 | nic->tx_frames = le32_to_cpu(s->tx_good_frames); |
1506 | nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); | 1506 | nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); |
@@ -1527,12 +1527,12 @@ static void e100_update_stats(struct nic *nic) | |||
1527 | le32_to_cpu(s->tx_single_collisions); | 1527 | le32_to_cpu(s->tx_single_collisions); |
1528 | nic->tx_multiple_collisions += | 1528 | nic->tx_multiple_collisions += |
1529 | le32_to_cpu(s->tx_multiple_collisions); | 1529 | le32_to_cpu(s->tx_multiple_collisions); |
1530 | if(nic->mac >= mac_82558_D101_A4) { | 1530 | if (nic->mac >= mac_82558_D101_A4) { |
1531 | nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); | 1531 | nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); |
1532 | nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); | 1532 | nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); |
1533 | nic->rx_fc_unsupported += | 1533 | nic->rx_fc_unsupported += |
1534 | le32_to_cpu(s->fc_rcv_unsupported); | 1534 | le32_to_cpu(s->fc_rcv_unsupported); |
1535 | if(nic->mac >= mac_82559_D101M) { | 1535 | if (nic->mac >= mac_82559_D101M) { |
1536 | nic->tx_tco_frames += | 1536 | nic->tx_tco_frames += |
1537 | le16_to_cpu(s->xmt_tco_frames); | 1537 | le16_to_cpu(s->xmt_tco_frames); |
1538 | nic->rx_tco_frames += | 1538 | nic->rx_tco_frames += |
@@ -1542,7 +1542,7 @@ static void e100_update_stats(struct nic *nic) | |||
1542 | } | 1542 | } |
1543 | 1543 | ||
1544 | 1544 | ||
1545 | if(e100_exec_cmd(nic, cuc_dump_reset, 0)) | 1545 | if (e100_exec_cmd(nic, cuc_dump_reset, 0)) |
1546 | DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); | 1546 | DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n"); |
1547 | } | 1547 | } |
1548 | 1548 | ||
@@ -1551,19 +1551,19 @@ static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) | |||
1551 | /* Adjust inter-frame-spacing (IFS) between two transmits if | 1551 | /* Adjust inter-frame-spacing (IFS) between two transmits if |
1552 | * we're getting collisions on a half-duplex connection. */ | 1552 | * we're getting collisions on a half-duplex connection. */ |
1553 | 1553 | ||
1554 | if(duplex == DUPLEX_HALF) { | 1554 | if (duplex == DUPLEX_HALF) { |
1555 | u32 prev = nic->adaptive_ifs; | 1555 | u32 prev = nic->adaptive_ifs; |
1556 | u32 min_frames = (speed == SPEED_100) ? 1000 : 100; | 1556 | u32 min_frames = (speed == SPEED_100) ? 1000 : 100; |
1557 | 1557 | ||
1558 | if((nic->tx_frames / 32 < nic->tx_collisions) && | 1558 | if ((nic->tx_frames / 32 < nic->tx_collisions) && |
1559 | (nic->tx_frames > min_frames)) { | 1559 | (nic->tx_frames > min_frames)) { |
1560 | if(nic->adaptive_ifs < 60) | 1560 | if (nic->adaptive_ifs < 60) |
1561 | nic->adaptive_ifs += 5; | 1561 | nic->adaptive_ifs += 5; |
1562 | } else if (nic->tx_frames < min_frames) { | 1562 | } else if (nic->tx_frames < min_frames) { |
1563 | if(nic->adaptive_ifs >= 5) | 1563 | if (nic->adaptive_ifs >= 5) |
1564 | nic->adaptive_ifs -= 5; | 1564 | nic->adaptive_ifs -= 5; |
1565 | } | 1565 | } |
1566 | if(nic->adaptive_ifs != prev) | 1566 | if (nic->adaptive_ifs != prev) |
1567 | e100_exec_cb(nic, NULL, e100_configure); | 1567 | e100_exec_cb(nic, NULL, e100_configure); |
1568 | } | 1568 | } |
1569 | } | 1569 | } |
@@ -1579,12 +1579,12 @@ static void e100_watchdog(unsigned long data) | |||
1579 | 1579 | ||
1580 | mii_ethtool_gset(&nic->mii, &cmd); | 1580 | mii_ethtool_gset(&nic->mii, &cmd); |
1581 | 1581 | ||
1582 | if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { | 1582 | if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { |
1583 | printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", | 1583 | printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n", |
1584 | nic->netdev->name, | 1584 | nic->netdev->name, |
1585 | cmd.speed == SPEED_100 ? "100" : "10", | 1585 | cmd.speed == SPEED_100 ? "100" : "10", |
1586 | cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); | 1586 | cmd.duplex == DUPLEX_FULL ? "Full" : "Half"); |
1587 | } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { | 1587 | } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { |
1588 | printk(KERN_INFO "e100: %s NIC Link is Down\n", | 1588 | printk(KERN_INFO "e100: %s NIC Link is Down\n", |
1589 | nic->netdev->name); | 1589 | nic->netdev->name); |
1590 | } | 1590 | } |
@@ -1604,11 +1604,11 @@ static void e100_watchdog(unsigned long data) | |||
1604 | e100_update_stats(nic); | 1604 | e100_update_stats(nic); |
1605 | e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); | 1605 | e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); |
1606 | 1606 | ||
1607 | if(nic->mac <= mac_82557_D100_C) | 1607 | if (nic->mac <= mac_82557_D100_C) |
1608 | /* Issue a multicast command to workaround a 557 lock up */ | 1608 | /* Issue a multicast command to workaround a 557 lock up */ |
1609 | e100_set_multicast_list(nic->netdev); | 1609 | e100_set_multicast_list(nic->netdev); |
1610 | 1610 | ||
1611 | if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) | 1611 | if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF) |
1612 | /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ | 1612 | /* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */ |
1613 | nic->flags |= ich_10h_workaround; | 1613 | nic->flags |= ich_10h_workaround; |
1614 | else | 1614 | else |
@@ -1623,7 +1623,7 @@ static void e100_xmit_prepare(struct nic *nic, struct cb *cb, | |||
1623 | { | 1623 | { |
1624 | cb->command = nic->tx_command; | 1624 | cb->command = nic->tx_command; |
1625 | /* interrupt every 16 packets regardless of delay */ | 1625 | /* interrupt every 16 packets regardless of delay */ |
1626 | if((nic->cbs_avail & ~15) == nic->cbs_avail) | 1626 | if ((nic->cbs_avail & ~15) == nic->cbs_avail) |
1627 | cb->command |= cpu_to_le16(cb_i); | 1627 | cb->command |= cpu_to_le16(cb_i); |
1628 | cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); | 1628 | cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); |
1629 | cb->u.tcb.tcb_byte_count = 0; | 1629 | cb->u.tcb.tcb_byte_count = 0; |
@@ -1640,18 +1640,18 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1640 | struct nic *nic = netdev_priv(netdev); | 1640 | struct nic *nic = netdev_priv(netdev); |
1641 | int err; | 1641 | int err; |
1642 | 1642 | ||
1643 | if(nic->flags & ich_10h_workaround) { | 1643 | if (nic->flags & ich_10h_workaround) { |
1644 | /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. | 1644 | /* SW workaround for ICH[x] 10Mbps/half duplex Tx hang. |
1645 | Issue a NOP command followed by a 1us delay before | 1645 | Issue a NOP command followed by a 1us delay before |
1646 | issuing the Tx command. */ | 1646 | issuing the Tx command. */ |
1647 | if(e100_exec_cmd(nic, cuc_nop, 0)) | 1647 | if (e100_exec_cmd(nic, cuc_nop, 0)) |
1648 | DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); | 1648 | DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n"); |
1649 | udelay(1); | 1649 | udelay(1); |
1650 | } | 1650 | } |
1651 | 1651 | ||
1652 | err = e100_exec_cb(nic, skb, e100_xmit_prepare); | 1652 | err = e100_exec_cb(nic, skb, e100_xmit_prepare); |
1653 | 1653 | ||
1654 | switch(err) { | 1654 | switch (err) { |
1655 | case -ENOSPC: | 1655 | case -ENOSPC: |
1656 | /* We queued the skb, but now we're out of space. */ | 1656 | /* We queued the skb, but now we're out of space. */ |
1657 | DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); | 1657 | DPRINTK(TX_ERR, DEBUG, "No space for CB\n"); |
@@ -1677,14 +1677,14 @@ static int e100_tx_clean(struct nic *nic) | |||
1677 | spin_lock(&nic->cb_lock); | 1677 | spin_lock(&nic->cb_lock); |
1678 | 1678 | ||
1679 | /* Clean CBs marked complete */ | 1679 | /* Clean CBs marked complete */ |
1680 | for(cb = nic->cb_to_clean; | 1680 | for (cb = nic->cb_to_clean; |
1681 | cb->status & cpu_to_le16(cb_complete); | 1681 | cb->status & cpu_to_le16(cb_complete); |
1682 | cb = nic->cb_to_clean = cb->next) { | 1682 | cb = nic->cb_to_clean = cb->next) { |
1683 | DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", | 1683 | DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n", |
1684 | (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), | 1684 | (int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)), |
1685 | cb->status); | 1685 | cb->status); |
1686 | 1686 | ||
1687 | if(likely(cb->skb != NULL)) { | 1687 | if (likely(cb->skb != NULL)) { |
1688 | dev->stats.tx_packets++; | 1688 | dev->stats.tx_packets++; |
1689 | dev->stats.tx_bytes += cb->skb->len; | 1689 | dev->stats.tx_bytes += cb->skb->len; |
1690 | 1690 | ||
@@ -1703,7 +1703,7 @@ static int e100_tx_clean(struct nic *nic) | |||
1703 | spin_unlock(&nic->cb_lock); | 1703 | spin_unlock(&nic->cb_lock); |
1704 | 1704 | ||
1705 | /* Recover from running out of Tx resources in xmit_frame */ | 1705 | /* Recover from running out of Tx resources in xmit_frame */ |
1706 | if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) | 1706 | if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) |
1707 | netif_wake_queue(nic->netdev); | 1707 | netif_wake_queue(nic->netdev); |
1708 | 1708 | ||
1709 | return tx_cleaned; | 1709 | return tx_cleaned; |
@@ -1711,10 +1711,10 @@ static int e100_tx_clean(struct nic *nic) | |||
1711 | 1711 | ||
1712 | static void e100_clean_cbs(struct nic *nic) | 1712 | static void e100_clean_cbs(struct nic *nic) |
1713 | { | 1713 | { |
1714 | if(nic->cbs) { | 1714 | if (nic->cbs) { |
1715 | while(nic->cbs_avail != nic->params.cbs.count) { | 1715 | while (nic->cbs_avail != nic->params.cbs.count) { |
1716 | struct cb *cb = nic->cb_to_clean; | 1716 | struct cb *cb = nic->cb_to_clean; |
1717 | if(cb->skb) { | 1717 | if (cb->skb) { |
1718 | pci_unmap_single(nic->pdev, | 1718 | pci_unmap_single(nic->pdev, |
1719 | le32_to_cpu(cb->u.tcb.tbd.buf_addr), | 1719 | le32_to_cpu(cb->u.tcb.tbd.buf_addr), |
1720 | le16_to_cpu(cb->u.tcb.tbd.size), | 1720 | le16_to_cpu(cb->u.tcb.tbd.size), |
@@ -1746,10 +1746,10 @@ static int e100_alloc_cbs(struct nic *nic) | |||
1746 | 1746 | ||
1747 | nic->cbs = pci_alloc_consistent(nic->pdev, | 1747 | nic->cbs = pci_alloc_consistent(nic->pdev, |
1748 | sizeof(struct cb) * count, &nic->cbs_dma_addr); | 1748 | sizeof(struct cb) * count, &nic->cbs_dma_addr); |
1749 | if(!nic->cbs) | 1749 | if (!nic->cbs) |
1750 | return -ENOMEM; | 1750 | return -ENOMEM; |
1751 | 1751 | ||
1752 | for(cb = nic->cbs, i = 0; i < count; cb++, i++) { | 1752 | for (cb = nic->cbs, i = 0; i < count; cb++, i++) { |
1753 | cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; | 1753 | cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; |
1754 | cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; | 1754 | cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; |
1755 | 1755 | ||
@@ -1767,14 +1767,14 @@ static int e100_alloc_cbs(struct nic *nic) | |||
1767 | 1767 | ||
1768 | static inline void e100_start_receiver(struct nic *nic, struct rx *rx) | 1768 | static inline void e100_start_receiver(struct nic *nic, struct rx *rx) |
1769 | { | 1769 | { |
1770 | if(!nic->rxs) return; | 1770 | if (!nic->rxs) return; |
1771 | if(RU_SUSPENDED != nic->ru_running) return; | 1771 | if (RU_SUSPENDED != nic->ru_running) return; |
1772 | 1772 | ||
1773 | /* handle init time starts */ | 1773 | /* handle init time starts */ |
1774 | if(!rx) rx = nic->rxs; | 1774 | if (!rx) rx = nic->rxs; |
1775 | 1775 | ||
1776 | /* (Re)start RU if suspended or idle and RFA is non-NULL */ | 1776 | /* (Re)start RU if suspended or idle and RFA is non-NULL */ |
1777 | if(rx->skb) { | 1777 | if (rx->skb) { |
1778 | e100_exec_cmd(nic, ruc_start, rx->dma_addr); | 1778 | e100_exec_cmd(nic, ruc_start, rx->dma_addr); |
1779 | nic->ru_running = RU_RUNNING; | 1779 | nic->ru_running = RU_RUNNING; |
1780 | } | 1780 | } |
@@ -1783,7 +1783,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx) | |||
1783 | #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) | 1783 | #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) |
1784 | static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) | 1784 | static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) |
1785 | { | 1785 | { |
1786 | if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) | 1786 | if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN))) |
1787 | return -ENOMEM; | 1787 | return -ENOMEM; |
1788 | 1788 | ||
1789 | /* Align, init, and map the RFD. */ | 1789 | /* Align, init, and map the RFD. */ |
@@ -1820,7 +1820,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1820 | struct rfd *rfd = (struct rfd *)skb->data; | 1820 | struct rfd *rfd = (struct rfd *)skb->data; |
1821 | u16 rfd_status, actual_size; | 1821 | u16 rfd_status, actual_size; |
1822 | 1822 | ||
1823 | if(unlikely(work_done && *work_done >= work_to_do)) | 1823 | if (unlikely(work_done && *work_done >= work_to_do)) |
1824 | return -EAGAIN; | 1824 | return -EAGAIN; |
1825 | 1825 | ||
1826 | /* Need to sync before taking a peek at cb_complete bit */ | 1826 | /* Need to sync before taking a peek at cb_complete bit */ |
@@ -1847,7 +1847,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1847 | 1847 | ||
1848 | /* Get actual data size */ | 1848 | /* Get actual data size */ |
1849 | actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; | 1849 | actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; |
1850 | if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) | 1850 | if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) |
1851 | actual_size = RFD_BUF_LEN - sizeof(struct rfd); | 1851 | actual_size = RFD_BUF_LEN - sizeof(struct rfd); |
1852 | 1852 | ||
1853 | /* Get data */ | 1853 | /* Get data */ |
@@ -1872,10 +1872,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1872 | skb_put(skb, actual_size); | 1872 | skb_put(skb, actual_size); |
1873 | skb->protocol = eth_type_trans(skb, nic->netdev); | 1873 | skb->protocol = eth_type_trans(skb, nic->netdev); |
1874 | 1874 | ||
1875 | if(unlikely(!(rfd_status & cb_ok))) { | 1875 | if (unlikely(!(rfd_status & cb_ok))) { |
1876 | /* Don't indicate if hardware indicates errors */ | 1876 | /* Don't indicate if hardware indicates errors */ |
1877 | dev_kfree_skb_any(skb); | 1877 | dev_kfree_skb_any(skb); |
1878 | } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { | 1878 | } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { |
1879 | /* Don't indicate oversized frames */ | 1879 | /* Don't indicate oversized frames */ |
1880 | nic->rx_over_length_errors++; | 1880 | nic->rx_over_length_errors++; |
1881 | dev_kfree_skb_any(skb); | 1881 | dev_kfree_skb_any(skb); |
@@ -1883,7 +1883,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1883 | dev->stats.rx_packets++; | 1883 | dev->stats.rx_packets++; |
1884 | dev->stats.rx_bytes += actual_size; | 1884 | dev->stats.rx_bytes += actual_size; |
1885 | netif_receive_skb(skb); | 1885 | netif_receive_skb(skb); |
1886 | if(work_done) | 1886 | if (work_done) |
1887 | (*work_done)++; | 1887 | (*work_done)++; |
1888 | } | 1888 | } |
1889 | 1889 | ||
@@ -1901,7 +1901,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
1901 | struct rfd *old_before_last_rfd, *new_before_last_rfd; | 1901 | struct rfd *old_before_last_rfd, *new_before_last_rfd; |
1902 | 1902 | ||
1903 | /* Indicate newly arrived packets */ | 1903 | /* Indicate newly arrived packets */ |
1904 | for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { | 1904 | for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { |
1905 | err = e100_rx_indicate(nic, rx, work_done, work_to_do); | 1905 | err = e100_rx_indicate(nic, rx, work_done, work_to_do); |
1906 | /* Hit quota or no more to clean */ | 1906 | /* Hit quota or no more to clean */ |
1907 | if (-EAGAIN == err || -ENODATA == err) | 1907 | if (-EAGAIN == err || -ENODATA == err) |
@@ -1922,8 +1922,8 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
1922 | old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; | 1922 | old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data; |
1923 | 1923 | ||
1924 | /* Alloc new skbs to refill list */ | 1924 | /* Alloc new skbs to refill list */ |
1925 | for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { | 1925 | for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { |
1926 | if(unlikely(e100_rx_alloc_skb(nic, rx))) | 1926 | if (unlikely(e100_rx_alloc_skb(nic, rx))) |
1927 | break; /* Better luck next time (see watchdog) */ | 1927 | break; /* Better luck next time (see watchdog) */ |
1928 | } | 1928 | } |
1929 | 1929 | ||
@@ -1959,11 +1959,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
1959 | PCI_DMA_BIDIRECTIONAL); | 1959 | PCI_DMA_BIDIRECTIONAL); |
1960 | } | 1960 | } |
1961 | 1961 | ||
1962 | if(restart_required) { | 1962 | if (restart_required) { |
1963 | // ack the rnr? | 1963 | // ack the rnr? |
1964 | iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); | 1964 | iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack); |
1965 | e100_start_receiver(nic, nic->rx_to_clean); | 1965 | e100_start_receiver(nic, nic->rx_to_clean); |
1966 | if(work_done) | 1966 | if (work_done) |
1967 | (*work_done)++; | 1967 | (*work_done)++; |
1968 | } | 1968 | } |
1969 | } | 1969 | } |
@@ -1975,9 +1975,9 @@ static void e100_rx_clean_list(struct nic *nic) | |||
1975 | 1975 | ||
1976 | nic->ru_running = RU_UNINITIALIZED; | 1976 | nic->ru_running = RU_UNINITIALIZED; |
1977 | 1977 | ||
1978 | if(nic->rxs) { | 1978 | if (nic->rxs) { |
1979 | for(rx = nic->rxs, i = 0; i < count; rx++, i++) { | 1979 | for (rx = nic->rxs, i = 0; i < count; rx++, i++) { |
1980 | if(rx->skb) { | 1980 | if (rx->skb) { |
1981 | pci_unmap_single(nic->pdev, rx->dma_addr, | 1981 | pci_unmap_single(nic->pdev, rx->dma_addr, |
1982 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); | 1982 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
1983 | dev_kfree_skb(rx->skb); | 1983 | dev_kfree_skb(rx->skb); |
@@ -1999,13 +1999,13 @@ static int e100_rx_alloc_list(struct nic *nic) | |||
1999 | nic->rx_to_use = nic->rx_to_clean = NULL; | 1999 | nic->rx_to_use = nic->rx_to_clean = NULL; |
2000 | nic->ru_running = RU_UNINITIALIZED; | 2000 | nic->ru_running = RU_UNINITIALIZED; |
2001 | 2001 | ||
2002 | if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) | 2002 | if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC))) |
2003 | return -ENOMEM; | 2003 | return -ENOMEM; |
2004 | 2004 | ||
2005 | for(rx = nic->rxs, i = 0; i < count; rx++, i++) { | 2005 | for (rx = nic->rxs, i = 0; i < count; rx++, i++) { |
2006 | rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; | 2006 | rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; |
2007 | rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; | 2007 | rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; |
2008 | if(e100_rx_alloc_skb(nic, rx)) { | 2008 | if (e100_rx_alloc_skb(nic, rx)) { |
2009 | e100_rx_clean_list(nic); | 2009 | e100_rx_clean_list(nic); |
2010 | return -ENOMEM; | 2010 | return -ENOMEM; |
2011 | } | 2011 | } |
@@ -2038,7 +2038,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id) | |||
2038 | 2038 | ||
2039 | DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); | 2039 | DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); |
2040 | 2040 | ||
2041 | if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ | 2041 | if (stat_ack == stat_ack_not_ours || /* Not our interrupt */ |
2042 | stat_ack == stat_ack_not_present) /* Hardware is ejected */ | 2042 | stat_ack == stat_ack_not_present) /* Hardware is ejected */ |
2043 | return IRQ_NONE; | 2043 | return IRQ_NONE; |
2044 | 2044 | ||
@@ -2046,10 +2046,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id) | |||
2046 | iowrite8(stat_ack, &nic->csr->scb.stat_ack); | 2046 | iowrite8(stat_ack, &nic->csr->scb.stat_ack); |
2047 | 2047 | ||
2048 | /* We hit Receive No Resource (RNR); restart RU after cleaning */ | 2048 | /* We hit Receive No Resource (RNR); restart RU after cleaning */ |
2049 | if(stat_ack & stat_ack_rnr) | 2049 | if (stat_ack & stat_ack_rnr) |
2050 | nic->ru_running = RU_SUSPENDED; | 2050 | nic->ru_running = RU_SUSPENDED; |
2051 | 2051 | ||
2052 | if(likely(netif_rx_schedule_prep(&nic->napi))) { | 2052 | if (likely(netif_rx_schedule_prep(&nic->napi))) { |
2053 | e100_disable_irq(nic); | 2053 | e100_disable_irq(nic); |
2054 | __netif_rx_schedule(&nic->napi); | 2054 | __netif_rx_schedule(&nic->napi); |
2055 | } | 2055 | } |
@@ -2102,7 +2102,7 @@ static int e100_set_mac_address(struct net_device *netdev, void *p) | |||
2102 | 2102 | ||
2103 | static int e100_change_mtu(struct net_device *netdev, int new_mtu) | 2103 | static int e100_change_mtu(struct net_device *netdev, int new_mtu) |
2104 | { | 2104 | { |
2105 | if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) | 2105 | if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) |
2106 | return -EINVAL; | 2106 | return -EINVAL; |
2107 | netdev->mtu = new_mtu; | 2107 | netdev->mtu = new_mtu; |
2108 | return 0; | 2108 | return 0; |
@@ -2121,16 +2121,16 @@ static int e100_up(struct nic *nic) | |||
2121 | { | 2121 | { |
2122 | int err; | 2122 | int err; |
2123 | 2123 | ||
2124 | if((err = e100_rx_alloc_list(nic))) | 2124 | if ((err = e100_rx_alloc_list(nic))) |
2125 | return err; | 2125 | return err; |
2126 | if((err = e100_alloc_cbs(nic))) | 2126 | if ((err = e100_alloc_cbs(nic))) |
2127 | goto err_rx_clean_list; | 2127 | goto err_rx_clean_list; |
2128 | if((err = e100_hw_init(nic))) | 2128 | if ((err = e100_hw_init(nic))) |
2129 | goto err_clean_cbs; | 2129 | goto err_clean_cbs; |
2130 | e100_set_multicast_list(nic->netdev); | 2130 | e100_set_multicast_list(nic->netdev); |
2131 | e100_start_receiver(nic, NULL); | 2131 | e100_start_receiver(nic, NULL); |
2132 | mod_timer(&nic->watchdog, jiffies); | 2132 | mod_timer(&nic->watchdog, jiffies); |
2133 | if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, | 2133 | if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED, |
2134 | nic->netdev->name, nic->netdev))) | 2134 | nic->netdev->name, nic->netdev))) |
2135 | goto err_no_irq; | 2135 | goto err_no_irq; |
2136 | netif_wake_queue(nic->netdev); | 2136 | netif_wake_queue(nic->netdev); |
@@ -2192,26 +2192,26 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) | |||
2192 | * in loopback mode, and the test passes if the received | 2192 | * in loopback mode, and the test passes if the received |
2193 | * packet compares byte-for-byte to the transmitted packet. */ | 2193 | * packet compares byte-for-byte to the transmitted packet. */ |
2194 | 2194 | ||
2195 | if((err = e100_rx_alloc_list(nic))) | 2195 | if ((err = e100_rx_alloc_list(nic))) |
2196 | return err; | 2196 | return err; |
2197 | if((err = e100_alloc_cbs(nic))) | 2197 | if ((err = e100_alloc_cbs(nic))) |
2198 | goto err_clean_rx; | 2198 | goto err_clean_rx; |
2199 | 2199 | ||
2200 | /* ICH PHY loopback is broken so do MAC loopback instead */ | 2200 | /* ICH PHY loopback is broken so do MAC loopback instead */ |
2201 | if(nic->flags & ich && loopback_mode == lb_phy) | 2201 | if (nic->flags & ich && loopback_mode == lb_phy) |
2202 | loopback_mode = lb_mac; | 2202 | loopback_mode = lb_mac; |
2203 | 2203 | ||
2204 | nic->loopback = loopback_mode; | 2204 | nic->loopback = loopback_mode; |
2205 | if((err = e100_hw_init(nic))) | 2205 | if ((err = e100_hw_init(nic))) |
2206 | goto err_loopback_none; | 2206 | goto err_loopback_none; |
2207 | 2207 | ||
2208 | if(loopback_mode == lb_phy) | 2208 | if (loopback_mode == lb_phy) |
2209 | mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, | 2209 | mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, |
2210 | BMCR_LOOPBACK); | 2210 | BMCR_LOOPBACK); |
2211 | 2211 | ||
2212 | e100_start_receiver(nic, NULL); | 2212 | e100_start_receiver(nic, NULL); |
2213 | 2213 | ||
2214 | if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { | 2214 | if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) { |
2215 | err = -ENOMEM; | 2215 | err = -ENOMEM; |
2216 | goto err_loopback_none; | 2216 | goto err_loopback_none; |
2217 | } | 2217 | } |
@@ -2224,7 +2224,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) | |||
2224 | pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, | 2224 | pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, |
2225 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); | 2225 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
2226 | 2226 | ||
2227 | if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), | 2227 | if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), |
2228 | skb->data, ETH_DATA_LEN)) | 2228 | skb->data, ETH_DATA_LEN)) |
2229 | err = -EAGAIN; | 2229 | err = -EAGAIN; |
2230 | 2230 | ||
@@ -2301,7 +2301,7 @@ static void e100_get_regs(struct net_device *netdev, | |||
2301 | buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | | 2301 | buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 | |
2302 | ioread8(&nic->csr->scb.cmd_lo) << 16 | | 2302 | ioread8(&nic->csr->scb.cmd_lo) << 16 | |
2303 | ioread16(&nic->csr->scb.status); | 2303 | ioread16(&nic->csr->scb.status); |
2304 | for(i = E100_PHY_REGS; i >= 0; i--) | 2304 | for (i = E100_PHY_REGS; i >= 0; i--) |
2305 | buff[1 + E100_PHY_REGS - i] = | 2305 | buff[1 + E100_PHY_REGS - i] = |
2306 | mdio_read(netdev, nic->mii.phy_id, i); | 2306 | mdio_read(netdev, nic->mii.phy_id, i); |
2307 | memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); | 2307 | memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); |
@@ -2326,7 +2326,7 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
2326 | !device_can_wakeup(&nic->pdev->dev)) | 2326 | !device_can_wakeup(&nic->pdev->dev)) |
2327 | return -EOPNOTSUPP; | 2327 | return -EOPNOTSUPP; |
2328 | 2328 | ||
2329 | if(wol->wolopts) | 2329 | if (wol->wolopts) |
2330 | nic->flags |= wol_magic; | 2330 | nic->flags |= wol_magic; |
2331 | else | 2331 | else |
2332 | nic->flags &= ~wol_magic; | 2332 | nic->flags &= ~wol_magic; |
@@ -2385,7 +2385,7 @@ static int e100_set_eeprom(struct net_device *netdev, | |||
2385 | { | 2385 | { |
2386 | struct nic *nic = netdev_priv(netdev); | 2386 | struct nic *nic = netdev_priv(netdev); |
2387 | 2387 | ||
2388 | if(eeprom->magic != E100_EEPROM_MAGIC) | 2388 | if (eeprom->magic != E100_EEPROM_MAGIC) |
2389 | return -EINVAL; | 2389 | return -EINVAL; |
2390 | 2390 | ||
2391 | memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); | 2391 | memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); |
@@ -2421,7 +2421,7 @@ static int e100_set_ringparam(struct net_device *netdev, | |||
2421 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) | 2421 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
2422 | return -EINVAL; | 2422 | return -EINVAL; |
2423 | 2423 | ||
2424 | if(netif_running(netdev)) | 2424 | if (netif_running(netdev)) |
2425 | e100_down(nic); | 2425 | e100_down(nic); |
2426 | rfds->count = max(ring->rx_pending, rfds->min); | 2426 | rfds->count = max(ring->rx_pending, rfds->min); |
2427 | rfds->count = min(rfds->count, rfds->max); | 2427 | rfds->count = min(rfds->count, rfds->max); |
@@ -2429,7 +2429,7 @@ static int e100_set_ringparam(struct net_device *netdev, | |||
2429 | cbs->count = min(cbs->count, cbs->max); | 2429 | cbs->count = min(cbs->count, cbs->max); |
2430 | DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", | 2430 | DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", |
2431 | rfds->count, cbs->count); | 2431 | rfds->count, cbs->count); |
2432 | if(netif_running(netdev)) | 2432 | if (netif_running(netdev)) |
2433 | e100_up(nic); | 2433 | e100_up(nic); |
2434 | 2434 | ||
2435 | return 0; | 2435 | return 0; |
@@ -2454,12 +2454,12 @@ static void e100_diag_test(struct net_device *netdev, | |||
2454 | memset(data, 0, E100_TEST_LEN * sizeof(u64)); | 2454 | memset(data, 0, E100_TEST_LEN * sizeof(u64)); |
2455 | data[0] = !mii_link_ok(&nic->mii); | 2455 | data[0] = !mii_link_ok(&nic->mii); |
2456 | data[1] = e100_eeprom_load(nic); | 2456 | data[1] = e100_eeprom_load(nic); |
2457 | if(test->flags & ETH_TEST_FL_OFFLINE) { | 2457 | if (test->flags & ETH_TEST_FL_OFFLINE) { |
2458 | 2458 | ||
2459 | /* save speed, duplex & autoneg settings */ | 2459 | /* save speed, duplex & autoneg settings */ |
2460 | err = mii_ethtool_gset(&nic->mii, &cmd); | 2460 | err = mii_ethtool_gset(&nic->mii, &cmd); |
2461 | 2461 | ||
2462 | if(netif_running(netdev)) | 2462 | if (netif_running(netdev)) |
2463 | e100_down(nic); | 2463 | e100_down(nic); |
2464 | data[2] = e100_self_test(nic); | 2464 | data[2] = e100_self_test(nic); |
2465 | data[3] = e100_loopback_test(nic, lb_mac); | 2465 | data[3] = e100_loopback_test(nic, lb_mac); |
@@ -2468,10 +2468,10 @@ static void e100_diag_test(struct net_device *netdev, | |||
2468 | /* restore speed, duplex & autoneg settings */ | 2468 | /* restore speed, duplex & autoneg settings */ |
2469 | err = mii_ethtool_sset(&nic->mii, &cmd); | 2469 | err = mii_ethtool_sset(&nic->mii, &cmd); |
2470 | 2470 | ||
2471 | if(netif_running(netdev)) | 2471 | if (netif_running(netdev)) |
2472 | e100_up(nic); | 2472 | e100_up(nic); |
2473 | } | 2473 | } |
2474 | for(i = 0; i < E100_TEST_LEN; i++) | 2474 | for (i = 0; i < E100_TEST_LEN; i++) |
2475 | test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; | 2475 | test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; |
2476 | 2476 | ||
2477 | msleep_interruptible(4 * 1000); | 2477 | msleep_interruptible(4 * 1000); |
@@ -2481,7 +2481,7 @@ static int e100_phys_id(struct net_device *netdev, u32 data) | |||
2481 | { | 2481 | { |
2482 | struct nic *nic = netdev_priv(netdev); | 2482 | struct nic *nic = netdev_priv(netdev); |
2483 | 2483 | ||
2484 | if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) | 2484 | if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) |
2485 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); | 2485 | data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); |
2486 | mod_timer(&nic->blink_timer, jiffies); | 2486 | mod_timer(&nic->blink_timer, jiffies); |
2487 | msleep_interruptible(data * 1000); | 2487 | msleep_interruptible(data * 1000); |
@@ -2524,7 +2524,7 @@ static void e100_get_ethtool_stats(struct net_device *netdev, | |||
2524 | struct nic *nic = netdev_priv(netdev); | 2524 | struct nic *nic = netdev_priv(netdev); |
2525 | int i; | 2525 | int i; |
2526 | 2526 | ||
2527 | for(i = 0; i < E100_NET_STATS_LEN; i++) | 2527 | for (i = 0; i < E100_NET_STATS_LEN; i++) |
2528 | data[i] = ((unsigned long *)&netdev->stats)[i]; | 2528 | data[i] = ((unsigned long *)&netdev->stats)[i]; |
2529 | 2529 | ||
2530 | data[i++] = nic->tx_deferred; | 2530 | data[i++] = nic->tx_deferred; |
@@ -2539,7 +2539,7 @@ static void e100_get_ethtool_stats(struct net_device *netdev, | |||
2539 | 2539 | ||
2540 | static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) | 2540 | static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) |
2541 | { | 2541 | { |
2542 | switch(stringset) { | 2542 | switch (stringset) { |
2543 | case ETH_SS_TEST: | 2543 | case ETH_SS_TEST: |
2544 | memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); | 2544 | memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); |
2545 | break; | 2545 | break; |
@@ -2589,7 +2589,7 @@ static int e100_alloc(struct nic *nic) | |||
2589 | 2589 | ||
2590 | static void e100_free(struct nic *nic) | 2590 | static void e100_free(struct nic *nic) |
2591 | { | 2591 | { |
2592 | if(nic->mem) { | 2592 | if (nic->mem) { |
2593 | pci_free_consistent(nic->pdev, sizeof(struct mem), | 2593 | pci_free_consistent(nic->pdev, sizeof(struct mem), |
2594 | nic->mem, nic->dma_addr); | 2594 | nic->mem, nic->dma_addr); |
2595 | nic->mem = NULL; | 2595 | nic->mem = NULL; |
@@ -2602,7 +2602,7 @@ static int e100_open(struct net_device *netdev) | |||
2602 | int err = 0; | 2602 | int err = 0; |
2603 | 2603 | ||
2604 | netif_carrier_off(netdev); | 2604 | netif_carrier_off(netdev); |
2605 | if((err = e100_up(nic))) | 2605 | if ((err = e100_up(nic))) |
2606 | DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); | 2606 | DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); |
2607 | return err; | 2607 | return err; |
2608 | } | 2608 | } |
@@ -2635,8 +2635,8 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2635 | struct nic *nic; | 2635 | struct nic *nic; |
2636 | int err; | 2636 | int err; |
2637 | 2637 | ||
2638 | if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { | 2638 | if (!(netdev = alloc_etherdev(sizeof(struct nic)))) { |
2639 | if(((1 << debug) - 1) & NETIF_MSG_PROBE) | 2639 | if (((1 << debug) - 1) & NETIF_MSG_PROBE) |
2640 | printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); | 2640 | printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); |
2641 | return -ENOMEM; | 2641 | return -ENOMEM; |
2642 | } | 2642 | } |
@@ -2653,24 +2653,24 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2653 | nic->msg_enable = (1 << debug) - 1; | 2653 | nic->msg_enable = (1 << debug) - 1; |
2654 | pci_set_drvdata(pdev, netdev); | 2654 | pci_set_drvdata(pdev, netdev); |
2655 | 2655 | ||
2656 | if((err = pci_enable_device(pdev))) { | 2656 | if ((err = pci_enable_device(pdev))) { |
2657 | DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); | 2657 | DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); |
2658 | goto err_out_free_dev; | 2658 | goto err_out_free_dev; |
2659 | } | 2659 | } |
2660 | 2660 | ||
2661 | if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { | 2661 | if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { |
2662 | DPRINTK(PROBE, ERR, "Cannot find proper PCI device " | 2662 | DPRINTK(PROBE, ERR, "Cannot find proper PCI device " |
2663 | "base address, aborting.\n"); | 2663 | "base address, aborting.\n"); |
2664 | err = -ENODEV; | 2664 | err = -ENODEV; |
2665 | goto err_out_disable_pdev; | 2665 | goto err_out_disable_pdev; |
2666 | } | 2666 | } |
2667 | 2667 | ||
2668 | if((err = pci_request_regions(pdev, DRV_NAME))) { | 2668 | if ((err = pci_request_regions(pdev, DRV_NAME))) { |
2669 | DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); | 2669 | DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); |
2670 | goto err_out_disable_pdev; | 2670 | goto err_out_disable_pdev; |
2671 | } | 2671 | } |
2672 | 2672 | ||
2673 | if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { | 2673 | if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { |
2674 | DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); | 2674 | DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); |
2675 | goto err_out_free_res; | 2675 | goto err_out_free_res; |
2676 | } | 2676 | } |
@@ -2681,13 +2681,13 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2681 | DPRINTK(PROBE, INFO, "using i/o access mode\n"); | 2681 | DPRINTK(PROBE, INFO, "using i/o access mode\n"); |
2682 | 2682 | ||
2683 | nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); | 2683 | nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr)); |
2684 | if(!nic->csr) { | 2684 | if (!nic->csr) { |
2685 | DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); | 2685 | DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); |
2686 | err = -ENOMEM; | 2686 | err = -ENOMEM; |
2687 | goto err_out_free_res; | 2687 | goto err_out_free_res; |
2688 | } | 2688 | } |
2689 | 2689 | ||
2690 | if(ent->driver_data) | 2690 | if (ent->driver_data) |
2691 | nic->flags |= ich; | 2691 | nic->flags |= ich; |
2692 | else | 2692 | else |
2693 | nic->flags &= ~ich; | 2693 | nic->flags &= ~ich; |
@@ -2715,12 +2715,12 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2715 | 2715 | ||
2716 | INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); | 2716 | INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task); |
2717 | 2717 | ||
2718 | if((err = e100_alloc(nic))) { | 2718 | if ((err = e100_alloc(nic))) { |
2719 | DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); | 2719 | DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); |
2720 | goto err_out_iounmap; | 2720 | goto err_out_iounmap; |
2721 | } | 2721 | } |
2722 | 2722 | ||
2723 | if((err = e100_eeprom_load(nic))) | 2723 | if ((err = e100_eeprom_load(nic))) |
2724 | goto err_out_free; | 2724 | goto err_out_free; |
2725 | 2725 | ||
2726 | e100_phy_init(nic); | 2726 | e100_phy_init(nic); |
@@ -2740,7 +2740,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2740 | } | 2740 | } |
2741 | 2741 | ||
2742 | /* Wol magic packet can be enabled from eeprom */ | 2742 | /* Wol magic packet can be enabled from eeprom */ |
2743 | if((nic->mac >= mac_82558_D101_A4) && | 2743 | if ((nic->mac >= mac_82558_D101_A4) && |
2744 | (nic->eeprom[eeprom_id] & eeprom_id_wol)) { | 2744 | (nic->eeprom[eeprom_id] & eeprom_id_wol)) { |
2745 | nic->flags |= wol_magic; | 2745 | nic->flags |= wol_magic; |
2746 | device_set_wakeup_enable(&pdev->dev, true); | 2746 | device_set_wakeup_enable(&pdev->dev, true); |
@@ -2750,7 +2750,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2750 | pci_pme_active(pdev, false); | 2750 | pci_pme_active(pdev, false); |
2751 | 2751 | ||
2752 | strcpy(netdev->name, "eth%d"); | 2752 | strcpy(netdev->name, "eth%d"); |
2753 | if((err = register_netdev(netdev))) { | 2753 | if ((err = register_netdev(netdev))) { |
2754 | DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); | 2754 | DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); |
2755 | goto err_out_free; | 2755 | goto err_out_free; |
2756 | } | 2756 | } |
@@ -2779,7 +2779,7 @@ static void __devexit e100_remove(struct pci_dev *pdev) | |||
2779 | { | 2779 | { |
2780 | struct net_device *netdev = pci_get_drvdata(pdev); | 2780 | struct net_device *netdev = pci_get_drvdata(pdev); |
2781 | 2781 | ||
2782 | if(netdev) { | 2782 | if (netdev) { |
2783 | struct nic *nic = netdev_priv(netdev); | 2783 | struct nic *nic = netdev_priv(netdev); |
2784 | unregister_netdev(netdev); | 2784 | unregister_netdev(netdev); |
2785 | e100_free(nic); | 2785 | e100_free(nic); |
@@ -2932,7 +2932,7 @@ static struct pci_driver e100_driver = { | |||
2932 | 2932 | ||
2933 | static int __init e100_init_module(void) | 2933 | static int __init e100_init_module(void) |
2934 | { | 2934 | { |
2935 | if(((1 << debug) - 1) & NETIF_MSG_DRV) { | 2935 | if (((1 << debug) - 1) & NETIF_MSG_DRV) { |
2936 | printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); | 2936 | printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); |
2937 | printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); | 2937 | printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); |
2938 | } | 2938 | } |
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 9930d5f8b9e1..6271b9411ccf 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h | |||
@@ -478,7 +478,7 @@ struct ehea_port { | |||
478 | int num_add_tx_qps; | 478 | int num_add_tx_qps; |
479 | int num_mcs; | 479 | int num_mcs; |
480 | int resets; | 480 | int resets; |
481 | u64 flags; | 481 | unsigned long flags; |
482 | u64 mac_addr; | 482 | u64 mac_addr; |
483 | u32 logical_port_id; | 483 | u32 logical_port_id; |
484 | u32 port_speed; | 484 | u32 port_speed; |
@@ -510,7 +510,6 @@ void ehea_set_ethtool_ops(struct net_device *netdev); | |||
510 | int ehea_sense_port_attr(struct ehea_port *port); | 510 | int ehea_sense_port_attr(struct ehea_port *port); |
511 | int ehea_set_portspeed(struct ehea_port *port, u32 port_speed); | 511 | int ehea_set_portspeed(struct ehea_port *port, u32 port_speed); |
512 | 512 | ||
513 | extern u64 ehea_driver_flags; | ||
514 | extern struct work_struct ehea_rereg_mr_task; | 513 | extern struct work_struct ehea_rereg_mr_task; |
515 | 514 | ||
516 | #endif /* __EHEA_H__ */ | 515 | #endif /* __EHEA_H__ */ |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index a2f1905a23df..e3131ea629cd 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -99,7 +99,7 @@ MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, " | |||
99 | 99 | ||
100 | static int port_name_cnt; | 100 | static int port_name_cnt; |
101 | static LIST_HEAD(adapter_list); | 101 | static LIST_HEAD(adapter_list); |
102 | u64 ehea_driver_flags; | 102 | static unsigned long ehea_driver_flags; |
103 | struct work_struct ehea_rereg_mr_task; | 103 | struct work_struct ehea_rereg_mr_task; |
104 | static DEFINE_MUTEX(dlpar_mem_lock); | 104 | static DEFINE_MUTEX(dlpar_mem_lock); |
105 | struct ehea_fw_handle_array ehea_fw_handles; | 105 | struct ehea_fw_handle_array ehea_fw_handles; |
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index b0ef46c51a9d..cefe1d98f93e 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c | |||
@@ -944,7 +944,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) | |||
944 | if (netif_msg_rx_status(priv)) | 944 | if (netif_msg_rx_status(priv)) |
945 | enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat); | 945 | enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat); |
946 | 946 | ||
947 | if (!RSV_GETBIT(rxstat, RSV_RXOK)) { | 947 | if (!RSV_GETBIT(rxstat, RSV_RXOK) || len > MAX_FRAMELEN) { |
948 | if (netif_msg_rx_err(priv)) | 948 | if (netif_msg_rx_err(priv)) |
949 | dev_err(&ndev->dev, "Rx Error (%04x)\n", rxstat); | 949 | dev_err(&ndev->dev, "Rx Error (%04x)\n", rxstat); |
950 | ndev->stats.rx_errors++; | 950 | ndev->stats.rx_errors++; |
@@ -952,6 +952,8 @@ static void enc28j60_hw_rx(struct net_device *ndev) | |||
952 | ndev->stats.rx_crc_errors++; | 952 | ndev->stats.rx_crc_errors++; |
953 | if (RSV_GETBIT(rxstat, RSV_LENCHECKERR)) | 953 | if (RSV_GETBIT(rxstat, RSV_LENCHECKERR)) |
954 | ndev->stats.rx_frame_errors++; | 954 | ndev->stats.rx_frame_errors++; |
955 | if (len > MAX_FRAMELEN) | ||
956 | ndev->stats.rx_over_errors++; | ||
955 | } else { | 957 | } else { |
956 | skb = dev_alloc_skb(len + NET_IP_ALIGN); | 958 | skb = dev_alloc_skb(len + NET_IP_ALIGN); |
957 | if (!skb) { | 959 | if (!skb) { |
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 022794e579c7..b82b0fb2056c 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
@@ -1457,8 +1457,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter) | |||
1457 | 1457 | ||
1458 | /* Number of supported queues. */ | 1458 | /* Number of supported queues. */ |
1459 | /* Having more queues than CPUs doesn't make sense. */ | 1459 | /* Having more queues than CPUs doesn't make sense. */ |
1460 | adapter->num_rx_queues = min((u32)IGB_MAX_RX_QUEUES, (u32)num_online_cpus()); | 1460 | adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus()); |
1461 | adapter->num_tx_queues = min(IGB_MAX_TX_QUEUES, num_online_cpus()); | 1461 | adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus()); |
1462 | 1462 | ||
1463 | /* This call may decrease the number of queues depending on | 1463 | /* This call may decrease the number of queues depending on |
1464 | * interrupt mode. */ | 1464 | * interrupt mode. */ |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5e70180bf569..6bb71b687f7b 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -75,7 +75,7 @@ | |||
75 | #include "myri10ge_mcp.h" | 75 | #include "myri10ge_mcp.h" |
76 | #include "myri10ge_mcp_gen_header.h" | 76 | #include "myri10ge_mcp_gen_header.h" |
77 | 77 | ||
78 | #define MYRI10GE_VERSION_STR "1.4.4-1.395" | 78 | #define MYRI10GE_VERSION_STR "1.4.4-1.398" |
79 | 79 | ||
80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); | 80 | MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); |
81 | MODULE_AUTHOR("Maintainer: help@myri.com"); | 81 | MODULE_AUTHOR("Maintainer: help@myri.com"); |
@@ -3929,6 +3929,10 @@ abort_with_firmware: | |||
3929 | myri10ge_dummy_rdma(mgp, 0); | 3929 | myri10ge_dummy_rdma(mgp, 0); |
3930 | 3930 | ||
3931 | abort_with_ioremap: | 3931 | abort_with_ioremap: |
3932 | if (mgp->mac_addr_string != NULL) | ||
3933 | dev_err(&pdev->dev, | ||
3934 | "myri10ge_probe() failed: MAC=%s, SN=%ld\n", | ||
3935 | mgp->mac_addr_string, mgp->serial_number); | ||
3932 | iounmap(mgp->sram); | 3936 | iounmap(mgp->sram); |
3933 | 3937 | ||
3934 | abort_with_mtrr: | 3938 | abort_with_mtrr: |
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index ba2e1c5b6bcf..459663a4023d 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -818,15 +818,6 @@ struct tx_doorbell_context { | |||
818 | }; | 818 | }; |
819 | 819 | ||
820 | /* DATA STRUCTURES SHARED WITH HARDWARE. */ | 820 | /* DATA STRUCTURES SHARED WITH HARDWARE. */ |
821 | |||
822 | struct bq_element { | ||
823 | u32 addr_lo; | ||
824 | #define BQ_END 0x00000001 | ||
825 | #define BQ_CONT 0x00000002 | ||
826 | #define BQ_MASK 0x00000003 | ||
827 | u32 addr_hi; | ||
828 | } __attribute((packed)); | ||
829 | |||
830 | struct tx_buf_desc { | 821 | struct tx_buf_desc { |
831 | __le64 addr; | 822 | __le64 addr; |
832 | __le32 len; | 823 | __le32 len; |
@@ -860,8 +851,8 @@ struct ob_mac_iocb_req { | |||
860 | __le16 frame_len; | 851 | __le16 frame_len; |
861 | #define OB_MAC_IOCB_LEN_MASK 0x3ffff | 852 | #define OB_MAC_IOCB_LEN_MASK 0x3ffff |
862 | __le16 reserved2; | 853 | __le16 reserved2; |
863 | __le32 tid; | 854 | u32 tid; |
864 | __le32 txq_idx; | 855 | u32 txq_idx; |
865 | __le32 reserved3; | 856 | __le32 reserved3; |
866 | __le16 vlan_tci; | 857 | __le16 vlan_tci; |
867 | __le16 reserved4; | 858 | __le16 reserved4; |
@@ -880,8 +871,8 @@ struct ob_mac_iocb_rsp { | |||
880 | u8 flags2; /* */ | 871 | u8 flags2; /* */ |
881 | u8 flags3; /* */ | 872 | u8 flags3; /* */ |
882 | #define OB_MAC_IOCB_RSP_B 0x80 /* */ | 873 | #define OB_MAC_IOCB_RSP_B 0x80 /* */ |
883 | __le32 tid; | 874 | u32 tid; |
884 | __le32 txq_idx; | 875 | u32 txq_idx; |
885 | __le32 reserved[13]; | 876 | __le32 reserved[13]; |
886 | } __attribute((packed)); | 877 | } __attribute((packed)); |
887 | 878 | ||
@@ -903,8 +894,8 @@ struct ob_mac_tso_iocb_req { | |||
903 | #define OB_MAC_TSO_IOCB_V 0x04 | 894 | #define OB_MAC_TSO_IOCB_V 0x04 |
904 | __le32 reserved1[2]; | 895 | __le32 reserved1[2]; |
905 | __le32 frame_len; | 896 | __le32 frame_len; |
906 | __le32 tid; | 897 | u32 tid; |
907 | __le32 txq_idx; | 898 | u32 txq_idx; |
908 | __le16 total_hdrs_len; | 899 | __le16 total_hdrs_len; |
909 | __le16 net_trans_offset; | 900 | __le16 net_trans_offset; |
910 | #define OB_MAC_TRANSPORT_HDR_SHIFT 6 | 901 | #define OB_MAC_TRANSPORT_HDR_SHIFT 6 |
@@ -925,8 +916,8 @@ struct ob_mac_tso_iocb_rsp { | |||
925 | u8 flags2; /* */ | 916 | u8 flags2; /* */ |
926 | u8 flags3; /* */ | 917 | u8 flags3; /* */ |
927 | #define OB_MAC_TSO_IOCB_RSP_B 0x8000 | 918 | #define OB_MAC_TSO_IOCB_RSP_B 0x8000 |
928 | __le32 tid; | 919 | u32 tid; |
929 | __le32 txq_idx; | 920 | u32 txq_idx; |
930 | __le32 reserved2[13]; | 921 | __le32 reserved2[13]; |
931 | } __attribute((packed)); | 922 | } __attribute((packed)); |
932 | 923 | ||
@@ -979,10 +970,11 @@ struct ib_mac_iocb_rsp { | |||
979 | 970 | ||
980 | __le16 reserved1; | 971 | __le16 reserved1; |
981 | __le32 reserved2[6]; | 972 | __le32 reserved2[6]; |
982 | __le32 flags4; | 973 | u8 reserved3[3]; |
983 | #define IB_MAC_IOCB_RSP_HV 0x20000000 /* */ | 974 | u8 flags4; |
984 | #define IB_MAC_IOCB_RSP_HS 0x40000000 /* */ | 975 | #define IB_MAC_IOCB_RSP_HV 0x20 |
985 | #define IB_MAC_IOCB_RSP_HL 0x80000000 /* */ | 976 | #define IB_MAC_IOCB_RSP_HS 0x40 |
977 | #define IB_MAC_IOCB_RSP_HL 0x80 | ||
986 | __le32 hdr_len; /* */ | 978 | __le32 hdr_len; /* */ |
987 | __le32 hdr_addr_lo; /* */ | 979 | __le32 hdr_addr_lo; /* */ |
988 | __le32 hdr_addr_hi; /* */ | 980 | __le32 hdr_addr_hi; /* */ |
@@ -1126,7 +1118,7 @@ struct map_list { | |||
1126 | struct tx_ring_desc { | 1118 | struct tx_ring_desc { |
1127 | struct sk_buff *skb; | 1119 | struct sk_buff *skb; |
1128 | struct ob_mac_iocb_req *queue_entry; | 1120 | struct ob_mac_iocb_req *queue_entry; |
1129 | int index; | 1121 | u32 index; |
1130 | struct oal oal; | 1122 | struct oal oal; |
1131 | struct map_list map[MAX_SKB_FRAGS + 1]; | 1123 | struct map_list map[MAX_SKB_FRAGS + 1]; |
1132 | int map_cnt; | 1124 | int map_cnt; |
@@ -1138,8 +1130,8 @@ struct bq_desc { | |||
1138 | struct page *lbq_page; | 1130 | struct page *lbq_page; |
1139 | struct sk_buff *skb; | 1131 | struct sk_buff *skb; |
1140 | } p; | 1132 | } p; |
1141 | struct bq_element *bq; | 1133 | __le64 *addr; |
1142 | int index; | 1134 | u32 index; |
1143 | DECLARE_PCI_UNMAP_ADDR(mapaddr); | 1135 | DECLARE_PCI_UNMAP_ADDR(mapaddr); |
1144 | DECLARE_PCI_UNMAP_LEN(maplen); | 1136 | DECLARE_PCI_UNMAP_LEN(maplen); |
1145 | }; | 1137 | }; |
@@ -1189,7 +1181,7 @@ struct rx_ring { | |||
1189 | u32 cq_size; | 1181 | u32 cq_size; |
1190 | u32 cq_len; | 1182 | u32 cq_len; |
1191 | u16 cq_id; | 1183 | u16 cq_id; |
1192 | u32 *prod_idx_sh_reg; /* Shadowed producer register. */ | 1184 | volatile __le32 *prod_idx_sh_reg; /* Shadowed producer register. */ |
1193 | dma_addr_t prod_idx_sh_reg_dma; | 1185 | dma_addr_t prod_idx_sh_reg_dma; |
1194 | void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */ | 1186 | void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */ |
1195 | u32 cnsmr_idx; /* current sw idx */ | 1187 | u32 cnsmr_idx; /* current sw idx */ |
@@ -1467,21 +1459,6 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr) | |||
1467 | mmiowb(); | 1459 | mmiowb(); |
1468 | } | 1460 | } |
1469 | 1461 | ||
1470 | /* | ||
1471 | * Shadow Registers: | ||
1472 | * Outbound queues have a consumer index that is maintained by the chip. | ||
1473 | * Inbound queues have a producer index that is maintained by the chip. | ||
1474 | * For lower overhead, these registers are "shadowed" to host memory | ||
1475 | * which allows the device driver to track the queue progress without | ||
1476 | * PCI reads. When an entry is placed on an inbound queue, the chip will | ||
1477 | * update the relevant index register and then copy the value to the | ||
1478 | * shadow register in host memory. | ||
1479 | */ | ||
1480 | static inline unsigned int ql_read_sh_reg(const volatile void *addr) | ||
1481 | { | ||
1482 | return *(volatile unsigned int __force *)addr; | ||
1483 | } | ||
1484 | |||
1485 | extern char qlge_driver_name[]; | 1462 | extern char qlge_driver_name[]; |
1486 | extern const char qlge_driver_version[]; | 1463 | extern const char qlge_driver_version[]; |
1487 | extern const struct ethtool_ops qlge_ethtool_ops; | 1464 | extern const struct ethtool_ops qlge_ethtool_ops; |
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c index 47df304a02c8..3f5e02d2e4a9 100644 --- a/drivers/net/qlge/qlge_dbg.c +++ b/drivers/net/qlge/qlge_dbg.c | |||
@@ -821,14 +821,11 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp) | |||
821 | le16_to_cpu(ib_mac_rsp->vlan_id)); | 821 | le16_to_cpu(ib_mac_rsp->vlan_id)); |
822 | 822 | ||
823 | printk(KERN_ERR PFX "flags4 = %s%s%s.\n", | 823 | printk(KERN_ERR PFX "flags4 = %s%s%s.\n", |
824 | le32_to_cpu(ib_mac_rsp-> | 824 | ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "", |
825 | flags4) & IB_MAC_IOCB_RSP_HV ? "HV " : "", | 825 | ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS ? "HS " : "", |
826 | le32_to_cpu(ib_mac_rsp-> | 826 | ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HL ? "HL " : ""); |
827 | flags4) & IB_MAC_IOCB_RSP_HS ? "HS " : "", | 827 | |
828 | le32_to_cpu(ib_mac_rsp-> | 828 | if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { |
829 | flags4) & IB_MAC_IOCB_RSP_HL ? "HL " : ""); | ||
830 | |||
831 | if (le32_to_cpu(ib_mac_rsp->flags4) & IB_MAC_IOCB_RSP_HV) { | ||
832 | printk(KERN_ERR PFX "hdr length = %d.\n", | 829 | printk(KERN_ERR PFX "hdr length = %d.\n", |
833 | le32_to_cpu(ib_mac_rsp->hdr_len)); | 830 | le32_to_cpu(ib_mac_rsp->hdr_len)); |
834 | printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n", | 831 | printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n", |
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c index eefb81b13758..9d922e2ff226 100644 --- a/drivers/net/qlge/qlge_ethtool.c +++ b/drivers/net/qlge/qlge_ethtool.c | |||
@@ -56,9 +56,9 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) | |||
56 | for (i = 1; i < qdev->rss_ring_first_cq_id; i++, rx_ring++) { | 56 | for (i = 1; i < qdev->rss_ring_first_cq_id; i++, rx_ring++) { |
57 | rx_ring = &qdev->rx_ring[i]; | 57 | rx_ring = &qdev->rx_ring[i]; |
58 | cqicb = (struct cqicb *)rx_ring; | 58 | cqicb = (struct cqicb *)rx_ring; |
59 | cqicb->irq_delay = le16_to_cpu(qdev->tx_coalesce_usecs); | 59 | cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs); |
60 | cqicb->pkt_delay = | 60 | cqicb->pkt_delay = |
61 | le16_to_cpu(qdev->tx_max_coalesced_frames); | 61 | cpu_to_le16(qdev->tx_max_coalesced_frames); |
62 | cqicb->flags = FLAGS_LI; | 62 | cqicb->flags = FLAGS_LI; |
63 | status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), | 63 | status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), |
64 | CFG_LCQ, rx_ring->cq_id); | 64 | CFG_LCQ, rx_ring->cq_id); |
@@ -79,9 +79,9 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) | |||
79 | i++) { | 79 | i++) { |
80 | rx_ring = &qdev->rx_ring[i]; | 80 | rx_ring = &qdev->rx_ring[i]; |
81 | cqicb = (struct cqicb *)rx_ring; | 81 | cqicb = (struct cqicb *)rx_ring; |
82 | cqicb->irq_delay = le16_to_cpu(qdev->rx_coalesce_usecs); | 82 | cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs); |
83 | cqicb->pkt_delay = | 83 | cqicb->pkt_delay = |
84 | le16_to_cpu(qdev->rx_max_coalesced_frames); | 84 | cpu_to_le16(qdev->rx_max_coalesced_frames); |
85 | cqicb->flags = FLAGS_LI; | 85 | cqicb->flags = FLAGS_LI; |
86 | status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), | 86 | status = ql_write_cfg(qdev, cqicb, sizeof(cqicb), |
87 | CFG_LCQ, rx_ring->cq_id); | 87 | CFG_LCQ, rx_ring->cq_id); |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 718a7bd0cd1a..f4c016012f18 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -257,7 +257,7 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, | |||
257 | { | 257 | { |
258 | status = | 258 | status = |
259 | ql_wait_reg_rdy(qdev, | 259 | ql_wait_reg_rdy(qdev, |
260 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 260 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
261 | if (status) | 261 | if (status) |
262 | goto exit; | 262 | goto exit; |
263 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ | 263 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ |
@@ -265,13 +265,13 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, | |||
265 | MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ | 265 | MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ |
266 | status = | 266 | status = |
267 | ql_wait_reg_rdy(qdev, | 267 | ql_wait_reg_rdy(qdev, |
268 | MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E); | 268 | MAC_ADDR_IDX, MAC_ADDR_MR, 0); |
269 | if (status) | 269 | if (status) |
270 | goto exit; | 270 | goto exit; |
271 | *value++ = ql_read32(qdev, MAC_ADDR_DATA); | 271 | *value++ = ql_read32(qdev, MAC_ADDR_DATA); |
272 | status = | 272 | status = |
273 | ql_wait_reg_rdy(qdev, | 273 | ql_wait_reg_rdy(qdev, |
274 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 274 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
275 | if (status) | 275 | if (status) |
276 | goto exit; | 276 | goto exit; |
277 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ | 277 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ |
@@ -279,14 +279,14 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, | |||
279 | MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ | 279 | MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ |
280 | status = | 280 | status = |
281 | ql_wait_reg_rdy(qdev, | 281 | ql_wait_reg_rdy(qdev, |
282 | MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E); | 282 | MAC_ADDR_IDX, MAC_ADDR_MR, 0); |
283 | if (status) | 283 | if (status) |
284 | goto exit; | 284 | goto exit; |
285 | *value++ = ql_read32(qdev, MAC_ADDR_DATA); | 285 | *value++ = ql_read32(qdev, MAC_ADDR_DATA); |
286 | if (type == MAC_ADDR_TYPE_CAM_MAC) { | 286 | if (type == MAC_ADDR_TYPE_CAM_MAC) { |
287 | status = | 287 | status = |
288 | ql_wait_reg_rdy(qdev, | 288 | ql_wait_reg_rdy(qdev, |
289 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 289 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
290 | if (status) | 290 | if (status) |
291 | goto exit; | 291 | goto exit; |
292 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ | 292 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ |
@@ -294,7 +294,7 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, | |||
294 | MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ | 294 | MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */ |
295 | status = | 295 | status = |
296 | ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, | 296 | ql_wait_reg_rdy(qdev, MAC_ADDR_IDX, |
297 | MAC_ADDR_MR, MAC_ADDR_E); | 297 | MAC_ADDR_MR, 0); |
298 | if (status) | 298 | if (status) |
299 | goto exit; | 299 | goto exit; |
300 | *value++ = ql_read32(qdev, MAC_ADDR_DATA); | 300 | *value++ = ql_read32(qdev, MAC_ADDR_DATA); |
@@ -344,7 +344,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, | |||
344 | 344 | ||
345 | status = | 345 | status = |
346 | ql_wait_reg_rdy(qdev, | 346 | ql_wait_reg_rdy(qdev, |
347 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 347 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
348 | if (status) | 348 | if (status) |
349 | goto exit; | 349 | goto exit; |
350 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ | 350 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ |
@@ -353,7 +353,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, | |||
353 | ql_write32(qdev, MAC_ADDR_DATA, lower); | 353 | ql_write32(qdev, MAC_ADDR_DATA, lower); |
354 | status = | 354 | status = |
355 | ql_wait_reg_rdy(qdev, | 355 | ql_wait_reg_rdy(qdev, |
356 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 356 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
357 | if (status) | 357 | if (status) |
358 | goto exit; | 358 | goto exit; |
359 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ | 359 | ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */ |
@@ -362,7 +362,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, | |||
362 | ql_write32(qdev, MAC_ADDR_DATA, upper); | 362 | ql_write32(qdev, MAC_ADDR_DATA, upper); |
363 | status = | 363 | status = |
364 | ql_wait_reg_rdy(qdev, | 364 | ql_wait_reg_rdy(qdev, |
365 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 365 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
366 | if (status) | 366 | if (status) |
367 | goto exit; | 367 | goto exit; |
368 | ql_write32(qdev, MAC_ADDR_IDX, (offset) | /* offset */ | 368 | ql_write32(qdev, MAC_ADDR_IDX, (offset) | /* offset */ |
@@ -400,7 +400,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, | |||
400 | 400 | ||
401 | status = | 401 | status = |
402 | ql_wait_reg_rdy(qdev, | 402 | ql_wait_reg_rdy(qdev, |
403 | MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E); | 403 | MAC_ADDR_IDX, MAC_ADDR_MW, 0); |
404 | if (status) | 404 | if (status) |
405 | goto exit; | 405 | goto exit; |
406 | ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */ | 406 | ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */ |
@@ -431,13 +431,13 @@ int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value) | |||
431 | if (status) | 431 | if (status) |
432 | goto exit; | 432 | goto exit; |
433 | 433 | ||
434 | status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, RT_IDX_E); | 434 | status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0); |
435 | if (status) | 435 | if (status) |
436 | goto exit; | 436 | goto exit; |
437 | 437 | ||
438 | ql_write32(qdev, RT_IDX, | 438 | ql_write32(qdev, RT_IDX, |
439 | RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT)); | 439 | RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT)); |
440 | status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, RT_IDX_E); | 440 | status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, 0); |
441 | if (status) | 441 | if (status) |
442 | goto exit; | 442 | goto exit; |
443 | *value = ql_read32(qdev, RT_DATA); | 443 | *value = ql_read32(qdev, RT_DATA); |
@@ -874,7 +874,6 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
874 | { | 874 | { |
875 | int clean_idx = rx_ring->lbq_clean_idx; | 875 | int clean_idx = rx_ring->lbq_clean_idx; |
876 | struct bq_desc *lbq_desc; | 876 | struct bq_desc *lbq_desc; |
877 | struct bq_element *bq; | ||
878 | u64 map; | 877 | u64 map; |
879 | int i; | 878 | int i; |
880 | 879 | ||
@@ -884,7 +883,6 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
884 | "lbq: try cleaning clean_idx = %d.\n", | 883 | "lbq: try cleaning clean_idx = %d.\n", |
885 | clean_idx); | 884 | clean_idx); |
886 | lbq_desc = &rx_ring->lbq[clean_idx]; | 885 | lbq_desc = &rx_ring->lbq[clean_idx]; |
887 | bq = lbq_desc->bq; | ||
888 | if (lbq_desc->p.lbq_page == NULL) { | 886 | if (lbq_desc->p.lbq_page == NULL) { |
889 | QPRINTK(qdev, RX_STATUS, DEBUG, | 887 | QPRINTK(qdev, RX_STATUS, DEBUG, |
890 | "lbq: getting new page for index %d.\n", | 888 | "lbq: getting new page for index %d.\n", |
@@ -906,10 +904,7 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
906 | } | 904 | } |
907 | pci_unmap_addr_set(lbq_desc, mapaddr, map); | 905 | pci_unmap_addr_set(lbq_desc, mapaddr, map); |
908 | pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE); | 906 | pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE); |
909 | bq->addr_lo = /*lbq_desc->addr_lo = */ | 907 | *lbq_desc->addr = cpu_to_le64(map); |
910 | cpu_to_le32(map); | ||
911 | bq->addr_hi = /*lbq_desc->addr_hi = */ | ||
912 | cpu_to_le32(map >> 32); | ||
913 | } | 908 | } |
914 | clean_idx++; | 909 | clean_idx++; |
915 | if (clean_idx == rx_ring->lbq_len) | 910 | if (clean_idx == rx_ring->lbq_len) |
@@ -934,7 +929,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
934 | { | 929 | { |
935 | int clean_idx = rx_ring->sbq_clean_idx; | 930 | int clean_idx = rx_ring->sbq_clean_idx; |
936 | struct bq_desc *sbq_desc; | 931 | struct bq_desc *sbq_desc; |
937 | struct bq_element *bq; | ||
938 | u64 map; | 932 | u64 map; |
939 | int i; | 933 | int i; |
940 | 934 | ||
@@ -944,7 +938,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
944 | QPRINTK(qdev, RX_STATUS, DEBUG, | 938 | QPRINTK(qdev, RX_STATUS, DEBUG, |
945 | "sbq: try cleaning clean_idx = %d.\n", | 939 | "sbq: try cleaning clean_idx = %d.\n", |
946 | clean_idx); | 940 | clean_idx); |
947 | bq = sbq_desc->bq; | ||
948 | if (sbq_desc->p.skb == NULL) { | 941 | if (sbq_desc->p.skb == NULL) { |
949 | QPRINTK(qdev, RX_STATUS, DEBUG, | 942 | QPRINTK(qdev, RX_STATUS, DEBUG, |
950 | "sbq: getting new skb for index %d.\n", | 943 | "sbq: getting new skb for index %d.\n", |
@@ -963,11 +956,15 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
963 | sbq_desc->p.skb->data, | 956 | sbq_desc->p.skb->data, |
964 | rx_ring->sbq_buf_size / | 957 | rx_ring->sbq_buf_size / |
965 | 2, PCI_DMA_FROMDEVICE); | 958 | 2, PCI_DMA_FROMDEVICE); |
959 | if (pci_dma_mapping_error(qdev->pdev, map)) { | ||
960 | QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n"); | ||
961 | rx_ring->sbq_clean_idx = clean_idx; | ||
962 | return; | ||
963 | } | ||
966 | pci_unmap_addr_set(sbq_desc, mapaddr, map); | 964 | pci_unmap_addr_set(sbq_desc, mapaddr, map); |
967 | pci_unmap_len_set(sbq_desc, maplen, | 965 | pci_unmap_len_set(sbq_desc, maplen, |
968 | rx_ring->sbq_buf_size / 2); | 966 | rx_ring->sbq_buf_size / 2); |
969 | bq->addr_lo = cpu_to_le32(map); | 967 | *sbq_desc->addr = cpu_to_le64(map); |
970 | bq->addr_hi = cpu_to_le32(map >> 32); | ||
971 | } | 968 | } |
972 | 969 | ||
973 | clean_idx++; | 970 | clean_idx++; |
@@ -1303,6 +1300,11 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, | |||
1303 | "No skb available, drop the packet.\n"); | 1300 | "No skb available, drop the packet.\n"); |
1304 | return NULL; | 1301 | return NULL; |
1305 | } | 1302 | } |
1303 | pci_unmap_page(qdev->pdev, | ||
1304 | pci_unmap_addr(lbq_desc, | ||
1305 | mapaddr), | ||
1306 | pci_unmap_len(lbq_desc, maplen), | ||
1307 | PCI_DMA_FROMDEVICE); | ||
1306 | skb_reserve(skb, NET_IP_ALIGN); | 1308 | skb_reserve(skb, NET_IP_ALIGN); |
1307 | QPRINTK(qdev, RX_STATUS, DEBUG, | 1309 | QPRINTK(qdev, RX_STATUS, DEBUG, |
1308 | "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); | 1310 | "%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length); |
@@ -1330,7 +1332,7 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, | |||
1330 | * eventually be in trouble. | 1332 | * eventually be in trouble. |
1331 | */ | 1333 | */ |
1332 | int size, offset, i = 0; | 1334 | int size, offset, i = 0; |
1333 | struct bq_element *bq, bq_array[8]; | 1335 | __le64 *bq, bq_array[8]; |
1334 | sbq_desc = ql_get_curr_sbuf(rx_ring); | 1336 | sbq_desc = ql_get_curr_sbuf(rx_ring); |
1335 | pci_unmap_single(qdev->pdev, | 1337 | pci_unmap_single(qdev->pdev, |
1336 | pci_unmap_addr(sbq_desc, mapaddr), | 1338 | pci_unmap_addr(sbq_desc, mapaddr), |
@@ -1356,16 +1358,10 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev, | |||
1356 | } else { | 1358 | } else { |
1357 | QPRINTK(qdev, RX_STATUS, DEBUG, | 1359 | QPRINTK(qdev, RX_STATUS, DEBUG, |
1358 | "Headers in small, %d bytes of data in chain of large.\n", length); | 1360 | "Headers in small, %d bytes of data in chain of large.\n", length); |
1359 | bq = (struct bq_element *)sbq_desc->p.skb->data; | 1361 | bq = (__le64 *)sbq_desc->p.skb->data; |
1360 | } | 1362 | } |
1361 | while (length > 0) { | 1363 | while (length > 0) { |
1362 | lbq_desc = ql_get_curr_lbuf(rx_ring); | 1364 | lbq_desc = ql_get_curr_lbuf(rx_ring); |
1363 | if ((bq->addr_lo & ~BQ_MASK) != lbq_desc->bq->addr_lo) { | ||
1364 | QPRINTK(qdev, RX_STATUS, ERR, | ||
1365 | "Panic!!! bad large buffer address, expected 0x%.08x, got 0x%.08x.\n", | ||
1366 | lbq_desc->bq->addr_lo, bq->addr_lo); | ||
1367 | return NULL; | ||
1368 | } | ||
1369 | pci_unmap_page(qdev->pdev, | 1365 | pci_unmap_page(qdev->pdev, |
1370 | pci_unmap_addr(lbq_desc, | 1366 | pci_unmap_addr(lbq_desc, |
1371 | mapaddr), | 1367 | mapaddr), |
@@ -1549,7 +1545,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev, | |||
1549 | static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) | 1545 | static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) |
1550 | { | 1546 | { |
1551 | struct ql_adapter *qdev = rx_ring->qdev; | 1547 | struct ql_adapter *qdev = rx_ring->qdev; |
1552 | u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); | 1548 | u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); |
1553 | struct ob_mac_iocb_rsp *net_rsp = NULL; | 1549 | struct ob_mac_iocb_rsp *net_rsp = NULL; |
1554 | int count = 0; | 1550 | int count = 0; |
1555 | 1551 | ||
@@ -1575,7 +1571,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) | |||
1575 | } | 1571 | } |
1576 | count++; | 1572 | count++; |
1577 | ql_update_cq(rx_ring); | 1573 | ql_update_cq(rx_ring); |
1578 | prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); | 1574 | prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); |
1579 | } | 1575 | } |
1580 | ql_write_cq_idx(rx_ring); | 1576 | ql_write_cq_idx(rx_ring); |
1581 | if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { | 1577 | if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { |
@@ -1595,7 +1591,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) | |||
1595 | static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) | 1591 | static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) |
1596 | { | 1592 | { |
1597 | struct ql_adapter *qdev = rx_ring->qdev; | 1593 | struct ql_adapter *qdev = rx_ring->qdev; |
1598 | u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); | 1594 | u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); |
1599 | struct ql_net_rsp_iocb *net_rsp; | 1595 | struct ql_net_rsp_iocb *net_rsp; |
1600 | int count = 0; | 1596 | int count = 0; |
1601 | 1597 | ||
@@ -1628,7 +1624,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) | |||
1628 | } | 1624 | } |
1629 | count++; | 1625 | count++; |
1630 | ql_update_cq(rx_ring); | 1626 | ql_update_cq(rx_ring); |
1631 | prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); | 1627 | prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg); |
1632 | if (count == budget) | 1628 | if (count == budget) |
1633 | break; | 1629 | break; |
1634 | } | 1630 | } |
@@ -1791,7 +1787,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) | |||
1791 | * Check the default queue and wake handler if active. | 1787 | * Check the default queue and wake handler if active. |
1792 | */ | 1788 | */ |
1793 | rx_ring = &qdev->rx_ring[0]; | 1789 | rx_ring = &qdev->rx_ring[0]; |
1794 | if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { | 1790 | if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { |
1795 | QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n"); | 1791 | QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n"); |
1796 | ql_disable_completion_interrupt(qdev, intr_context->intr); | 1792 | ql_disable_completion_interrupt(qdev, intr_context->intr); |
1797 | queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue, | 1793 | queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue, |
@@ -1805,7 +1801,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) | |||
1805 | */ | 1801 | */ |
1806 | for (i = 1; i < qdev->rx_ring_count; i++) { | 1802 | for (i = 1; i < qdev->rx_ring_count; i++) { |
1807 | rx_ring = &qdev->rx_ring[i]; | 1803 | rx_ring = &qdev->rx_ring[i]; |
1808 | if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != | 1804 | if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != |
1809 | rx_ring->cnsmr_idx) { | 1805 | rx_ring->cnsmr_idx) { |
1810 | QPRINTK(qdev, INTR, INFO, | 1806 | QPRINTK(qdev, INTR, INFO, |
1811 | "Waking handler for rx_ring[%d].\n", i); | 1807 | "Waking handler for rx_ring[%d].\n", i); |
@@ -1874,7 +1870,7 @@ static void ql_hw_csum_setup(struct sk_buff *skb, | |||
1874 | { | 1870 | { |
1875 | int len; | 1871 | int len; |
1876 | struct iphdr *iph = ip_hdr(skb); | 1872 | struct iphdr *iph = ip_hdr(skb); |
1877 | u16 *check; | 1873 | __sum16 *check; |
1878 | mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB; | 1874 | mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB; |
1879 | mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len); | 1875 | mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len); |
1880 | mac_iocb_ptr->net_trans_offset = | 1876 | mac_iocb_ptr->net_trans_offset = |
@@ -2083,8 +2079,6 @@ static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring | |||
2083 | put_page(lbq_desc->p.lbq_page); | 2079 | put_page(lbq_desc->p.lbq_page); |
2084 | lbq_desc->p.lbq_page = NULL; | 2080 | lbq_desc->p.lbq_page = NULL; |
2085 | } | 2081 | } |
2086 | lbq_desc->bq->addr_lo = 0; | ||
2087 | lbq_desc->bq->addr_hi = 0; | ||
2088 | } | 2082 | } |
2089 | } | 2083 | } |
2090 | 2084 | ||
@@ -2097,12 +2091,12 @@ static int ql_alloc_lbq_buffers(struct ql_adapter *qdev, | |||
2097 | int i; | 2091 | int i; |
2098 | struct bq_desc *lbq_desc; | 2092 | struct bq_desc *lbq_desc; |
2099 | u64 map; | 2093 | u64 map; |
2100 | struct bq_element *bq = rx_ring->lbq_base; | 2094 | __le64 *bq = rx_ring->lbq_base; |
2101 | 2095 | ||
2102 | for (i = 0; i < rx_ring->lbq_len; i++) { | 2096 | for (i = 0; i < rx_ring->lbq_len; i++) { |
2103 | lbq_desc = &rx_ring->lbq[i]; | 2097 | lbq_desc = &rx_ring->lbq[i]; |
2104 | memset(lbq_desc, 0, sizeof(lbq_desc)); | 2098 | memset(lbq_desc, 0, sizeof(lbq_desc)); |
2105 | lbq_desc->bq = bq; | 2099 | lbq_desc->addr = bq; |
2106 | lbq_desc->index = i; | 2100 | lbq_desc->index = i; |
2107 | lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC); | 2101 | lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC); |
2108 | if (unlikely(!lbq_desc->p.lbq_page)) { | 2102 | if (unlikely(!lbq_desc->p.lbq_page)) { |
@@ -2119,8 +2113,7 @@ static int ql_alloc_lbq_buffers(struct ql_adapter *qdev, | |||
2119 | } | 2113 | } |
2120 | pci_unmap_addr_set(lbq_desc, mapaddr, map); | 2114 | pci_unmap_addr_set(lbq_desc, mapaddr, map); |
2121 | pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE); | 2115 | pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE); |
2122 | bq->addr_lo = cpu_to_le32(map); | 2116 | *lbq_desc->addr = cpu_to_le64(map); |
2123 | bq->addr_hi = cpu_to_le32(map >> 32); | ||
2124 | } | 2117 | } |
2125 | bq++; | 2118 | bq++; |
2126 | } | 2119 | } |
@@ -2149,13 +2142,6 @@ static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring | |||
2149 | dev_kfree_skb(sbq_desc->p.skb); | 2142 | dev_kfree_skb(sbq_desc->p.skb); |
2150 | sbq_desc->p.skb = NULL; | 2143 | sbq_desc->p.skb = NULL; |
2151 | } | 2144 | } |
2152 | if (sbq_desc->bq == NULL) { | ||
2153 | QPRINTK(qdev, IFUP, ERR, "sbq_desc->bq %d is NULL.\n", | ||
2154 | i); | ||
2155 | return; | ||
2156 | } | ||
2157 | sbq_desc->bq->addr_lo = 0; | ||
2158 | sbq_desc->bq->addr_hi = 0; | ||
2159 | } | 2145 | } |
2160 | } | 2146 | } |
2161 | 2147 | ||
@@ -2167,13 +2153,13 @@ static int ql_alloc_sbq_buffers(struct ql_adapter *qdev, | |||
2167 | struct bq_desc *sbq_desc; | 2153 | struct bq_desc *sbq_desc; |
2168 | struct sk_buff *skb; | 2154 | struct sk_buff *skb; |
2169 | u64 map; | 2155 | u64 map; |
2170 | struct bq_element *bq = rx_ring->sbq_base; | 2156 | __le64 *bq = rx_ring->sbq_base; |
2171 | 2157 | ||
2172 | for (i = 0; i < rx_ring->sbq_len; i++) { | 2158 | for (i = 0; i < rx_ring->sbq_len; i++) { |
2173 | sbq_desc = &rx_ring->sbq[i]; | 2159 | sbq_desc = &rx_ring->sbq[i]; |
2174 | memset(sbq_desc, 0, sizeof(sbq_desc)); | 2160 | memset(sbq_desc, 0, sizeof(sbq_desc)); |
2175 | sbq_desc->index = i; | 2161 | sbq_desc->index = i; |
2176 | sbq_desc->bq = bq; | 2162 | sbq_desc->addr = bq; |
2177 | skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size); | 2163 | skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size); |
2178 | if (unlikely(!skb)) { | 2164 | if (unlikely(!skb)) { |
2179 | /* Better luck next round */ | 2165 | /* Better luck next round */ |
@@ -2199,10 +2185,7 @@ static int ql_alloc_sbq_buffers(struct ql_adapter *qdev, | |||
2199 | } | 2185 | } |
2200 | pci_unmap_addr_set(sbq_desc, mapaddr, map); | 2186 | pci_unmap_addr_set(sbq_desc, mapaddr, map); |
2201 | pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2); | 2187 | pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2); |
2202 | bq->addr_lo = /*sbq_desc->addr_lo = */ | 2188 | *sbq_desc->addr = cpu_to_le64(map); |
2203 | cpu_to_le32(map); | ||
2204 | bq->addr_hi = /*sbq_desc->addr_hi = */ | ||
2205 | cpu_to_le32(map >> 32); | ||
2206 | bq++; | 2189 | bq++; |
2207 | } | 2190 | } |
2208 | return 0; | 2191 | return 0; |
@@ -2481,7 +2464,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
2481 | memset((void *)cqicb, 0, sizeof(struct cqicb)); | 2464 | memset((void *)cqicb, 0, sizeof(struct cqicb)); |
2482 | cqicb->msix_vect = rx_ring->irq; | 2465 | cqicb->msix_vect = rx_ring->irq; |
2483 | 2466 | ||
2484 | cqicb->len = cpu_to_le16(rx_ring->cq_len | LEN_V | LEN_CPP_CONT); | 2467 | bq_len = (rx_ring->cq_len == 65536) ? 0 : (u16) rx_ring->cq_len; |
2468 | cqicb->len = cpu_to_le16(bq_len | LEN_V | LEN_CPP_CONT); | ||
2485 | 2469 | ||
2486 | cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma); | 2470 | cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma); |
2487 | cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32); | 2471 | cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32); |
@@ -2503,8 +2487,11 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
2503 | cpu_to_le32(rx_ring->lbq_base_indirect_dma); | 2487 | cpu_to_le32(rx_ring->lbq_base_indirect_dma); |
2504 | cqicb->lbq_addr_hi = | 2488 | cqicb->lbq_addr_hi = |
2505 | cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32); | 2489 | cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32); |
2506 | cqicb->lbq_buf_size = cpu_to_le32(rx_ring->lbq_buf_size); | 2490 | bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 : |
2507 | bq_len = (u16) rx_ring->lbq_len; | 2491 | (u16) rx_ring->lbq_buf_size; |
2492 | cqicb->lbq_buf_size = cpu_to_le16(bq_len); | ||
2493 | bq_len = (rx_ring->lbq_len == 65536) ? 0 : | ||
2494 | (u16) rx_ring->lbq_len; | ||
2508 | cqicb->lbq_len = cpu_to_le16(bq_len); | 2495 | cqicb->lbq_len = cpu_to_le16(bq_len); |
2509 | rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16; | 2496 | rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16; |
2510 | rx_ring->lbq_curr_idx = 0; | 2497 | rx_ring->lbq_curr_idx = 0; |
@@ -2520,7 +2507,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) | |||
2520 | cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32); | 2507 | cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32); |
2521 | cqicb->sbq_buf_size = | 2508 | cqicb->sbq_buf_size = |
2522 | cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8); | 2509 | cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8); |
2523 | bq_len = (u16) rx_ring->sbq_len; | 2510 | bq_len = (rx_ring->sbq_len == 65536) ? 0 : |
2511 | (u16) rx_ring->sbq_len; | ||
2524 | cqicb->sbq_len = cpu_to_le16(bq_len); | 2512 | cqicb->sbq_len = cpu_to_le16(bq_len); |
2525 | rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16; | 2513 | rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16; |
2526 | rx_ring->sbq_curr_idx = 0; | 2514 | rx_ring->sbq_curr_idx = 0; |
@@ -3341,11 +3329,11 @@ static int ql_configure_rings(struct ql_adapter *qdev) | |||
3341 | rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); | 3329 | rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); |
3342 | rx_ring->lbq_len = NUM_LARGE_BUFFERS; | 3330 | rx_ring->lbq_len = NUM_LARGE_BUFFERS; |
3343 | rx_ring->lbq_size = | 3331 | rx_ring->lbq_size = |
3344 | rx_ring->lbq_len * sizeof(struct bq_element); | 3332 | rx_ring->lbq_len * sizeof(__le64); |
3345 | rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE; | 3333 | rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE; |
3346 | rx_ring->sbq_len = NUM_SMALL_BUFFERS; | 3334 | rx_ring->sbq_len = NUM_SMALL_BUFFERS; |
3347 | rx_ring->sbq_size = | 3335 | rx_ring->sbq_size = |
3348 | rx_ring->sbq_len * sizeof(struct bq_element); | 3336 | rx_ring->sbq_len * sizeof(__le64); |
3349 | rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2; | 3337 | rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2; |
3350 | rx_ring->type = DEFAULT_Q; | 3338 | rx_ring->type = DEFAULT_Q; |
3351 | } else if (i < qdev->rss_ring_first_cq_id) { | 3339 | } else if (i < qdev->rss_ring_first_cq_id) { |
@@ -3372,11 +3360,11 @@ static int ql_configure_rings(struct ql_adapter *qdev) | |||
3372 | rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); | 3360 | rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb); |
3373 | rx_ring->lbq_len = NUM_LARGE_BUFFERS; | 3361 | rx_ring->lbq_len = NUM_LARGE_BUFFERS; |
3374 | rx_ring->lbq_size = | 3362 | rx_ring->lbq_size = |
3375 | rx_ring->lbq_len * sizeof(struct bq_element); | 3363 | rx_ring->lbq_len * sizeof(__le64); |
3376 | rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE; | 3364 | rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE; |
3377 | rx_ring->sbq_len = NUM_SMALL_BUFFERS; | 3365 | rx_ring->sbq_len = NUM_SMALL_BUFFERS; |
3378 | rx_ring->sbq_size = | 3366 | rx_ring->sbq_size = |
3379 | rx_ring->sbq_len * sizeof(struct bq_element); | 3367 | rx_ring->sbq_len * sizeof(__le64); |
3380 | rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2; | 3368 | rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2; |
3381 | rx_ring->type = RX_Q; | 3369 | rx_ring->type = RX_Q; |
3382 | } | 3370 | } |
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index f54ac2389da2..57fb1f71c47b 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c | |||
@@ -42,11 +42,11 @@ | |||
42 | #include <linux/mii.h> | 42 | #include <linux/mii.h> |
43 | #include <linux/if_vlan.h> | 43 | #include <linux/if_vlan.h> |
44 | #include <linux/mm.h> | 44 | #include <linux/mm.h> |
45 | #include <linux/firmware.h> | ||
45 | #include <asm/processor.h> /* Processor type for cache alignment. */ | 46 | #include <asm/processor.h> /* Processor type for cache alignment. */ |
46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
47 | #include <asm/io.h> | 48 | #include <asm/io.h> |
48 | 49 | ||
49 | #include "starfire_firmware.h" | ||
50 | /* | 50 | /* |
51 | * The current frame processor firmware fails to checksum a fragment | 51 | * The current frame processor firmware fails to checksum a fragment |
52 | * of length 1. If and when this is fixed, the #define below can be removed. | 52 | * of length 1. If and when this is fixed, the #define below can be removed. |
@@ -173,6 +173,10 @@ static int full_duplex[MAX_UNITS] = {0, }; | |||
173 | #define skb_first_frag_len(skb) skb_headlen(skb) | 173 | #define skb_first_frag_len(skb) skb_headlen(skb) |
174 | #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1) | 174 | #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1) |
175 | 175 | ||
176 | /* Firmware names */ | ||
177 | #define FIRMWARE_RX "adaptec/starfire_rx.bin" | ||
178 | #define FIRMWARE_TX "adaptec/starfire_tx.bin" | ||
179 | |||
176 | /* These identify the driver base version and may not be removed. */ | 180 | /* These identify the driver base version and may not be removed. */ |
177 | static char version[] = | 181 | static char version[] = |
178 | KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" | 182 | KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" |
@@ -182,6 +186,8 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>"); | |||
182 | MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); | 186 | MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver"); |
183 | MODULE_LICENSE("GPL"); | 187 | MODULE_LICENSE("GPL"); |
184 | MODULE_VERSION(DRV_VERSION); | 188 | MODULE_VERSION(DRV_VERSION); |
189 | MODULE_FIRMWARE(FIRMWARE_RX); | ||
190 | MODULE_FIRMWARE(FIRMWARE_TX); | ||
185 | 191 | ||
186 | module_param(max_interrupt_work, int, 0); | 192 | module_param(max_interrupt_work, int, 0); |
187 | module_param(mtu, int, 0); | 193 | module_param(mtu, int, 0); |
@@ -902,9 +908,12 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val | |||
902 | 908 | ||
903 | static int netdev_open(struct net_device *dev) | 909 | static int netdev_open(struct net_device *dev) |
904 | { | 910 | { |
911 | const struct firmware *fw_rx, *fw_tx; | ||
912 | const __be32 *fw_rx_data, *fw_tx_data; | ||
905 | struct netdev_private *np = netdev_priv(dev); | 913 | struct netdev_private *np = netdev_priv(dev); |
906 | void __iomem *ioaddr = np->base; | 914 | void __iomem *ioaddr = np->base; |
907 | int i, retval; | 915 | int i, retval; |
916 | size_t tx_size, rx_size; | ||
908 | size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size; | 917 | size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size; |
909 | 918 | ||
910 | /* Do we ever need to reset the chip??? */ | 919 | /* Do we ever need to reset the chip??? */ |
@@ -1040,11 +1049,40 @@ static int netdev_open(struct net_device *dev) | |||
1040 | writel(ETH_P_8021Q, ioaddr + VlanType); | 1049 | writel(ETH_P_8021Q, ioaddr + VlanType); |
1041 | #endif /* VLAN_SUPPORT */ | 1050 | #endif /* VLAN_SUPPORT */ |
1042 | 1051 | ||
1052 | retval = request_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev); | ||
1053 | if (retval) { | ||
1054 | printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", | ||
1055 | FIRMWARE_RX); | ||
1056 | return retval; | ||
1057 | } | ||
1058 | if (fw_rx->size % 4) { | ||
1059 | printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", | ||
1060 | fw_rx->size, FIRMWARE_RX); | ||
1061 | retval = -EINVAL; | ||
1062 | goto out_rx; | ||
1063 | } | ||
1064 | retval = request_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev); | ||
1065 | if (retval) { | ||
1066 | printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", | ||
1067 | FIRMWARE_TX); | ||
1068 | goto out_rx; | ||
1069 | } | ||
1070 | if (fw_tx->size % 4) { | ||
1071 | printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", | ||
1072 | fw_tx->size, FIRMWARE_TX); | ||
1073 | retval = -EINVAL; | ||
1074 | goto out_tx; | ||
1075 | } | ||
1076 | fw_rx_data = (const __be32 *)&fw_rx->data[0]; | ||
1077 | fw_tx_data = (const __be32 *)&fw_tx->data[0]; | ||
1078 | rx_size = fw_rx->size / 4; | ||
1079 | tx_size = fw_tx->size / 4; | ||
1080 | |||
1043 | /* Load Rx/Tx firmware into the frame processors */ | 1081 | /* Load Rx/Tx firmware into the frame processors */ |
1044 | for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++) | 1082 | for (i = 0; i < rx_size; i++) |
1045 | writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4); | 1083 | writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4); |
1046 | for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++) | 1084 | for (i = 0; i < tx_size; i++) |
1047 | writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4); | 1085 | writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4); |
1048 | if (enable_hw_cksum) | 1086 | if (enable_hw_cksum) |
1049 | /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */ | 1087 | /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */ |
1050 | writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl); | 1088 | writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl); |
@@ -1056,7 +1094,11 @@ static int netdev_open(struct net_device *dev) | |||
1056 | printk(KERN_DEBUG "%s: Done netdev_open().\n", | 1094 | printk(KERN_DEBUG "%s: Done netdev_open().\n", |
1057 | dev->name); | 1095 | dev->name); |
1058 | 1096 | ||
1059 | return 0; | 1097 | out_tx: |
1098 | release_firmware(fw_tx); | ||
1099 | out_rx: | ||
1100 | release_firmware(fw_rx); | ||
1101 | return retval; | ||
1060 | } | 1102 | } |
1061 | 1103 | ||
1062 | 1104 | ||
diff --git a/drivers/net/starfire_firmware.h b/drivers/net/starfire_firmware.h deleted file mode 100644 index 0a668528955d..000000000000 --- a/drivers/net/starfire_firmware.h +++ /dev/null | |||
@@ -1,346 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2003 Adaptec, Inc. | ||
3 | * | ||
4 | * Please read the following license before using the Adaptec Software | ||
5 | * ("Program"). If you do not agree to the license terms, do not use the | ||
6 | * Program: | ||
7 | * | ||
8 | * You agree to be bound by version 2 of the General Public License ("GPL") | ||
9 | * dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html. | ||
10 | * If the link is broken, write to Free Software Foundation, 59 Temple Place, | ||
11 | * Boston, Massachusetts 02111-1307. | ||
12 | * | ||
13 | * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND | ||
14 | * THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR | ||
17 | * OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR | ||
18 | * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES | ||
19 | * ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | static const u32 firmware_rx[] = { | ||
24 | 0x010003dc, 0x00000000, | ||
25 | 0x04000421, 0x00000086, | ||
26 | 0x80000015, 0x0000180e, | ||
27 | 0x81000015, 0x00006664, | ||
28 | 0x1a0040ab, 0x00000b06, | ||
29 | 0x14200011, 0x00000000, | ||
30 | 0x14204022, 0x0000aaaa, | ||
31 | 0x14204022, 0x00000300, | ||
32 | 0x14204022, 0x00000000, | ||
33 | 0x1a0040ab, 0x00000b14, | ||
34 | 0x14200011, 0x00000000, | ||
35 | 0x83000015, 0x00000002, | ||
36 | 0x04000021, 0x00000000, | ||
37 | 0x00000010, 0x00000000, | ||
38 | 0x04000421, 0x00000087, | ||
39 | 0x00000010, 0x00000000, | ||
40 | 0x00000010, 0x00000000, | ||
41 | 0x00008015, 0x00000000, | ||
42 | 0x0000003e, 0x00000000, | ||
43 | 0x00000010, 0x00000000, | ||
44 | 0x82000015, 0x00004000, | ||
45 | 0x009e8050, 0x00000000, | ||
46 | 0x03008015, 0x00000000, | ||
47 | 0x86008015, 0x00000000, | ||
48 | 0x82000015, 0x00008000, | ||
49 | 0x0100001c, 0x00000000, | ||
50 | 0x000050a0, 0x0000010c, | ||
51 | 0x4e20d011, 0x00006008, | ||
52 | 0x1420d012, 0x00004008, | ||
53 | 0x0000f090, 0x00007000, | ||
54 | 0x0000c8b0, 0x00003000, | ||
55 | 0x00004040, 0x00000000, | ||
56 | 0x00108015, 0x00000000, | ||
57 | 0x00a2c150, 0x00004000, | ||
58 | 0x00a400b0, 0x00000014, | ||
59 | 0x00000020, 0x00000000, | ||
60 | 0x2500400d, 0x00002525, | ||
61 | 0x00047220, 0x00003100, | ||
62 | 0x00934070, 0x00000000, | ||
63 | 0x00000020, 0x00000000, | ||
64 | 0x00924460, 0x00000184, | ||
65 | 0x2b20c011, 0x00000000, | ||
66 | 0x0000c420, 0x00000540, | ||
67 | 0x36014018, 0x0000422d, | ||
68 | 0x14200011, 0x00000000, | ||
69 | 0x00924460, 0x00000183, | ||
70 | 0x3200001f, 0x00000034, | ||
71 | 0x02ac0015, 0x00000002, | ||
72 | 0x00a60110, 0x00000008, | ||
73 | 0x42200011, 0x00000000, | ||
74 | 0x00924060, 0x00000103, | ||
75 | 0x0000001e, 0x00000000, | ||
76 | 0x00000020, 0x00000100, | ||
77 | 0x0000001e, 0x00000000, | ||
78 | 0x00924460, 0x00000086, | ||
79 | 0x00004080, 0x00000000, | ||
80 | 0x0092c070, 0x00000000, | ||
81 | 0x00924060, 0x00000100, | ||
82 | 0x0000c890, 0x00005000, | ||
83 | 0x00a6c110, 0x00000000, | ||
84 | 0x00b0c090, 0x00000012, | ||
85 | 0x021c0015, 0x00000000, | ||
86 | 0x3200001f, 0x00000034, | ||
87 | 0x00924460, 0x00000510, | ||
88 | 0x44210011, 0x00000000, | ||
89 | 0x42000011, 0x00000000, | ||
90 | 0x83000015, 0x00000040, | ||
91 | 0x00924460, 0x00000508, | ||
92 | 0x45014018, 0x00004545, | ||
93 | 0x00808050, 0x00000000, | ||
94 | 0x62208012, 0x00000000, | ||
95 | 0x82000015, 0x00000800, | ||
96 | 0x15200011, 0x00000000, | ||
97 | 0x00000010, 0x00000000, | ||
98 | 0x00000010, 0x00000000, | ||
99 | 0x00000010, 0x00000000, | ||
100 | 0x00000010, 0x00000000, | ||
101 | 0x00000010, 0x00000000, | ||
102 | 0x80000015, 0x0000eea4, | ||
103 | 0x81000015, 0x0000005f, | ||
104 | 0x00000060, 0x00000000, | ||
105 | 0x00004120, 0x00000000, | ||
106 | 0x00004a00, 0x00004000, | ||
107 | 0x00924460, 0x00000190, | ||
108 | 0x5601401a, 0x00005956, | ||
109 | 0x14000011, 0x00000000, | ||
110 | 0x00934050, 0x00000018, | ||
111 | 0x00930050, 0x00000018, | ||
112 | 0x3601403a, 0x0000002d, | ||
113 | 0x000643a9, 0x00000000, | ||
114 | 0x0000c420, 0x00000140, | ||
115 | 0x5601401a, 0x00005956, | ||
116 | 0x14000011, 0x00000000, | ||
117 | 0x00000010, 0x00000000, | ||
118 | 0x00000010, 0x00000000, | ||
119 | 0x000642a9, 0x00000000, | ||
120 | 0x00024420, 0x00000183, | ||
121 | 0x5601401a, 0x00005956, | ||
122 | 0x82000015, 0x00002000, | ||
123 | 0x15200011, 0x00000000, | ||
124 | 0x82000015, 0x00000010, | ||
125 | 0x15200011, 0x00000000, | ||
126 | 0x82000015, 0x00000010, | ||
127 | 0x15200011, 0x00000000, | ||
128 | }; /* 104 Rx instructions */ | ||
129 | #define FIRMWARE_RX_SIZE 104 | ||
130 | |||
131 | static const u32 firmware_tx[] = { | ||
132 | 0x010003dc, 0x00000000, | ||
133 | 0x04000421, 0x00000086, | ||
134 | 0x80000015, 0x0000180e, | ||
135 | 0x81000015, 0x00006664, | ||
136 | 0x1a0040ab, 0x00000b06, | ||
137 | 0x14200011, 0x00000000, | ||
138 | 0x14204022, 0x0000aaaa, | ||
139 | 0x14204022, 0x00000300, | ||
140 | 0x14204022, 0x00000000, | ||
141 | 0x1a0040ab, 0x00000b14, | ||
142 | 0x14200011, 0x00000000, | ||
143 | 0x83000015, 0x00000002, | ||
144 | 0x04000021, 0x00000000, | ||
145 | 0x00000010, 0x00000000, | ||
146 | 0x04000421, 0x00000087, | ||
147 | 0x00000010, 0x00000000, | ||
148 | 0x00000010, 0x00000000, | ||
149 | 0x00008015, 0x00000000, | ||
150 | 0x0000003e, 0x00000000, | ||
151 | 0x00000010, 0x00000000, | ||
152 | 0x82000015, 0x00004000, | ||
153 | 0x009e8050, 0x00000000, | ||
154 | 0x03008015, 0x00000000, | ||
155 | 0x86008015, 0x00000000, | ||
156 | 0x82000015, 0x00008000, | ||
157 | 0x0100001c, 0x00000000, | ||
158 | 0x000050a0, 0x0000010c, | ||
159 | 0x4e20d011, 0x00006008, | ||
160 | 0x1420d012, 0x00004008, | ||
161 | 0x0000f090, 0x00007000, | ||
162 | 0x0000c8b0, 0x00003000, | ||
163 | 0x00004040, 0x00000000, | ||
164 | 0x00108015, 0x00000000, | ||
165 | 0x00a2c150, 0x00004000, | ||
166 | 0x00a400b0, 0x00000014, | ||
167 | 0x00000020, 0x00000000, | ||
168 | 0x2500400d, 0x00002525, | ||
169 | 0x00047220, 0x00003100, | ||
170 | 0x00934070, 0x00000000, | ||
171 | 0x00000020, 0x00000000, | ||
172 | 0x00924460, 0x00000184, | ||
173 | 0x2b20c011, 0x00000000, | ||
174 | 0x0000c420, 0x00000540, | ||
175 | 0x36014018, 0x0000422d, | ||
176 | 0x14200011, 0x00000000, | ||
177 | 0x00924460, 0x00000183, | ||
178 | 0x3200001f, 0x00000034, | ||
179 | 0x02ac0015, 0x00000002, | ||
180 | 0x00a60110, 0x00000008, | ||
181 | 0x42200011, 0x00000000, | ||
182 | 0x00924060, 0x00000103, | ||
183 | 0x0000001e, 0x00000000, | ||
184 | 0x00000020, 0x00000100, | ||
185 | 0x0000001e, 0x00000000, | ||
186 | 0x00924460, 0x00000086, | ||
187 | 0x00004080, 0x00000000, | ||
188 | 0x0092c070, 0x00000000, | ||
189 | 0x00924060, 0x00000100, | ||
190 | 0x0000c890, 0x00005000, | ||
191 | 0x00a6c110, 0x00000000, | ||
192 | 0x00b0c090, 0x00000012, | ||
193 | 0x021c0015, 0x00000000, | ||
194 | 0x3200001f, 0x00000034, | ||
195 | 0x00924460, 0x00000510, | ||
196 | 0x44210011, 0x00000000, | ||
197 | 0x42000011, 0x00000000, | ||
198 | 0x83000015, 0x00000040, | ||
199 | 0x00924460, 0x00000508, | ||
200 | 0x45014018, 0x00004545, | ||
201 | 0x00808050, 0x00000000, | ||
202 | 0x62208012, 0x00000000, | ||
203 | 0x82000015, 0x00000800, | ||
204 | 0x15200011, 0x00000000, | ||
205 | 0x00000010, 0x00000000, | ||
206 | 0x00000010, 0x00000000, | ||
207 | 0x00000010, 0x00000000, | ||
208 | 0x00000010, 0x00000000, | ||
209 | 0x00000010, 0x00000000, | ||
210 | 0x80000015, 0x0000eea4, | ||
211 | 0x81000015, 0x0000005f, | ||
212 | 0x00000060, 0x00000000, | ||
213 | 0x00004120, 0x00000000, | ||
214 | 0x00004a00, 0x00004000, | ||
215 | 0x00924460, 0x00000190, | ||
216 | 0x5601401a, 0x00005956, | ||
217 | 0x14000011, 0x00000000, | ||
218 | 0x00934050, 0x00000018, | ||
219 | 0x00930050, 0x00000018, | ||
220 | 0x3601403a, 0x0000002d, | ||
221 | 0x000643a9, 0x00000000, | ||
222 | 0x0000c420, 0x00000140, | ||
223 | 0x5601401a, 0x00005956, | ||
224 | 0x14000011, 0x00000000, | ||
225 | 0x00000010, 0x00000000, | ||
226 | 0x00000010, 0x00000000, | ||
227 | 0x000642a9, 0x00000000, | ||
228 | 0x00024420, 0x00000183, | ||
229 | 0x5601401a, 0x00005956, | ||
230 | 0x82000015, 0x00002000, | ||
231 | 0x15200011, 0x00000000, | ||
232 | 0x82000015, 0x00000010, | ||
233 | 0x15200011, 0x00000000, | ||
234 | 0x82000015, 0x00000010, | ||
235 | 0x15200011, 0x00000000, | ||
236 | }; /* 104 Tx instructions */ | ||
237 | #define FIRMWARE_TX_SIZE 104 | ||
238 | #if 0 | ||
239 | static const u32 firmware_wol[] = { | ||
240 | 0x010003dc, 0x00000000, | ||
241 | 0x19000421, 0x00000087, | ||
242 | 0x80000015, 0x00001a1a, | ||
243 | 0x81000015, 0x00001a1a, | ||
244 | 0x1a0040ab, 0x00000b06, | ||
245 | 0x15200011, 0x00000000, | ||
246 | 0x15204022, 0x0000aaaa, | ||
247 | 0x15204022, 0x00000300, | ||
248 | 0x15204022, 0x00000000, | ||
249 | 0x1a0040ab, 0x00000b15, | ||
250 | 0x15200011, 0x00000000, | ||
251 | 0x83000015, 0x00000002, | ||
252 | 0x04000021, 0x00000000, | ||
253 | 0x00000010, 0x00000000, | ||
254 | 0x04000421, 0x00000087, | ||
255 | 0x00000010, 0x00000000, | ||
256 | 0x00000010, 0x00000000, | ||
257 | 0x00008015, 0x00000000, | ||
258 | 0x0000003e, 0x00000000, | ||
259 | 0x00000010, 0x00000000, | ||
260 | 0x00000010, 0x00000000, | ||
261 | 0x82000015, 0x00004000, | ||
262 | 0x82000015, 0x00008000, | ||
263 | 0x0000000c, 0x00000000, | ||
264 | 0x00000010, 0x00000000, | ||
265 | 0x00004080, 0x00000100, | ||
266 | 0x1f20c011, 0x00001122, | ||
267 | 0x2720f011, 0x00003011, | ||
268 | 0x19200071, 0x00000000, | ||
269 | 0x1a200051, 0x00000000, | ||
270 | 0x00000010, 0x00000000, | ||
271 | 0x00000010, 0x00000000, | ||
272 | 0x1d2040a4, 0x00003344, | ||
273 | 0x1d2040a2, 0x00005566, | ||
274 | 0x000040a0, 0x00000100, | ||
275 | 0x00108050, 0x00000001, | ||
276 | 0x1a208012, 0x00000006, | ||
277 | 0x82000015, 0x00008080, | ||
278 | 0x010003dc, 0x00000000, | ||
279 | 0x1d2040a4, 0x00002233, | ||
280 | 0x1d2040a4, 0x00004455, | ||
281 | 0x2d208011, 0x00000005, | ||
282 | 0x1d2040a4, 0x00006611, | ||
283 | 0x00108050, 0x00000001, | ||
284 | 0x27200011, 0x00000000, | ||
285 | 0x1d2050a4, 0x00006600, | ||
286 | 0x82000015, 0x00008080, | ||
287 | 0x010003dc, 0x00000000, | ||
288 | 0x00000050, 0x00000000, | ||
289 | 0x1b200031, 0x00000000, | ||
290 | 0x0000001e, 0x00000000, | ||
291 | 0x0000001e, 0x00000000, | ||
292 | 0x0000001e, 0x00000000, | ||
293 | 0x0000001e, 0x00000000, | ||
294 | 0x00924460, 0x00000086, | ||
295 | 0x00004080, 0x00000000, | ||
296 | 0x0092c070, 0x00000000, | ||
297 | 0x00924060, 0x00000100, | ||
298 | 0x0000c890, 0x00005000, | ||
299 | 0x00a6c110, 0x00000000, | ||
300 | 0x00b0c090, 0x00000012, | ||
301 | 0x021c0015, 0x00000000, | ||
302 | 0x3200001f, 0x00000034, | ||
303 | 0x00924460, 0x00000510, | ||
304 | 0x44210011, 0x00000000, | ||
305 | 0x42000011, 0x00000000, | ||
306 | 0x83000015, 0x00000040, | ||
307 | 0x00924460, 0x00000508, | ||
308 | 0x476a0012, 0x00000100, | ||
309 | 0x83000015, 0x00000008, | ||
310 | 0x16200011, 0x00000000, | ||
311 | 0x001e8050, 0x00000000, | ||
312 | 0x001e8050, 0x00000000, | ||
313 | 0x00808050, 0x00000000, | ||
314 | 0x03008015, 0x00000000, | ||
315 | 0x62208012, 0x00000000, | ||
316 | 0x82000015, 0x00000800, | ||
317 | 0x16200011, 0x00000000, | ||
318 | 0x80000015, 0x0000eea4, | ||
319 | 0x81000015, 0x0000005f, | ||
320 | 0x00000020, 0x00000000, | ||
321 | 0x00004120, 0x00000000, | ||
322 | 0x00004a00, 0x00004000, | ||
323 | 0x00924460, 0x00000190, | ||
324 | 0x5c01401a, 0x0000595c, | ||
325 | 0x15000011, 0x00000000, | ||
326 | 0x00934050, 0x00000018, | ||
327 | 0x00930050, 0x00000018, | ||
328 | 0x3601403a, 0x0000002d, | ||
329 | 0x00064029, 0x00000000, | ||
330 | 0x0000c420, 0x00000140, | ||
331 | 0x5c01401a, 0x0000595c, | ||
332 | 0x15000011, 0x00000000, | ||
333 | 0x00000010, 0x00000000, | ||
334 | 0x00000010, 0x00000000, | ||
335 | 0x00064029, 0x00000000, | ||
336 | 0x00024420, 0x00000183, | ||
337 | 0x5c01401a, 0x0000595c, | ||
338 | 0x82000015, 0x00002000, | ||
339 | 0x16200011, 0x00000000, | ||
340 | 0x82000015, 0x00000010, | ||
341 | 0x16200011, 0x00000000, | ||
342 | 0x82000015, 0x00000010, | ||
343 | 0x16200011, 0x00000000, | ||
344 | }; /* 104 WoL instructions */ | ||
345 | #define FIRMWARE_WOL_SIZE 104 | ||
346 | #endif | ||
diff --git a/drivers/net/starfire_firmware.pl b/drivers/net/starfire_firmware.pl deleted file mode 100644 index 0c82b80e1074..000000000000 --- a/drivers/net/starfire_firmware.pl +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | #!/usr/bin/perl | ||
2 | |||
3 | # This script can be used to generate a new starfire_firmware.h | ||
4 | # from GFP_RX.DAT and GFP_TX.DAT, files included with the DDK | ||
5 | # and also with the Novell drivers. | ||
6 | |||
7 | open FW, "GFP_RX.DAT" || die; | ||
8 | open FWH, ">starfire_firmware.h" || die; | ||
9 | |||
10 | printf(FWH "static u32 firmware_rx[] = {\n"); | ||
11 | $counter = 0; | ||
12 | while ($foo = <FW>) { | ||
13 | chomp; | ||
14 | printf(FWH " 0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4)); | ||
15 | $counter++; | ||
16 | } | ||
17 | |||
18 | close FW; | ||
19 | open FW, "GFP_TX.DAT" || die; | ||
20 | |||
21 | printf(FWH "};\t/* %d Rx instructions */\n#define FIRMWARE_RX_SIZE %d\n\nstatic u32 firmware_tx[] = {\n", $counter, $counter); | ||
22 | $counter = 0; | ||
23 | while ($foo = <FW>) { | ||
24 | chomp; | ||
25 | printf(FWH " 0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4)); | ||
26 | $counter++; | ||
27 | } | ||
28 | |||
29 | close FW; | ||
30 | printf(FWH "};\t/* %d Tx instructions */\n#define FIRMWARE_TX_SIZE %d\n", $counter, $counter); | ||
31 | close(FWH); | ||
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 04ae1e86aeaa..5e2dbaee125b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/workqueue.h> | 40 | #include <linux/workqueue.h> |
41 | #include <linux/prefetch.h> | 41 | #include <linux/prefetch.h> |
42 | #include <linux/dma-mapping.h> | 42 | #include <linux/dma-mapping.h> |
43 | #include <linux/firmware.h> | ||
43 | 44 | ||
44 | #include <net/checksum.h> | 45 | #include <net/checksum.h> |
45 | #include <net/ip.h> | 46 | #include <net/ip.h> |
@@ -137,6 +138,10 @@ | |||
137 | 138 | ||
138 | #define TG3_NUM_TEST 6 | 139 | #define TG3_NUM_TEST 6 |
139 | 140 | ||
141 | #define FIRMWARE_TG3 "tigon/tg3.bin" | ||
142 | #define FIRMWARE_TG3TSO "tigon/tg3_tso.bin" | ||
143 | #define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin" | ||
144 | |||
140 | static char version[] __devinitdata = | 145 | static char version[] __devinitdata = |
141 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 146 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
142 | 147 | ||
@@ -144,6 +149,10 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox | |||
144 | MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); | 149 | MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver"); |
145 | MODULE_LICENSE("GPL"); | 150 | MODULE_LICENSE("GPL"); |
146 | MODULE_VERSION(DRV_MODULE_VERSION); | 151 | MODULE_VERSION(DRV_MODULE_VERSION); |
152 | MODULE_FIRMWARE(FIRMWARE_TG3); | ||
153 | MODULE_FIRMWARE(FIRMWARE_TG3TSO); | ||
154 | MODULE_FIRMWARE(FIRMWARE_TG3TSO5); | ||
155 | |||
147 | 156 | ||
148 | static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ | 157 | static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */ |
149 | module_param(tg3_debug, int, 0); | 158 | module_param(tg3_debug, int, 0); |
@@ -6205,130 +6214,6 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) | |||
6205 | return 0; | 6214 | return 0; |
6206 | } | 6215 | } |
6207 | 6216 | ||
6208 | #define TG3_FW_RELEASE_MAJOR 0x0 | ||
6209 | #define TG3_FW_RELASE_MINOR 0x0 | ||
6210 | #define TG3_FW_RELEASE_FIX 0x0 | ||
6211 | #define TG3_FW_START_ADDR 0x08000000 | ||
6212 | #define TG3_FW_TEXT_ADDR 0x08000000 | ||
6213 | #define TG3_FW_TEXT_LEN 0x9c0 | ||
6214 | #define TG3_FW_RODATA_ADDR 0x080009c0 | ||
6215 | #define TG3_FW_RODATA_LEN 0x60 | ||
6216 | #define TG3_FW_DATA_ADDR 0x08000a40 | ||
6217 | #define TG3_FW_DATA_LEN 0x20 | ||
6218 | #define TG3_FW_SBSS_ADDR 0x08000a60 | ||
6219 | #define TG3_FW_SBSS_LEN 0xc | ||
6220 | #define TG3_FW_BSS_ADDR 0x08000a70 | ||
6221 | #define TG3_FW_BSS_LEN 0x10 | ||
6222 | |||
6223 | static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { | ||
6224 | 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, | ||
6225 | 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000, | ||
6226 | 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034, | ||
6227 | 0x0e00021c, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000, | ||
6228 | 0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xaf80680c, 0x0e00004c, 0x241b2105, | ||
6229 | 0x97850000, 0x97870002, 0x9782002c, 0x9783002e, 0x3c040800, 0x248409c0, | ||
6230 | 0xafa00014, 0x00021400, 0x00621825, 0x00052c00, 0xafa30010, 0x8f860010, | ||
6231 | 0x00e52825, 0x0e000060, 0x24070102, 0x3c02ac00, 0x34420100, 0x3c03ac01, | ||
6232 | 0x34630100, 0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, 0xaf82049c, | ||
6233 | 0x24020001, 0xaf825ce0, 0x0e00003f, 0xaf825d00, 0x0e000140, 0x00000000, | ||
6234 | 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, 0x8f835400, | ||
6235 | 0x34630400, 0xaf835400, 0xaf825404, 0x3c020800, 0x24420034, 0xaf82541c, | ||
6236 | 0x03e00008, 0xaf805400, 0x00000000, 0x00000000, 0x3c020800, 0x34423000, | ||
6237 | 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac220a64, | ||
6238 | 0x24020040, 0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, 0xac600000, | ||
6239 | 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, | ||
6240 | 0x00804821, 0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, 0x8c840a68, | ||
6241 | 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac230a60, 0x14400003, | ||
6242 | 0x00004021, 0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, 0x3c030800, | ||
6243 | 0x8c630a64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001, | ||
6244 | 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c420a60, | ||
6245 | 0x3c030800, 0x8c630a64, 0x8f84680c, 0x00021140, 0x00431021, 0xac440008, | ||
6246 | 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, | ||
6247 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
6248 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
6249 | 0, 0, 0, 0, 0, 0, | ||
6250 | 0x02000008, 0x00000000, 0x0a0001e3, 0x3c0a0001, 0x0a0001e3, 0x3c0a0002, | ||
6251 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, | ||
6252 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, | ||
6253 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, | ||
6254 | 0x0a0001e3, 0x3c0a0007, 0x0a0001e3, 0x3c0a0008, 0x0a0001e3, 0x3c0a0009, | ||
6255 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000b, | ||
6256 | 0x0a0001e3, 0x3c0a000c, 0x0a0001e3, 0x3c0a000d, 0x0a0001e3, 0x00000000, | ||
6257 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000e, 0x0a0001e3, 0x00000000, | ||
6258 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, | ||
6259 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, | ||
6260 | 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a0013, 0x0a0001e3, 0x3c0a0014, | ||
6261 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
6262 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
6263 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
6264 | 0x27bdffe0, 0x00001821, 0x00001021, 0xafbf0018, 0xafb10014, 0xafb00010, | ||
6265 | 0x3c010800, 0x00220821, 0xac200a70, 0x3c010800, 0x00220821, 0xac200a74, | ||
6266 | 0x3c010800, 0x00220821, 0xac200a78, 0x24630001, 0x1860fff5, 0x2442000c, | ||
6267 | 0x24110001, 0x8f906810, 0x32020004, 0x14400005, 0x24040001, 0x3c020800, | ||
6268 | 0x8c420a78, 0x18400003, 0x00002021, 0x0e000182, 0x00000000, 0x32020001, | ||
6269 | 0x10400003, 0x00000000, 0x0e000169, 0x00000000, 0x0a000153, 0xaf915028, | ||
6270 | 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c050800, | ||
6271 | 0x8ca50a70, 0x3c060800, 0x8cc60a80, 0x3c070800, 0x8ce70a78, 0x27bdffe0, | ||
6272 | 0x3c040800, 0x248409d0, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, | ||
6273 | 0x0e00017b, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001, | ||
6274 | 0x8f836810, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, 0xaf836810, | ||
6275 | 0x27bdffd8, 0xafbf0024, 0x1080002e, 0xafb00020, 0x8f825cec, 0xafa20018, | ||
6276 | 0x8f825cec, 0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, 0xaf825cec, | ||
6277 | 0x8e020000, 0x18400016, 0x00000000, 0x3c020800, 0x94420a74, 0x8fa3001c, | ||
6278 | 0x000221c0, 0xac830004, 0x8fa2001c, 0x3c010800, 0x0e000201, 0xac220a74, | ||
6279 | 0x10400005, 0x00000000, 0x8e020000, 0x24420001, 0x0a0001df, 0xae020000, | ||
6280 | 0x3c020800, 0x8c420a70, 0x00021c02, 0x000321c0, 0x0a0001c5, 0xafa2001c, | ||
6281 | 0x0e000201, 0x00000000, 0x1040001f, 0x00000000, 0x8e020000, 0x8fa3001c, | ||
6282 | 0x24420001, 0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, 0x0a0001df, | ||
6283 | 0xae020000, 0x3c100800, 0x26100a78, 0x8e020000, 0x18400028, 0x00000000, | ||
6284 | 0x0e000201, 0x00000000, 0x14400024, 0x00000000, 0x8e020000, 0x3c030800, | ||
6285 | 0x8c630a70, 0x2442ffff, 0xafa3001c, 0x18400006, 0xae020000, 0x00031402, | ||
6286 | 0x000221c0, 0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, 0x2442ff00, | ||
6287 | 0x2c420300, 0x1440000b, 0x24024000, 0x3c040800, 0x248409dc, 0xafa00010, | ||
6288 | 0xafa00014, 0x8fa6001c, 0x24050008, 0x0e000060, 0x00003821, 0x0a0001df, | ||
6289 | 0x00000000, 0xaf825cf8, 0x3c020800, 0x8c420a40, 0x8fa3001c, 0x24420001, | ||
6290 | 0xaf835cf8, 0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, 0x03e00008, | ||
6291 | 0x27bd0028, 0x27bdffe0, 0x3c040800, 0x248409e8, 0x00002821, 0x00003021, | ||
6292 | 0x00003821, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x8fbf0018, | ||
6293 | 0x03e00008, 0x27bd0020, 0x8f82680c, 0x8f85680c, 0x00021827, 0x0003182b, | ||
6294 | 0x00031823, 0x00431024, 0x00441021, 0x00a2282b, 0x10a00006, 0x00000000, | ||
6295 | 0x00401821, 0x8f82680c, 0x0043102b, 0x1440fffd, 0x00000000, 0x03e00008, | ||
6296 | 0x00000000, 0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, 0x0064102b, | ||
6297 | 0x54400002, 0x00831023, 0x00641023, 0x2c420008, 0x03e00008, 0x38420001, | ||
6298 | 0x27bdffe0, 0x00802821, 0x3c040800, 0x24840a00, 0x00003021, 0x00003821, | ||
6299 | 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x0a000216, 0x00000000, | ||
6300 | 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, 0x27bdffe0, 0x3c1cc000, | ||
6301 | 0xafbf0018, 0x0e00004c, 0xaf80680c, 0x3c040800, 0x24840a10, 0x03802821, | ||
6302 | 0x00003021, 0x00003821, 0xafa00010, 0x0e000060, 0xafa00014, 0x2402ffff, | ||
6303 | 0xaf825404, 0x3c0200aa, 0x0e000234, 0xaf825434, 0x8fbf0018, 0x03e00008, | ||
6304 | 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe8, 0xafb00010, | ||
6305 | 0x24100001, 0xafbf0014, 0x3c01c003, 0xac200000, 0x8f826810, 0x30422000, | ||
6306 | 0x10400003, 0x00000000, 0x0e000246, 0x00000000, 0x0a00023a, 0xaf905428, | ||
6307 | 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdfff8, 0x8f845d0c, | ||
6308 | 0x3c0200ff, 0x3c030800, 0x8c630a50, 0x3442fff8, 0x00821024, 0x1043001e, | ||
6309 | 0x3c0500ff, 0x34a5fff8, 0x3c06c003, 0x3c074000, 0x00851824, 0x8c620010, | ||
6310 | 0x3c010800, 0xac230a50, 0x30420008, 0x10400005, 0x00871025, 0x8cc20000, | ||
6311 | 0x24420001, 0xacc20000, 0x00871025, 0xaf825d0c, 0x8fa20000, 0x24420001, | ||
6312 | 0xafa20000, 0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, 0x8fa20000, | ||
6313 | 0x8f845d0c, 0x3c030800, 0x8c630a50, 0x00851024, 0x1443ffe8, 0x00851824, | ||
6314 | 0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000 | ||
6315 | }; | ||
6316 | |||
6317 | static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { | ||
6318 | 0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430, | ||
6319 | 0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74, | ||
6320 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, | ||
6321 | 0x00000000, 0x00000000, 0x4d61696e, 0x43707542, 0x00000000, 0x00000000, | ||
6322 | 0x00000000 | ||
6323 | }; | ||
6324 | |||
6325 | #if 0 /* All zeros, don't eat up space with it. */ | ||
6326 | u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = { | ||
6327 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
6328 | 0x00000000, 0x00000000, 0x00000000, 0x00000000 | ||
6329 | }; | ||
6330 | #endif | ||
6331 | |||
6332 | #define RX_CPU_SCRATCH_BASE 0x30000 | 6217 | #define RX_CPU_SCRATCH_BASE 0x30000 |
6333 | #define RX_CPU_SCRATCH_SIZE 0x04000 | 6218 | #define RX_CPU_SCRATCH_SIZE 0x04000 |
6334 | #define TX_CPU_SCRATCH_BASE 0x34000 | 6219 | #define TX_CPU_SCRATCH_BASE 0x34000 |
@@ -6383,15 +6268,9 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) | |||
6383 | } | 6268 | } |
6384 | 6269 | ||
6385 | struct fw_info { | 6270 | struct fw_info { |
6386 | unsigned int text_base; | 6271 | unsigned int fw_base; |
6387 | unsigned int text_len; | 6272 | unsigned int fw_len; |
6388 | const u32 *text_data; | 6273 | const __be32 *fw_data; |
6389 | unsigned int rodata_base; | ||
6390 | unsigned int rodata_len; | ||
6391 | const u32 *rodata_data; | ||
6392 | unsigned int data_base; | ||
6393 | unsigned int data_len; | ||
6394 | const u32 *data_data; | ||
6395 | }; | 6274 | }; |
6396 | 6275 | ||
6397 | /* tp->lock is held. */ | 6276 | /* tp->lock is held. */ |
@@ -6428,24 +6307,11 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b | |||
6428 | write_op(tp, cpu_scratch_base + i, 0); | 6307 | write_op(tp, cpu_scratch_base + i, 0); |
6429 | tw32(cpu_base + CPU_STATE, 0xffffffff); | 6308 | tw32(cpu_base + CPU_STATE, 0xffffffff); |
6430 | tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); | 6309 | tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); |
6431 | for (i = 0; i < (info->text_len / sizeof(u32)); i++) | 6310 | for (i = 0; i < (info->fw_len / sizeof(u32)); i++) |
6432 | write_op(tp, (cpu_scratch_base + | ||
6433 | (info->text_base & 0xffff) + | ||
6434 | (i * sizeof(u32))), | ||
6435 | (info->text_data ? | ||
6436 | info->text_data[i] : 0)); | ||
6437 | for (i = 0; i < (info->rodata_len / sizeof(u32)); i++) | ||
6438 | write_op(tp, (cpu_scratch_base + | ||
6439 | (info->rodata_base & 0xffff) + | ||
6440 | (i * sizeof(u32))), | ||
6441 | (info->rodata_data ? | ||
6442 | info->rodata_data[i] : 0)); | ||
6443 | for (i = 0; i < (info->data_len / sizeof(u32)); i++) | ||
6444 | write_op(tp, (cpu_scratch_base + | 6311 | write_op(tp, (cpu_scratch_base + |
6445 | (info->data_base & 0xffff) + | 6312 | (info->fw_base & 0xffff) + |
6446 | (i * sizeof(u32))), | 6313 | (i * sizeof(u32))), |
6447 | (info->data_data ? | 6314 | be32_to_cpu(info->fw_data[i])); |
6448 | info->data_data[i] : 0)); | ||
6449 | 6315 | ||
6450 | err = 0; | 6316 | err = 0; |
6451 | 6317 | ||
@@ -6457,17 +6323,20 @@ out: | |||
6457 | static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) | 6323 | static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) |
6458 | { | 6324 | { |
6459 | struct fw_info info; | 6325 | struct fw_info info; |
6326 | const __be32 *fw_data; | ||
6460 | int err, i; | 6327 | int err, i; |
6461 | 6328 | ||
6462 | info.text_base = TG3_FW_TEXT_ADDR; | 6329 | fw_data = (void *)tp->fw->data; |
6463 | info.text_len = TG3_FW_TEXT_LEN; | 6330 | |
6464 | info.text_data = &tg3FwText[0]; | 6331 | /* Firmware blob starts with version numbers, followed by |
6465 | info.rodata_base = TG3_FW_RODATA_ADDR; | 6332 | start address and length. We are setting complete length. |
6466 | info.rodata_len = TG3_FW_RODATA_LEN; | 6333 | length = end_address_of_bss - start_address_of_text. |
6467 | info.rodata_data = &tg3FwRodata[0]; | 6334 | Remainder is the blob to be loaded contiguously |
6468 | info.data_base = TG3_FW_DATA_ADDR; | 6335 | from start address. */ |
6469 | info.data_len = TG3_FW_DATA_LEN; | 6336 | |
6470 | info.data_data = NULL; | 6337 | info.fw_base = be32_to_cpu(fw_data[1]); |
6338 | info.fw_len = tp->fw->size - 12; | ||
6339 | info.fw_data = &fw_data[3]; | ||
6471 | 6340 | ||
6472 | err = tg3_load_firmware_cpu(tp, RX_CPU_BASE, | 6341 | err = tg3_load_firmware_cpu(tp, RX_CPU_BASE, |
6473 | RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE, | 6342 | RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE, |
@@ -6483,21 +6352,21 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) | |||
6483 | 6352 | ||
6484 | /* Now startup only the RX cpu. */ | 6353 | /* Now startup only the RX cpu. */ |
6485 | tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); | 6354 | tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); |
6486 | tw32_f(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); | 6355 | tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base); |
6487 | 6356 | ||
6488 | for (i = 0; i < 5; i++) { | 6357 | for (i = 0; i < 5; i++) { |
6489 | if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR) | 6358 | if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base) |
6490 | break; | 6359 | break; |
6491 | tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); | 6360 | tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); |
6492 | tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); | 6361 | tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); |
6493 | tw32_f(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); | 6362 | tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base); |
6494 | udelay(1000); | 6363 | udelay(1000); |
6495 | } | 6364 | } |
6496 | if (i >= 5) { | 6365 | if (i >= 5) { |
6497 | printk(KERN_ERR PFX "tg3_load_firmware fails for %s " | 6366 | printk(KERN_ERR PFX "tg3_load_firmware fails for %s " |
6498 | "to set RX CPU PC, is %08x should be %08x\n", | 6367 | "to set RX CPU PC, is %08x should be %08x\n", |
6499 | tp->dev->name, tr32(RX_CPU_BASE + CPU_PC), | 6368 | tp->dev->name, tr32(RX_CPU_BASE + CPU_PC), |
6500 | TG3_FW_TEXT_ADDR); | 6369 | info.fw_base); |
6501 | return -ENODEV; | 6370 | return -ENODEV; |
6502 | } | 6371 | } |
6503 | tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); | 6372 | tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); |
@@ -6506,547 +6375,36 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) | |||
6506 | return 0; | 6375 | return 0; |
6507 | } | 6376 | } |
6508 | 6377 | ||
6509 | |||
6510 | #define TG3_TSO_FW_RELEASE_MAJOR 0x1 | ||
6511 | #define TG3_TSO_FW_RELASE_MINOR 0x6 | ||
6512 | #define TG3_TSO_FW_RELEASE_FIX 0x0 | ||
6513 | #define TG3_TSO_FW_START_ADDR 0x08000000 | ||
6514 | #define TG3_TSO_FW_TEXT_ADDR 0x08000000 | ||
6515 | #define TG3_TSO_FW_TEXT_LEN 0x1aa0 | ||
6516 | #define TG3_TSO_FW_RODATA_ADDR 0x08001aa0 | ||
6517 | #define TG3_TSO_FW_RODATA_LEN 0x60 | ||
6518 | #define TG3_TSO_FW_DATA_ADDR 0x08001b20 | ||
6519 | #define TG3_TSO_FW_DATA_LEN 0x30 | ||
6520 | #define TG3_TSO_FW_SBSS_ADDR 0x08001b50 | ||
6521 | #define TG3_TSO_FW_SBSS_LEN 0x2c | ||
6522 | #define TG3_TSO_FW_BSS_ADDR 0x08001b80 | ||
6523 | #define TG3_TSO_FW_BSS_LEN 0x894 | ||
6524 | |||
6525 | static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { | ||
6526 | 0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000, | ||
6527 | 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800, | ||
6528 | 0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, | ||
6529 | 0xafbf0018, 0x0e0005d8, 0x34840002, 0x0e000668, 0x00000000, 0x3c030800, | ||
6530 | 0x90631b68, 0x24020002, 0x3c040800, 0x24841aac, 0x14620003, 0x24050001, | ||
6531 | 0x3c040800, 0x24841aa0, 0x24060006, 0x00003821, 0xafa00010, 0x0e00067c, | ||
6532 | 0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001, | ||
6533 | 0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008, | ||
6534 | 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, | ||
6535 | 0xafb20018, 0xafb10014, 0x0e00005b, 0xafb00010, 0x24120002, 0x24110001, | ||
6536 | 0x8f706820, 0x32020100, 0x10400003, 0x00000000, 0x0e0000bb, 0x00000000, | ||
6537 | 0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001f0, 0x24040001, | ||
6538 | 0x32020001, 0x10400003, 0x00000000, 0x0e0000a3, 0x00000000, 0x3c020800, | ||
6539 | 0x90421b98, 0x14520003, 0x00000000, 0x0e0004c0, 0x00000000, 0x0a00003c, | ||
6540 | 0xaf715028, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, | ||
6541 | 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac0, 0x00002821, 0x00003021, | ||
6542 | 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x3c040800, | ||
6543 | 0x248423d8, 0xa4800000, 0x3c010800, 0xa0201b98, 0x3c010800, 0xac201b9c, | ||
6544 | 0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac, | ||
6545 | 0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bbc, 0x8f624434, 0x3c010800, | ||
6546 | 0xac221b88, 0x8f624438, 0x3c010800, 0xac221b8c, 0x8f624410, 0xac80f7a8, | ||
6547 | 0x3c010800, 0xac201b84, 0x3c010800, 0xac2023e0, 0x3c010800, 0xac2023c8, | ||
6548 | 0x3c010800, 0xac2023cc, 0x3c010800, 0xac202400, 0x3c010800, 0xac221b90, | ||
6549 | 0x8f620068, 0x24030007, 0x00021702, 0x10430005, 0x00000000, 0x8f620068, | ||
6550 | 0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac20240c, | ||
6551 | 0xac820034, 0x3c040800, 0x24841acc, 0x3c050800, 0x8ca5240c, 0x00003021, | ||
6552 | 0x00003821, 0xafa00010, 0x0e00067c, 0xafa00014, 0x8fbf0018, 0x03e00008, | ||
6553 | 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ad8, 0x00002821, 0x00003021, | ||
6554 | 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x0e00005b, | ||
6555 | 0x00000000, 0x0e0000b4, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, | ||
6556 | 0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, | ||
6557 | 0xaf636820, 0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, | ||
6558 | 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f675c5c, 0x3c030800, | ||
6559 | 0x24631bbc, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b98, | ||
6560 | 0x14400119, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902, | ||
6561 | 0x306300ff, 0x30e20003, 0x000211c0, 0x00622825, 0x00a04021, 0x00071602, | ||
6562 | 0x3c030800, 0x90631b98, 0x3044000f, 0x14600036, 0x00804821, 0x24020001, | ||
6563 | 0x3c010800, 0xa0221b98, 0x00051100, 0x00821025, 0x3c010800, 0xac201b9c, | ||
6564 | 0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac, | ||
6565 | 0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4, | ||
6566 | 0x3c010800, 0xa42223d8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222410, | ||
6567 | 0x30428000, 0x3c010800, 0xa4231bc6, 0x10400005, 0x24020001, 0x3c010800, | ||
6568 | 0xac2223f4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023f4, | ||
6569 | 0x9622000a, 0x3c030800, 0x94631bc6, 0x3c010800, 0xac2023f0, 0x3c010800, | ||
6570 | 0xac2023f8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800, | ||
6571 | 0xa42223d0, 0x3c010800, 0x0a000115, 0xa4231b96, 0x9622000c, 0x3c010800, | ||
6572 | 0xa42223ec, 0x3c040800, 0x24841b9c, 0x8c820000, 0x00021100, 0x3c010800, | ||
6573 | 0x00220821, 0xac311bc8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, | ||
6574 | 0xac271bcc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800, | ||
6575 | 0x00220821, 0xac261bd0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821, | ||
6576 | 0xac291bd4, 0x96230008, 0x3c020800, 0x8c421bac, 0x00432821, 0x3c010800, | ||
6577 | 0xac251bac, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14, | ||
6578 | 0x3063000f, 0x2c620002, 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800, | ||
6579 | 0x8c421b40, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, | ||
6580 | 0x1040fff7, 0x3c02c000, 0x00e21825, 0xaf635c5c, 0x8f625c50, 0x30420002, | ||
6581 | 0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b80, | ||
6582 | 0x3c040800, 0x94841b94, 0x01221025, 0x3c010800, 0xa42223da, 0x24020001, | ||
6583 | 0x3c010800, 0xac221bb8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003, | ||
6584 | 0xac231b80, 0x3c010800, 0xa4251b94, 0x3c060800, 0x24c61b9c, 0x8cc20000, | ||
6585 | 0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000656, | ||
6586 | 0x24040002, 0x0a0001e6, 0x00000000, 0x3c020800, 0x8c421bb8, 0x10400078, | ||
6587 | 0x24020001, 0x3c050800, 0x90a51b98, 0x14a20072, 0x00000000, 0x3c150800, | ||
6588 | 0x96b51b96, 0x3c040800, 0x8c841bac, 0x32a3ffff, 0x0083102a, 0x1440006c, | ||
6589 | 0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523f0, 0x1060005c, | ||
6590 | 0x00009021, 0x24d60004, 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100, | ||
6591 | 0x3c110800, 0x02308821, 0x0e000625, 0x8e311bc8, 0x00402821, 0x10a00054, | ||
6592 | 0x00000000, 0x9628000a, 0x31020040, 0x10400005, 0x2407180c, 0x8e22000c, | ||
6593 | 0x2407188c, 0x00021400, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bd0, | ||
6594 | 0x3c020800, 0x00501021, 0x8c421bd4, 0x00031d00, 0x00021400, 0x00621825, | ||
6595 | 0xaca30014, 0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff, | ||
6596 | 0x00431021, 0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000, | ||
6597 | 0x30c4ffff, 0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004, | ||
6598 | 0x8e63fff4, 0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021, | ||
6599 | 0xae62fff4, 0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0, | ||
6600 | 0xae60fff4, 0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008, | ||
6601 | 0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c, | ||
6602 | 0x0a0001cb, 0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223f0, 0x10400003, | ||
6603 | 0x3c024b65, 0x0a0001d3, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c, | ||
6604 | 0x30e2ffff, 0xaca20010, 0x0e0005a2, 0x00a02021, 0x3242ffff, 0x0054102b, | ||
6605 | 0x1440ffa9, 0x00000000, 0x24020002, 0x3c010800, 0x0a0001e6, 0xa0221b98, | ||
6606 | 0x8ec2083c, 0x24420001, 0x0a0001e6, 0xaec2083c, 0x0e0004c0, 0x00000000, | ||
6607 | 0x8fbf002c, 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, | ||
6608 | 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028, | ||
6609 | 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff, | ||
6610 | 0x3442fff8, 0x3c070800, 0x24e71bb4, 0x02428824, 0x9623000e, 0x8ce20000, | ||
6611 | 0x00431021, 0xace20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821, | ||
6612 | 0x0e00063b, 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90, | ||
6613 | 0x30420002, 0x1040011e, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, | ||
6614 | 0x10400119, 0x00000000, 0x0a00020d, 0x00000000, 0x8e240008, 0x8e230014, | ||
6615 | 0x00041402, 0x000231c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f, | ||
6616 | 0x00031942, 0x30637800, 0x00021100, 0x24424000, 0x00624821, 0x9522000a, | ||
6617 | 0x3084ffff, 0x30420008, 0x104000b0, 0x000429c0, 0x3c020800, 0x8c422400, | ||
6618 | 0x14400024, 0x24c50008, 0x94c20014, 0x3c010800, 0xa42223d0, 0x8cc40010, | ||
6619 | 0x00041402, 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42423d4, 0x94c2000e, | ||
6620 | 0x3083ffff, 0x00431023, 0x3c010800, 0xac222408, 0x94c2001a, 0x3c010800, | ||
6621 | 0xac262400, 0x3c010800, 0xac322404, 0x3c010800, 0xac2223fc, 0x3c02c000, | ||
6622 | 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e5, 0x00000000, | ||
6623 | 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e0, 0x00000000, 0x0a000246, | ||
6624 | 0x00000000, 0x94c2000e, 0x3c030800, 0x946323d4, 0x00434023, 0x3103ffff, | ||
6625 | 0x2c620008, 0x1040001c, 0x00000000, 0x94c20014, 0x24420028, 0x00a22821, | ||
6626 | 0x00031042, 0x1840000b, 0x00002021, 0x24e60848, 0x00403821, 0x94a30000, | ||
6627 | 0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, 0x0087102a, 0x1440fff9, | ||
6628 | 0x24a50002, 0x31020001, 0x1040001f, 0x3c024000, 0x3c040800, 0x248423fc, | ||
6629 | 0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, 0x0a000285, 0xac820000, | ||
6630 | 0x8f626800, 0x3c030010, 0x00431024, 0x10400009, 0x00000000, 0x94c2001a, | ||
6631 | 0x3c030800, 0x8c6323fc, 0x00431021, 0x3c010800, 0xac2223fc, 0x0a000286, | ||
6632 | 0x3c024000, 0x94c2001a, 0x94c4001c, 0x3c030800, 0x8c6323fc, 0x00441023, | ||
6633 | 0x00621821, 0x3c010800, 0xac2323fc, 0x3c024000, 0x02421825, 0xaf635c9c, | ||
6634 | 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x9522000a, 0x30420010, | ||
6635 | 0x1040009b, 0x00000000, 0x3c030800, 0x946323d4, 0x3c070800, 0x24e72400, | ||
6636 | 0x8ce40000, 0x8f626800, 0x24630030, 0x00832821, 0x3c030010, 0x00431024, | ||
6637 | 0x1440000a, 0x00000000, 0x94a20004, 0x3c040800, 0x8c842408, 0x3c030800, | ||
6638 | 0x8c6323fc, 0x00441023, 0x00621821, 0x3c010800, 0xac2323fc, 0x3c040800, | ||
6639 | 0x8c8423fc, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, 0x00822021, | ||
6640 | 0x00041027, 0xa4a20006, 0x3c030800, 0x8c632404, 0x3c0200ff, 0x3442fff8, | ||
6641 | 0x00628824, 0x96220008, 0x24050001, 0x24034000, 0x000231c0, 0x00801021, | ||
6642 | 0xa4c2001a, 0xa4c0001c, 0xace00000, 0x3c010800, 0xac251b60, 0xaf635cb8, | ||
6643 | 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, 0x3c010800, 0xac201b60, | ||
6644 | 0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, | ||
6645 | 0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x1040ffec, 0x00000000, | ||
6646 | 0x3c040800, 0x0e00063b, 0x8c842404, 0x0a00032a, 0x00000000, 0x3c030800, | ||
6647 | 0x90631b98, 0x24020002, 0x14620003, 0x3c034b65, 0x0a0002e1, 0x00008021, | ||
6648 | 0x8e22001c, 0x34637654, 0x10430002, 0x24100002, 0x24100001, 0x00c02021, | ||
6649 | 0x0e000350, 0x02003021, 0x24020003, 0x3c010800, 0xa0221b98, 0x24020002, | ||
6650 | 0x1202000a, 0x24020001, 0x3c030800, 0x8c6323f0, 0x10620006, 0x00000000, | ||
6651 | 0x3c020800, 0x944223d8, 0x00021400, 0x0a00031f, 0xae220014, 0x3c040800, | ||
6652 | 0x248423da, 0x94820000, 0x00021400, 0xae220014, 0x3c020800, 0x8c421bbc, | ||
6653 | 0x3c03c000, 0x3c010800, 0xa0201b98, 0x00431025, 0xaf625c5c, 0x8f625c50, | ||
6654 | 0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, 0x8c820000, 0x00431025, | ||
6655 | 0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, 0x00000000, 0x3c020800, | ||
6656 | 0x24421b84, 0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 0x3063000f, | ||
6657 | 0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, 0x3c020800, 0x8c421b40, | ||
6658 | 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, | ||
6659 | 0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, | ||
6660 | 0x1440fffc, 0x00000000, 0x12600003, 0x00000000, 0x0e0004c0, 0x00000000, | ||
6661 | 0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x03e00008, | ||
6662 | 0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b88, 0x8c820000, 0x00031c02, | ||
6663 | 0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02, | ||
6664 | 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, | ||
6665 | 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000, | ||
6666 | 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000, | ||
6667 | 0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, 0x14c00011, 0x256e0008, | ||
6668 | 0x3c020800, 0x8c4223f4, 0x10400007, 0x24020016, 0x3c010800, 0xa42223d2, | ||
6669 | 0x2402002a, 0x3c010800, 0x0a000364, 0xa42223d4, 0x8d670010, 0x00071402, | ||
6670 | 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42723d4, 0x3c040800, 0x948423d4, | ||
6671 | 0x3c030800, 0x946323d2, 0x95cf0006, 0x3c020800, 0x944223d0, 0x00832023, | ||
6672 | 0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, 0x3082ffff, 0x14c0001a, | ||
6673 | 0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, 0xa42223d6, 0x95820004, | ||
6674 | 0x95830006, 0x3c010800, 0xac2023e4, 0x3c010800, 0xac2023e8, 0x00021400, | ||
6675 | 0x00431025, 0x3c010800, 0xac221bc0, 0x95220004, 0x3c010800, 0xa4221bc4, | ||
6676 | 0x95230002, 0x01e51023, 0x0043102a, 0x10400010, 0x24020001, 0x3c010800, | ||
6677 | 0x0a000398, 0xac2223f8, 0x3c030800, 0x8c6323e8, 0x3c020800, 0x94421bc4, | ||
6678 | 0x00431021, 0xa5220004, 0x3c020800, 0x94421bc0, 0xa5820004, 0x3c020800, | ||
6679 | 0x8c421bc0, 0xa5820006, 0x3c020800, 0x8c4223f0, 0x3c0d0800, 0x8dad23e4, | ||
6680 | 0x3c0a0800, 0x144000e5, 0x8d4a23e8, 0x3c020800, 0x94421bc4, 0x004a1821, | ||
6681 | 0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, 0x01435023, 0x3c020800, | ||
6682 | 0x944223d6, 0x30420009, 0x10400008, 0x00000000, 0x9582000c, 0x3042fff6, | ||
6683 | 0xa582000c, 0x3c020800, 0x944223d6, 0x30420009, 0x01a26823, 0x3c020800, | ||
6684 | 0x8c4223f8, 0x1040004a, 0x01203821, 0x3c020800, 0x944223d2, 0x00004021, | ||
6685 | 0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, 0x00021042, 0x18400008, | ||
6686 | 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021, 0x0103102a, | ||
6687 | 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402, | ||
6688 | 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021, 0x2527000c, | ||
6689 | 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004, 0x1440fffb, | ||
6690 | 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023, 0x01803821, | ||
6691 | 0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, 0x18400010, 0x00c33021, | ||
6692 | 0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006, | ||
6693 | 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008, | ||
6694 | 0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00061c02, | ||
6695 | 0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, 0x30c2ffff, 0x00623021, | ||
6696 | 0x00061402, 0x00c23021, 0x0a00047d, 0x30c6ffff, 0x24020002, 0x14c20081, | ||
6697 | 0x00000000, 0x3c020800, 0x8c42240c, 0x14400007, 0x00000000, 0x3c020800, | ||
6698 | 0x944223d2, 0x95230002, 0x01e21023, 0x10620077, 0x00000000, 0x3c020800, | ||
6699 | 0x944223d2, 0x01e21023, 0xa5220002, 0x3c020800, 0x8c42240c, 0x1040001a, | ||
6700 | 0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b96, 0x00e04021, 0x00072c02, | ||
6701 | 0x00aa2021, 0x00431023, 0x00823823, 0x00072402, 0x30e2ffff, 0x00823821, | ||
6702 | 0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, 0x948423d4, 0x00453023, | ||
6703 | 0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, 0x00061c02, 0x30c2ffff, | ||
6704 | 0x0a00047d, 0x00623021, 0x01203821, 0x00004021, 0x3082ffff, 0x00021042, | ||
6705 | 0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021, | ||
6706 | 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021, | ||
6707 | 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021, | ||
6708 | 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004, | ||
6709 | 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023, | ||
6710 | 0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423d4, 0x00621821, | ||
6711 | 0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061c02, 0x3c020800, | ||
6712 | 0x944223d0, 0x00c34821, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043, | ||
6713 | 0x18400010, 0x00003021, 0x00402021, 0x94e20000, 0x24e70002, 0x00c23021, | ||
6714 | 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, | ||
6715 | 0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, 0x00000000, 0x3c020800, | ||
6716 | 0x944223ec, 0x00c23021, 0x3122ffff, 0x00c23021, 0x00061c02, 0x30c2ffff, | ||
6717 | 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010, | ||
6718 | 0xadc00014, 0x0a00049d, 0xadc00000, 0x8dc70010, 0x00e04021, 0x11400007, | ||
6719 | 0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, 0x00433021, 0x00061402, | ||
6720 | 0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, 0x946323d4, 0x3102ffff, | ||
6721 | 0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, 0x30c2ffff, 0x00623021, | ||
6722 | 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010, 0x3102ffff, | ||
6723 | 0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, 0x8c4223f4, 0x10400005, | ||
6724 | 0x2de205eb, 0x14400002, 0x25e2fff2, 0x34028870, 0xa5c20034, 0x3c030800, | ||
6725 | 0x246323e8, 0x8c620000, 0x24420001, 0xac620000, 0x3c040800, 0x8c8423e4, | ||
6726 | 0x3c020800, 0x8c421bc0, 0x3303ffff, 0x00832021, 0x00431821, 0x0062102b, | ||
6727 | 0x3c010800, 0xac2423e4, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223e4, | ||
6728 | 0x3c010800, 0xac231bc0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800, | ||
6729 | 0x24a51b96, 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034, | ||
6730 | 0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000, | ||
6731 | 0x3c020800, 0x944223d0, 0x3c030800, 0x8c631bb0, 0x3c040800, 0x8c841bac, | ||
6732 | 0x01221023, 0x0064182a, 0xa7a9001e, 0x106000be, 0xa7a20016, 0x24be0022, | ||
6733 | 0x97b6001e, 0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000, | ||
6734 | 0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000b0, | ||
6735 | 0x00000000, 0x97d50818, 0x32a2ffff, 0x104000a3, 0x00009021, 0x0040a021, | ||
6736 | 0x00008821, 0x0e000625, 0x00000000, 0x00403021, 0x14c00007, 0x00000000, | ||
6737 | 0x3c020800, 0x8c4223dc, 0x24420001, 0x3c010800, 0x0a000596, 0xac2223dc, | ||
6738 | 0x3c100800, 0x02118021, 0x8e101bc8, 0x9608000a, 0x31020040, 0x10400005, | ||
6739 | 0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x31020080, | ||
6740 | 0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421bd0, 0x3c030800, | ||
6741 | 0x00711821, 0x8c631bd4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014, | ||
6742 | 0x96040008, 0x3242ffff, 0x00821021, 0x0282102a, 0x14400002, 0x02b22823, | ||
6743 | 0x00802821, 0x8e020000, 0x02459021, 0xacc20000, 0x8e020004, 0x00c02021, | ||
6744 | 0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010, | ||
6745 | 0x24020305, 0x0e0005a2, 0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc5, | ||
6746 | 0x3242ffff, 0x0a00058e, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a, | ||
6747 | 0x10400067, 0x00000000, 0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021, | ||
6748 | 0x0e000625, 0x8e101bc8, 0x00403021, 0x14c00005, 0x00000000, 0x8e62082c, | ||
6749 | 0x24420001, 0x0a000596, 0xae62082c, 0x9608000a, 0x31020040, 0x10400005, | ||
6750 | 0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x3c020800, | ||
6751 | 0x00511021, 0x8c421bd0, 0x3c030800, 0x00711821, 0x8c631bd4, 0x00021500, | ||
6752 | 0x00031c00, 0x00431025, 0xacc20014, 0x8e63fff4, 0x96020008, 0x00432023, | ||
6753 | 0x3242ffff, 0x3083ffff, 0x00431021, 0x02c2102a, 0x10400003, 0x00802821, | ||
6754 | 0x97a9001e, 0x01322823, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000, | ||
6755 | 0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, 0x8e63fff4, 0x00431021, | ||
6756 | 0xacc20004, 0x8e63fff4, 0x96020008, 0x00641821, 0x0062102a, 0x14400006, | ||
6757 | 0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0x0a000571, 0xae62fff0, | ||
6758 | 0xae63fff4, 0xacc00008, 0x3242ffff, 0x10560003, 0x31020004, 0x10400006, | ||
6759 | 0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020, 0x24020905, | ||
6760 | 0xa4c2000c, 0x8ee30000, 0x8ee20004, 0x14620007, 0x3c02b49a, 0x8ee20860, | ||
6761 | 0x54400001, 0x34e70400, 0x3c024b65, 0x0a000588, 0x34427654, 0x344289ab, | ||
6762 | 0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005a2, 0x00c02021, 0x3242ffff, | ||
6763 | 0x0056102b, 0x1440ff9b, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a, | ||
6764 | 0x1440ff48, 0x00000000, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, | ||
6765 | 0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, | ||
6766 | 0x03e00008, 0x27bd0048, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450, | ||
6767 | 0x8f634410, 0x0a0005b1, 0x00808021, 0x8f626820, 0x30422000, 0x10400003, | ||
6768 | 0x00000000, 0x0e0001f0, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff, | ||
6769 | 0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002, | ||
6770 | 0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c421b40, 0x3063000f, | ||
6771 | 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, 0x00000000, | ||
6772 | 0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820, | ||
6773 | 0x30422000, 0x1040fff8, 0x00000000, 0x0e0001f0, 0x00002021, 0x0a0005c4, | ||
6774 | 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, | ||
6775 | 0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, | ||
6776 | 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, | ||
6777 | 0x3c010800, 0xac221b54, 0x24020b78, 0x3c010800, 0xac221b64, 0x34630002, | ||
6778 | 0xaf634000, 0x0e000605, 0x00808021, 0x3c010800, 0xa0221b68, 0x304200ff, | ||
6779 | 0x24030002, 0x14430005, 0x00000000, 0x3c020800, 0x8c421b54, 0x0a0005f8, | ||
6780 | 0xac5000c0, 0x3c020800, 0x8c421b54, 0xac5000bc, 0x8f624434, 0x8f634438, | ||
6781 | 0x8f644410, 0x3c010800, 0xac221b5c, 0x3c010800, 0xac231b6c, 0x3c010800, | ||
6782 | 0xac241b58, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c040800, | ||
6783 | 0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 0x8cc20000, | ||
6784 | 0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, 0xac830000, 0x8cc20000, | ||
6785 | 0x50430001, 0x24050001, 0x3c020800, 0xac470000, 0x03e00008, 0x00a01021, | ||
6786 | 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe, | ||
6787 | 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008, | ||
6788 | 0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b5c, 0x00031c02, 0x0043102b, | ||
6789 | 0x14400008, 0x3c038000, 0x3c040800, 0x8c841b6c, 0x8f624450, 0x00021c02, | ||
6790 | 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, | ||
6791 | 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff, | ||
6792 | 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0a000648, 0x2402ffff, | ||
6793 | 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021, | ||
6794 | 0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, 0x8c631b58, 0x0a000651, | ||
6795 | 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000, | ||
6796 | 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040800, 0x24841af0, | ||
6797 | 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, | ||
6798 | 0x0a000660, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, | ||
6799 | 0x00000000, 0x00000000, 0x3c020800, 0x34423000, 0x3c030800, 0x34633000, | ||
6800 | 0x3c040800, 0x348437ff, 0x3c010800, 0xac221b74, 0x24020040, 0x3c010800, | ||
6801 | 0xac221b78, 0x3c010800, 0xac201b70, 0xac600000, 0x24630004, 0x0083102b, | ||
6802 | 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010, | ||
6803 | 0x3c020800, 0x8c421b70, 0x3c040800, 0x8c841b78, 0x8fab0014, 0x24430001, | ||
6804 | 0x0044102b, 0x3c010800, 0xac231b70, 0x14400003, 0x00004021, 0x3c010800, | ||
6805 | 0xac201b70, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, 0x91240000, | ||
6806 | 0x00021140, 0x00431021, 0x00481021, 0x25080001, 0xa0440000, 0x29020008, | ||
6807 | 0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, | ||
6808 | 0x8f64680c, 0x00021140, 0x00431021, 0xac440008, 0xac45000c, 0xac460010, | ||
6809 | 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, | ||
6810 | }; | ||
6811 | |||
6812 | static const u32 tg3TsoFwRodata[] = { | ||
6813 | 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, | ||
6814 | 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, | ||
6815 | 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, | ||
6816 | 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000, | ||
6817 | 0x00000000, | ||
6818 | }; | ||
6819 | |||
6820 | static const u32 tg3TsoFwData[] = { | ||
6821 | 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, | ||
6822 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
6823 | 0x00000000, | ||
6824 | }; | ||
6825 | |||
6826 | /* 5705 needs a special version of the TSO firmware. */ | 6378 | /* 5705 needs a special version of the TSO firmware. */ |
6827 | #define TG3_TSO5_FW_RELEASE_MAJOR 0x1 | ||
6828 | #define TG3_TSO5_FW_RELASE_MINOR 0x2 | ||
6829 | #define TG3_TSO5_FW_RELEASE_FIX 0x0 | ||
6830 | #define TG3_TSO5_FW_START_ADDR 0x00010000 | ||
6831 | #define TG3_TSO5_FW_TEXT_ADDR 0x00010000 | ||
6832 | #define TG3_TSO5_FW_TEXT_LEN 0xe90 | ||
6833 | #define TG3_TSO5_FW_RODATA_ADDR 0x00010e90 | ||
6834 | #define TG3_TSO5_FW_RODATA_LEN 0x50 | ||
6835 | #define TG3_TSO5_FW_DATA_ADDR 0x00010f00 | ||
6836 | #define TG3_TSO5_FW_DATA_LEN 0x20 | ||
6837 | #define TG3_TSO5_FW_SBSS_ADDR 0x00010f20 | ||
6838 | #define TG3_TSO5_FW_SBSS_LEN 0x28 | ||
6839 | #define TG3_TSO5_FW_BSS_ADDR 0x00010f50 | ||
6840 | #define TG3_TSO5_FW_BSS_LEN 0x88 | ||
6841 | |||
6842 | static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { | ||
6843 | 0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000, | ||
6844 | 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001, | ||
6845 | 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, | ||
6846 | 0xafbf0018, 0x0c0042e8, 0x34840002, 0x0c004364, 0x00000000, 0x3c030001, | ||
6847 | 0x90630f34, 0x24020002, 0x3c040001, 0x24840e9c, 0x14620003, 0x24050001, | ||
6848 | 0x3c040001, 0x24840e90, 0x24060002, 0x00003821, 0xafa00010, 0x0c004378, | ||
6849 | 0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, | ||
6850 | 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014, | ||
6851 | 0x0c0042d4, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400, | ||
6852 | 0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000, | ||
6853 | 0x0c004064, 0x00000000, 0x3c020001, 0x90420f56, 0x10510003, 0x32020200, | ||
6854 | 0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000, | ||
6855 | 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, | ||
6856 | 0x27bdffe0, 0x3c040001, 0x24840eb0, 0x00002821, 0x00003021, 0x00003821, | ||
6857 | 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130, | ||
6858 | 0xaf625000, 0x3c010001, 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018, | ||
6859 | 0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f60, | ||
6860 | 0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821, | ||
6861 | 0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000, | ||
6862 | 0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028, | ||
6863 | 0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f7a, 0x00041402, | ||
6864 | 0xa0a20000, 0x3c010001, 0xa0240f7b, 0x3c020001, 0x00431021, 0x94428014, | ||
6865 | 0x3c010001, 0xa0220f7c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff, | ||
6866 | 0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f60, 0x0124102b, | ||
6867 | 0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004, | ||
6868 | 0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8, | ||
6869 | 0x24c60008, 0x00003821, 0x3c080001, 0x25080f7b, 0x91060000, 0x3c020001, | ||
6870 | 0x90420f7c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021, | ||
6871 | 0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2, | ||
6872 | 0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a, | ||
6873 | 0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, | ||
6874 | 0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001, | ||
6875 | 0x080040fa, 0xac220f80, 0x3c050001, 0x24a50f7c, 0x90a20000, 0x3c0c0001, | ||
6876 | 0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021, | ||
6877 | 0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000, | ||
6878 | 0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f7c, | ||
6879 | 0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005, | ||
6880 | 0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006, | ||
6881 | 0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c, | ||
6882 | 0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c, | ||
6883 | 0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021, | ||
6884 | 0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001, | ||
6885 | 0x90420f7c, 0x3c030001, 0x90630f7a, 0x00e2c823, 0x3c020001, 0x90420f7b, | ||
6886 | 0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c, | ||
6887 | 0x3c010001, 0xa4220f78, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f76, | ||
6888 | 0x3c010001, 0xa4200f72, 0x00021400, 0x00431025, 0x3c010001, 0xac220f6c, | ||
6889 | 0x95020004, 0x3c010001, 0x08004124, 0xa4220f70, 0x3c020001, 0x94420f70, | ||
6890 | 0x3c030001, 0x94630f72, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f6c, | ||
6891 | 0xa4c20004, 0x3c020001, 0x8c420f6c, 0xa4c20006, 0x3c040001, 0x94840f72, | ||
6892 | 0x3c020001, 0x94420f70, 0x3c0a0001, 0x954a0f76, 0x00441821, 0x3063ffff, | ||
6893 | 0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f78, | ||
6894 | 0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f78, | ||
6895 | 0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005, | ||
6896 | 0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d, | ||
6897 | 0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0f80, 0x10800005, | ||
6898 | 0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027, | ||
6899 | 0xa502000a, 0x3c030001, 0x90630f7b, 0x31a2ffff, 0x00e21021, 0x0800418d, | ||
6900 | 0x00432023, 0x3c020001, 0x94420f80, 0x00442021, 0x00041c02, 0x3082ffff, | ||
6901 | 0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001, | ||
6902 | 0x24a50f7a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000, | ||
6903 | 0x00e21023, 0xa5020002, 0x3c030001, 0x94630f80, 0x3c020001, 0x94420f5a, | ||
6904 | 0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff, | ||
6905 | 0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f7c, 0x24620001, | ||
6906 | 0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200, | ||
6907 | 0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001, | ||
6908 | 0x94420f82, 0x3183ffff, 0x3c040001, 0x90840f7b, 0x00431021, 0x00e21021, | ||
6909 | 0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, | ||
6910 | 0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00, | ||
6911 | 0x00431025, 0x3c040001, 0x24840f72, 0xade20010, 0x94820000, 0x3c050001, | ||
6912 | 0x94a50f76, 0x3c030001, 0x8c630f6c, 0x24420001, 0x00b92821, 0xa4820000, | ||
6913 | 0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f76, 0x10600003, | ||
6914 | 0x24a2ffff, 0x3c010001, 0xa4220f76, 0x3c024000, 0x03021025, 0x3c010001, | ||
6915 | 0xac240f6c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f56, | ||
6916 | 0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4, | ||
6917 | 0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f64, | ||
6918 | 0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088, | ||
6919 | 0x24020008, 0x3c010001, 0xa4220f68, 0x30620004, 0x10400005, 0x24020001, | ||
6920 | 0x3c010001, 0xa0220f57, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f57, | ||
6921 | 0x00031402, 0x3c010001, 0xa4220f54, 0x9483000c, 0x24020001, 0x3c010001, | ||
6922 | 0xa4200f50, 0x3c010001, 0xa0220f56, 0x3c010001, 0xa4230f62, 0x24020001, | ||
6923 | 0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000, | ||
6924 | 0x080042cf, 0x00000000, 0x3c020001, 0x94420f62, 0x241a0001, 0x3c010001, | ||
6925 | 0xa4200f5e, 0x3c010001, 0xa4200f52, 0x304407ff, 0x00021bc2, 0x00031823, | ||
6926 | 0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001, | ||
6927 | 0xa4240f58, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f5a, 0x3c010001, | ||
6928 | 0xa4230f5c, 0x3c060001, 0x24c60f52, 0x94c50000, 0x94c30002, 0x3c040001, | ||
6929 | 0x94840f5a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021, | ||
6930 | 0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008, | ||
6931 | 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, | ||
6932 | 0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001, | ||
6933 | 0x94630f50, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001, | ||
6934 | 0xa4230f50, 0xaf620ce8, 0x3c020001, 0x94420f68, 0x34420024, 0xaf620cec, | ||
6935 | 0x94c30002, 0x3c020001, 0x94420f50, 0x14620012, 0x3c028000, 0x3c108000, | ||
6936 | 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008, 0x00901024, | ||
6937 | 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, | ||
6938 | 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000, | ||
6939 | 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, | ||
6940 | 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, | ||
6941 | 0x3c070001, 0x24e70f50, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001, | ||
6942 | 0x8c420f64, 0xaf620ce4, 0x3c050001, 0x94a50f54, 0x94e30000, 0x3c040001, | ||
6943 | 0x94840f58, 0x3c020001, 0x94420f5e, 0x00a32823, 0x00822023, 0x30a6ffff, | ||
6944 | 0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f5c, | ||
6945 | 0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f54, | ||
6946 | 0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001, | ||
6947 | 0x90420f57, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624, | ||
6948 | 0x0800427c, 0x0000d021, 0x3c020001, 0x94420f68, 0x3c030008, 0x34630624, | ||
6949 | 0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001, | ||
6950 | 0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, | ||
6951 | 0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283, | ||
6952 | 0x00000000, 0x3c030001, 0x94630f68, 0x34420624, 0x3c108000, 0x00621825, | ||
6953 | 0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003, | ||
6954 | 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, | ||
6955 | 0x00000000, 0x3c010001, 0x080042cf, 0xa4200f5e, 0x3c020001, 0x94420f5c, | ||
6956 | 0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f57, 0x10400009, | ||
6957 | 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624, 0x0000d021, 0x00431025, | ||
6958 | 0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f68, 0x3c030008, | ||
6959 | 0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f5e, 0x00451021, | ||
6960 | 0x3c010001, 0xa4220f5e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001, | ||
6961 | 0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, | ||
6962 | 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014, | ||
6963 | 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, 0x27bdffe0, 0x3c040001, | ||
6964 | 0x24840ec0, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, | ||
6965 | 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001, | ||
6966 | 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018, 0x03e00008, 0x27bd0020, | ||
6967 | 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804, | ||
6968 | 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 0xac220f20, | ||
6969 | 0x24020b78, 0x3c010001, 0xac220f30, 0x34630002, 0xaf634000, 0x0c004315, | ||
6970 | 0x00808021, 0x3c010001, 0xa0220f34, 0x304200ff, 0x24030002, 0x14430005, | ||
6971 | 0x00000000, 0x3c020001, 0x8c420f20, 0x08004308, 0xac5000c0, 0x3c020001, | ||
6972 | 0x8c420f20, 0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010001, | ||
6973 | 0xac220f28, 0x3c010001, 0xac230f38, 0x3c010001, 0xac240f24, 0x8fbf0014, | ||
6974 | 0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, 0x24020001, 0x27bdfff8, | ||
6975 | 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000, | ||
6976 | 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008, | ||
6977 | 0x8f634450, 0x3c020001, 0x8c420f28, 0x00031c02, 0x0043102b, 0x14400008, | ||
6978 | 0x3c038000, 0x3c040001, 0x8c840f38, 0x8f624450, 0x00021c02, 0x0083102b, | ||
6979 | 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd, | ||
6980 | 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff, 0x2442e000, | ||
6981 | 0x2c422001, 0x14400003, 0x3c024000, 0x08004347, 0x2402ffff, 0x00822025, | ||
6982 | 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021, 0x03e00008, | ||
6983 | 0x00000000, 0x8f624450, 0x3c030001, 0x8c630f24, 0x08004350, 0x3042ffff, | ||
6984 | 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000, 0x03e00008, | ||
6985 | 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, 0x24840ed0, 0x00003021, | ||
6986 | 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0800435f, | ||
6987 | 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x3c020001, 0x3442d600, | ||
6988 | 0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 0xac220f40, | ||
6989 | 0x24020040, 0x3c010001, 0xac220f44, 0x3c010001, 0xac200f3c, 0xac600000, | ||
6990 | 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, | ||
6991 | 0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f3c, 0x3c040001, 0x8c840f44, | ||
6992 | 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, 0xac230f3c, 0x14400003, | ||
6993 | 0x00004021, 0x3c010001, 0xac200f3c, 0x3c020001, 0x8c420f3c, 0x3c030001, | ||
6994 | 0x8c630f40, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001, | ||
6995 | 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020001, 0x8c420f3c, | ||
6996 | 0x3c030001, 0x8c630f40, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008, | ||
6997 | 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, | ||
6998 | 0x00000000, 0x00000000, 0x00000000, | ||
6999 | }; | ||
7000 | |||
7001 | static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { | ||
7002 | 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, | ||
7003 | 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, | ||
7004 | 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, | ||
7005 | 0x00000000, 0x00000000, 0x00000000, | ||
7006 | }; | ||
7007 | |||
7008 | static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { | ||
7009 | 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, | ||
7010 | 0x00000000, 0x00000000, 0x00000000, | ||
7011 | }; | ||
7012 | 6379 | ||
7013 | /* tp->lock is held. */ | 6380 | /* tp->lock is held. */ |
7014 | static int tg3_load_tso_firmware(struct tg3 *tp) | 6381 | static int tg3_load_tso_firmware(struct tg3 *tp) |
7015 | { | 6382 | { |
7016 | struct fw_info info; | 6383 | struct fw_info info; |
6384 | const __be32 *fw_data; | ||
7017 | unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; | 6385 | unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; |
7018 | int err, i; | 6386 | int err, i; |
7019 | 6387 | ||
7020 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) | 6388 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) |
7021 | return 0; | 6389 | return 0; |
7022 | 6390 | ||
6391 | fw_data = (void *)tp->fw->data; | ||
6392 | |||
6393 | /* Firmware blob starts with version numbers, followed by | ||
6394 | start address and length. We are setting complete length. | ||
6395 | length = end_address_of_bss - start_address_of_text. | ||
6396 | Remainder is the blob to be loaded contiguously | ||
6397 | from start address. */ | ||
6398 | |||
6399 | info.fw_base = be32_to_cpu(fw_data[1]); | ||
6400 | cpu_scratch_size = tp->fw_len; | ||
6401 | info.fw_len = tp->fw->size - 12; | ||
6402 | info.fw_data = &fw_data[3]; | ||
6403 | |||
7023 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { | 6404 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { |
7024 | info.text_base = TG3_TSO5_FW_TEXT_ADDR; | ||
7025 | info.text_len = TG3_TSO5_FW_TEXT_LEN; | ||
7026 | info.text_data = &tg3Tso5FwText[0]; | ||
7027 | info.rodata_base = TG3_TSO5_FW_RODATA_ADDR; | ||
7028 | info.rodata_len = TG3_TSO5_FW_RODATA_LEN; | ||
7029 | info.rodata_data = &tg3Tso5FwRodata[0]; | ||
7030 | info.data_base = TG3_TSO5_FW_DATA_ADDR; | ||
7031 | info.data_len = TG3_TSO5_FW_DATA_LEN; | ||
7032 | info.data_data = &tg3Tso5FwData[0]; | ||
7033 | cpu_base = RX_CPU_BASE; | 6405 | cpu_base = RX_CPU_BASE; |
7034 | cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705; | 6406 | cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705; |
7035 | cpu_scratch_size = (info.text_len + | ||
7036 | info.rodata_len + | ||
7037 | info.data_len + | ||
7038 | TG3_TSO5_FW_SBSS_LEN + | ||
7039 | TG3_TSO5_FW_BSS_LEN); | ||
7040 | } else { | 6407 | } else { |
7041 | info.text_base = TG3_TSO_FW_TEXT_ADDR; | ||
7042 | info.text_len = TG3_TSO_FW_TEXT_LEN; | ||
7043 | info.text_data = &tg3TsoFwText[0]; | ||
7044 | info.rodata_base = TG3_TSO_FW_RODATA_ADDR; | ||
7045 | info.rodata_len = TG3_TSO_FW_RODATA_LEN; | ||
7046 | info.rodata_data = &tg3TsoFwRodata[0]; | ||
7047 | info.data_base = TG3_TSO_FW_DATA_ADDR; | ||
7048 | info.data_len = TG3_TSO_FW_DATA_LEN; | ||
7049 | info.data_data = &tg3TsoFwData[0]; | ||
7050 | cpu_base = TX_CPU_BASE; | 6408 | cpu_base = TX_CPU_BASE; |
7051 | cpu_scratch_base = TX_CPU_SCRATCH_BASE; | 6409 | cpu_scratch_base = TX_CPU_SCRATCH_BASE; |
7052 | cpu_scratch_size = TX_CPU_SCRATCH_SIZE; | 6410 | cpu_scratch_size = TX_CPU_SCRATCH_SIZE; |
@@ -7060,21 +6418,21 @@ static int tg3_load_tso_firmware(struct tg3 *tp) | |||
7060 | 6418 | ||
7061 | /* Now startup the cpu. */ | 6419 | /* Now startup the cpu. */ |
7062 | tw32(cpu_base + CPU_STATE, 0xffffffff); | 6420 | tw32(cpu_base + CPU_STATE, 0xffffffff); |
7063 | tw32_f(cpu_base + CPU_PC, info.text_base); | 6421 | tw32_f(cpu_base + CPU_PC, info.fw_base); |
7064 | 6422 | ||
7065 | for (i = 0; i < 5; i++) { | 6423 | for (i = 0; i < 5; i++) { |
7066 | if (tr32(cpu_base + CPU_PC) == info.text_base) | 6424 | if (tr32(cpu_base + CPU_PC) == info.fw_base) |
7067 | break; | 6425 | break; |
7068 | tw32(cpu_base + CPU_STATE, 0xffffffff); | 6426 | tw32(cpu_base + CPU_STATE, 0xffffffff); |
7069 | tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); | 6427 | tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); |
7070 | tw32_f(cpu_base + CPU_PC, info.text_base); | 6428 | tw32_f(cpu_base + CPU_PC, info.fw_base); |
7071 | udelay(1000); | 6429 | udelay(1000); |
7072 | } | 6430 | } |
7073 | if (i >= 5) { | 6431 | if (i >= 5) { |
7074 | printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s " | 6432 | printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s " |
7075 | "to set CPU PC, is %08x should be %08x\n", | 6433 | "to set CPU PC, is %08x should be %08x\n", |
7076 | tp->dev->name, tr32(cpu_base + CPU_PC), | 6434 | tp->dev->name, tr32(cpu_base + CPU_PC), |
7077 | info.text_base); | 6435 | info.fw_base); |
7078 | return -ENODEV; | 6436 | return -ENODEV; |
7079 | } | 6437 | } |
7080 | tw32(cpu_base + CPU_STATE, 0xffffffff); | 6438 | tw32(cpu_base + CPU_STATE, 0xffffffff); |
@@ -7299,11 +6657,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) | |||
7299 | else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { | 6657 | else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { |
7300 | int fw_len; | 6658 | int fw_len; |
7301 | 6659 | ||
7302 | fw_len = (TG3_TSO5_FW_TEXT_LEN + | 6660 | fw_len = tp->fw_len; |
7303 | TG3_TSO5_FW_RODATA_LEN + | ||
7304 | TG3_TSO5_FW_DATA_LEN + | ||
7305 | TG3_TSO5_FW_SBSS_LEN + | ||
7306 | TG3_TSO5_FW_BSS_LEN); | ||
7307 | fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1); | 6661 | fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1); |
7308 | tw32(BUFMGR_MB_POOL_ADDR, | 6662 | tw32(BUFMGR_MB_POOL_ADDR, |
7309 | NIC_SRAM_MBUF_POOL_BASE5705 + fw_len); | 6663 | NIC_SRAM_MBUF_POOL_BASE5705 + fw_len); |
@@ -13580,6 +12934,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13580 | struct net_device *dev; | 12934 | struct net_device *dev; |
13581 | struct tg3 *tp; | 12935 | struct tg3 *tp; |
13582 | int err, pm_cap; | 12936 | int err, pm_cap; |
12937 | const char *fw_name = NULL; | ||
13583 | char str[40]; | 12938 | char str[40]; |
13584 | u64 dma_mask, persist_dma_mask; | 12939 | u64 dma_mask, persist_dma_mask; |
13585 | 12940 | ||
@@ -13735,6 +13090,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13735 | 13090 | ||
13736 | tg3_init_bufmgr_config(tp); | 13091 | tg3_init_bufmgr_config(tp); |
13737 | 13092 | ||
13093 | if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) | ||
13094 | fw_name = FIRMWARE_TG3; | ||
13095 | |||
13738 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { | 13096 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { |
13739 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; | 13097 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; |
13740 | } | 13098 | } |
@@ -13747,6 +13105,37 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13747 | } else { | 13105 | } else { |
13748 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG; | 13106 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG; |
13749 | } | 13107 | } |
13108 | if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { | ||
13109 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) | ||
13110 | fw_name = FIRMWARE_TG3TSO5; | ||
13111 | else | ||
13112 | fw_name = FIRMWARE_TG3TSO; | ||
13113 | } | ||
13114 | |||
13115 | if (fw_name) { | ||
13116 | const __be32 *fw_data; | ||
13117 | |||
13118 | err = request_firmware(&tp->fw, fw_name, &tp->pdev->dev); | ||
13119 | if (err) { | ||
13120 | printk(KERN_ERR "tg3: Failed to load firmware \"%s\"\n", | ||
13121 | fw_name); | ||
13122 | goto err_out_iounmap; | ||
13123 | } | ||
13124 | |||
13125 | fw_data = (void *)tp->fw->data; | ||
13126 | |||
13127 | /* Firmware blob starts with version numbers, followed by | ||
13128 | start address and _full_ length including BSS sections | ||
13129 | (which must be longer than the actual data, of course */ | ||
13130 | |||
13131 | tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ | ||
13132 | if (tp->fw_len < (tp->fw->size - 12)) { | ||
13133 | printk(KERN_ERR "tg3: bogus length %d in \"%s\"\n", | ||
13134 | tp->fw_len, fw_name); | ||
13135 | err = -EINVAL; | ||
13136 | goto err_out_fw; | ||
13137 | } | ||
13138 | } | ||
13750 | 13139 | ||
13751 | /* TSO is on by default on chips that support hardware TSO. | 13140 | /* TSO is on by default on chips that support hardware TSO. |
13752 | * Firmware TSO on older chips gives lower performance, so it | 13141 | * Firmware TSO on older chips gives lower performance, so it |
@@ -13778,7 +13167,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13778 | if (err) { | 13167 | if (err) { |
13779 | printk(KERN_ERR PFX "Could not obtain valid ethernet address, " | 13168 | printk(KERN_ERR PFX "Could not obtain valid ethernet address, " |
13780 | "aborting.\n"); | 13169 | "aborting.\n"); |
13781 | goto err_out_iounmap; | 13170 | goto err_out_fw; |
13782 | } | 13171 | } |
13783 | 13172 | ||
13784 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { | 13173 | if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { |
@@ -13787,7 +13176,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13787 | printk(KERN_ERR PFX "Cannot map APE registers, " | 13176 | printk(KERN_ERR PFX "Cannot map APE registers, " |
13788 | "aborting.\n"); | 13177 | "aborting.\n"); |
13789 | err = -ENOMEM; | 13178 | err = -ENOMEM; |
13790 | goto err_out_iounmap; | 13179 | goto err_out_fw; |
13791 | } | 13180 | } |
13792 | 13181 | ||
13793 | tg3_ape_lock_init(tp); | 13182 | tg3_ape_lock_init(tp); |
@@ -13867,6 +13256,10 @@ err_out_apeunmap: | |||
13867 | tp->aperegs = NULL; | 13256 | tp->aperegs = NULL; |
13868 | } | 13257 | } |
13869 | 13258 | ||
13259 | err_out_fw: | ||
13260 | if (tp->fw) | ||
13261 | release_firmware(tp->fw); | ||
13262 | |||
13870 | err_out_iounmap: | 13263 | err_out_iounmap: |
13871 | if (tp->regs) { | 13264 | if (tp->regs) { |
13872 | iounmap(tp->regs); | 13265 | iounmap(tp->regs); |
@@ -13892,6 +13285,9 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
13892 | if (dev) { | 13285 | if (dev) { |
13893 | struct tg3 *tp = netdev_priv(dev); | 13286 | struct tg3 *tp = netdev_priv(dev); |
13894 | 13287 | ||
13288 | if (tp->fw) | ||
13289 | release_firmware(tp->fw); | ||
13290 | |||
13895 | flush_scheduled_work(); | 13291 | flush_scheduled_work(); |
13896 | 13292 | ||
13897 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { | 13293 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 8936edfb0438..ae5da603c6af 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2762,6 +2762,10 @@ struct tg3 { | |||
2762 | #define SST_25VF0X0_PAGE_SIZE 4098 | 2762 | #define SST_25VF0X0_PAGE_SIZE 4098 |
2763 | 2763 | ||
2764 | struct ethtool_coalesce coal; | 2764 | struct ethtool_coalesce coal; |
2765 | |||
2766 | /* firmware info */ | ||
2767 | const struct firmware *fw; | ||
2768 | u32 fw_len; /* includes BSS */ | ||
2765 | }; | 2769 | }; |
2766 | 2770 | ||
2767 | #endif /* !(_T3_H) */ | 2771 | #endif /* !(_T3_H) */ |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 69f9a0ec764d..d7b81e4fdd56 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -213,7 +213,7 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb) | |||
213 | 213 | ||
214 | /* Network device part of the driver */ | 214 | /* Network device part of the driver */ |
215 | 215 | ||
216 | static unsigned int tun_net_id; | 216 | static int tun_net_id; |
217 | struct tun_net { | 217 | struct tun_net { |
218 | struct list_head dev_list; | 218 | struct list_head dev_list; |
219 | }; | 219 | }; |
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index ddc4c59f02dc..b7e4cee24269 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c | |||
@@ -29,9 +29,6 @@ static struct inode *oprofilefs_get_inode(struct super_block *sb, int mode) | |||
29 | 29 | ||
30 | if (inode) { | 30 | if (inode) { |
31 | inode->i_mode = mode; | 31 | inode->i_mode = mode; |
32 | inode->i_uid = 0; | ||
33 | inode->i_gid = 0; | ||
34 | inode->i_blocks = 0; | ||
35 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 32 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
36 | } | 33 | } |
37 | return inode; | 34 | return inode; |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 8e0c2b47803c..668472405a57 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -29,6 +29,13 @@ config APM_POWER | |||
29 | Say Y here to enable support APM status emulation using | 29 | Say Y here to enable support APM status emulation using |
30 | battery class devices. | 30 | battery class devices. |
31 | 31 | ||
32 | config WM8350_POWER | ||
33 | tristate "WM8350 PMU support" | ||
34 | depends on MFD_WM8350 | ||
35 | help | ||
36 | Say Y here to enable support for the power management unit | ||
37 | provided by the Wolfson Microelectronics WM8350 PMIC. | ||
38 | |||
32 | config BATTERY_DS2760 | 39 | config BATTERY_DS2760 |
33 | tristate "DS2760 battery driver (HP iPAQ & others)" | 40 | tristate "DS2760 battery driver (HP iPAQ & others)" |
34 | select W1 | 41 | select W1 |
@@ -68,4 +75,11 @@ config BATTERY_BQ27x00 | |||
68 | help | 75 | help |
69 | Say Y here to enable support for batteries with BQ27200(I2C) chip. | 76 | Say Y here to enable support for batteries with BQ27200(I2C) chip. |
70 | 77 | ||
78 | config BATTERY_DA9030 | ||
79 | tristate "DA9030 battery driver" | ||
80 | depends on PMIC_DA903X | ||
81 | help | ||
82 | Say Y here to enable support for batteries charger integrated into | ||
83 | DA9030 PMIC. | ||
84 | |||
71 | endif # POWER_SUPPLY | 85 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index e8f1ecec5d8f..eebb15505a40 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o | |||
16 | 16 | ||
17 | obj-$(CONFIG_PDA_POWER) += pda_power.o | 17 | obj-$(CONFIG_PDA_POWER) += pda_power.o |
18 | obj-$(CONFIG_APM_POWER) += apm_power.o | 18 | obj-$(CONFIG_APM_POWER) += apm_power.o |
19 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o | ||
19 | 20 | ||
20 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o | 21 | obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o |
21 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o | 22 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o |
@@ -23,3 +24,4 @@ obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o | |||
23 | obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o | 24 | obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o |
24 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o | 25 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o |
25 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | 26 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o |
27 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | ||
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c new file mode 100644 index 000000000000..1662bb0f23a5 --- /dev/null +++ b/drivers/power/da9030_battery.c | |||
@@ -0,0 +1,600 @@ | |||
1 | /* | ||
2 | * Battery charger driver for Dialog Semiconductor DA9030 | ||
3 | * | ||
4 | * Copyright (C) 2008 Compulab, Ltd. | ||
5 | * Mike Rapoport <mike@compulab.co.il> | ||
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 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/workqueue.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/power_supply.h> | ||
20 | #include <linux/mfd/da903x.h> | ||
21 | |||
22 | #include <linux/debugfs.h> | ||
23 | #include <linux/seq_file.h> | ||
24 | |||
25 | #define DA9030_STATUS_CHDET (1 << 3) | ||
26 | |||
27 | #define DA9030_FAULT_LOG 0x0a | ||
28 | #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) | ||
29 | #define DA9030_FAULT_LOG_VBAT_OVER (1 << 4) | ||
30 | |||
31 | #define DA9030_CHARGE_CONTROL 0x28 | ||
32 | #define DA9030_CHRG_CHARGER_ENABLE (1 << 7) | ||
33 | |||
34 | #define DA9030_ADC_MAN_CONTROL 0x30 | ||
35 | #define DA9030_ADC_TBATREF_ENABLE (1 << 5) | ||
36 | #define DA9030_ADC_LDO_INT_ENABLE (1 << 4) | ||
37 | |||
38 | #define DA9030_ADC_AUTO_CONTROL 0x31 | ||
39 | #define DA9030_ADC_TBAT_ENABLE (1 << 5) | ||
40 | #define DA9030_ADC_VBAT_IN_TXON (1 << 4) | ||
41 | #define DA9030_ADC_VCH_ENABLE (1 << 3) | ||
42 | #define DA9030_ADC_ICH_ENABLE (1 << 2) | ||
43 | #define DA9030_ADC_VBAT_ENABLE (1 << 1) | ||
44 | #define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0) | ||
45 | |||
46 | #define DA9030_VBATMON 0x32 | ||
47 | #define DA9030_VBATMONTXON 0x33 | ||
48 | #define DA9030_TBATHIGHP 0x34 | ||
49 | #define DA9030_TBATHIGHN 0x35 | ||
50 | #define DA9030_TBATLOW 0x36 | ||
51 | |||
52 | #define DA9030_VBAT_RES 0x41 | ||
53 | #define DA9030_VBATMIN_RES 0x42 | ||
54 | #define DA9030_VBATMINTXON_RES 0x43 | ||
55 | #define DA9030_ICHMAX_RES 0x44 | ||
56 | #define DA9030_ICHMIN_RES 0x45 | ||
57 | #define DA9030_ICHAVERAGE_RES 0x46 | ||
58 | #define DA9030_VCHMAX_RES 0x47 | ||
59 | #define DA9030_VCHMIN_RES 0x48 | ||
60 | #define DA9030_TBAT_RES 0x49 | ||
61 | |||
62 | struct da9030_adc_res { | ||
63 | uint8_t vbat_res; | ||
64 | uint8_t vbatmin_res; | ||
65 | uint8_t vbatmintxon; | ||
66 | uint8_t ichmax_res; | ||
67 | uint8_t ichmin_res; | ||
68 | uint8_t ichaverage_res; | ||
69 | uint8_t vchmax_res; | ||
70 | uint8_t vchmin_res; | ||
71 | uint8_t tbat_res; | ||
72 | uint8_t adc_in4_res; | ||
73 | uint8_t adc_in5_res; | ||
74 | }; | ||
75 | |||
76 | struct da9030_battery_thresholds { | ||
77 | int tbat_low; | ||
78 | int tbat_high; | ||
79 | int tbat_restart; | ||
80 | |||
81 | int vbat_low; | ||
82 | int vbat_crit; | ||
83 | int vbat_charge_start; | ||
84 | int vbat_charge_stop; | ||
85 | int vbat_charge_restart; | ||
86 | |||
87 | int vcharge_min; | ||
88 | int vcharge_max; | ||
89 | }; | ||
90 | |||
91 | struct da9030_charger { | ||
92 | struct power_supply psy; | ||
93 | |||
94 | struct device *master; | ||
95 | |||
96 | struct da9030_adc_res adc; | ||
97 | struct delayed_work work; | ||
98 | unsigned int interval; | ||
99 | |||
100 | struct power_supply_info *battery_info; | ||
101 | |||
102 | struct da9030_battery_thresholds thresholds; | ||
103 | |||
104 | unsigned int charge_milliamp; | ||
105 | unsigned int charge_millivolt; | ||
106 | |||
107 | /* charger status */ | ||
108 | bool chdet; | ||
109 | uint8_t fault; | ||
110 | int mA; | ||
111 | int mV; | ||
112 | bool is_on; | ||
113 | |||
114 | struct notifier_block nb; | ||
115 | |||
116 | /* platform callbacks for battery low and critical events */ | ||
117 | void (*battery_low)(void); | ||
118 | void (*battery_critical)(void); | ||
119 | |||
120 | struct dentry *debug_file; | ||
121 | }; | ||
122 | |||
123 | static inline int da9030_reg_to_mV(int reg) | ||
124 | { | ||
125 | return ((reg * 2650) >> 8) + 2650; | ||
126 | } | ||
127 | |||
128 | static inline int da9030_millivolt_to_reg(int mV) | ||
129 | { | ||
130 | return ((mV - 2650) << 8) / 2650; | ||
131 | } | ||
132 | |||
133 | static inline int da9030_reg_to_mA(int reg) | ||
134 | { | ||
135 | return ((reg * 24000) >> 8) / 15; | ||
136 | } | ||
137 | |||
138 | #ifdef CONFIG_DEBUG_FS | ||
139 | static int bat_debug_show(struct seq_file *s, void *data) | ||
140 | { | ||
141 | struct da9030_charger *charger = s->private; | ||
142 | |||
143 | seq_printf(s, "charger is %s\n", charger->is_on ? "on" : "off"); | ||
144 | if (charger->chdet) { | ||
145 | seq_printf(s, "iset = %dmA, vset = %dmV\n", | ||
146 | charger->mA, charger->mV); | ||
147 | } | ||
148 | |||
149 | seq_printf(s, "vbat_res = %d (%dmV)\n", | ||
150 | charger->adc.vbat_res, | ||
151 | da9030_reg_to_mV(charger->adc.vbat_res)); | ||
152 | seq_printf(s, "vbatmin_res = %d (%dmV)\n", | ||
153 | charger->adc.vbatmin_res, | ||
154 | da9030_reg_to_mV(charger->adc.vbatmin_res)); | ||
155 | seq_printf(s, "vbatmintxon = %d (%dmV)\n", | ||
156 | charger->adc.vbatmintxon, | ||
157 | da9030_reg_to_mV(charger->adc.vbatmintxon)); | ||
158 | seq_printf(s, "ichmax_res = %d (%dmA)\n", | ||
159 | charger->adc.ichmax_res, | ||
160 | da9030_reg_to_mV(charger->adc.ichmax_res)); | ||
161 | seq_printf(s, "ichmin_res = %d (%dmA)\n", | ||
162 | charger->adc.ichmin_res, | ||
163 | da9030_reg_to_mA(charger->adc.ichmin_res)); | ||
164 | seq_printf(s, "ichaverage_res = %d (%dmA)\n", | ||
165 | charger->adc.ichaverage_res, | ||
166 | da9030_reg_to_mA(charger->adc.ichaverage_res)); | ||
167 | seq_printf(s, "vchmax_res = %d (%dmV)\n", | ||
168 | charger->adc.vchmax_res, | ||
169 | da9030_reg_to_mA(charger->adc.vchmax_res)); | ||
170 | seq_printf(s, "vchmin_res = %d (%dmV)\n", | ||
171 | charger->adc.vchmin_res, | ||
172 | da9030_reg_to_mV(charger->adc.vchmin_res)); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int debug_open(struct inode *inode, struct file *file) | ||
178 | { | ||
179 | return single_open(file, bat_debug_show, inode->i_private); | ||
180 | } | ||
181 | |||
182 | static const struct file_operations bat_debug_fops = { | ||
183 | .open = debug_open, | ||
184 | .read = seq_read, | ||
185 | .llseek = seq_lseek, | ||
186 | .release = single_release, | ||
187 | }; | ||
188 | |||
189 | static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger) | ||
190 | { | ||
191 | charger->debug_file = debugfs_create_file("charger", 0666, 0, charger, | ||
192 | &bat_debug_fops); | ||
193 | return charger->debug_file; | ||
194 | } | ||
195 | |||
196 | static void da9030_bat_remove_debugfs(struct da9030_charger *charger) | ||
197 | { | ||
198 | debugfs_remove(charger->debug_file); | ||
199 | } | ||
200 | #else | ||
201 | static inline struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger) | ||
202 | { | ||
203 | return NULL; | ||
204 | } | ||
205 | static inline void da9030_bat_remove_debugfs(struct da9030_charger *charger) | ||
206 | { | ||
207 | } | ||
208 | #endif | ||
209 | |||
210 | static inline void da9030_read_adc(struct da9030_charger *charger, | ||
211 | struct da9030_adc_res *adc) | ||
212 | { | ||
213 | da903x_reads(charger->master, DA9030_VBAT_RES, | ||
214 | sizeof(*adc), (uint8_t *)adc); | ||
215 | } | ||
216 | |||
217 | static void da9030_charger_update_state(struct da9030_charger *charger) | ||
218 | { | ||
219 | uint8_t val; | ||
220 | |||
221 | da903x_read(charger->master, DA9030_CHARGE_CONTROL, &val); | ||
222 | charger->is_on = (val & DA9030_CHRG_CHARGER_ENABLE) ? 1 : 0; | ||
223 | charger->mA = ((val >> 3) & 0xf) * 100; | ||
224 | charger->mV = (val & 0x7) * 50 + 4000; | ||
225 | |||
226 | da9030_read_adc(charger, &charger->adc); | ||
227 | da903x_read(charger->master, DA9030_FAULT_LOG, &charger->fault); | ||
228 | charger->chdet = da903x_query_status(charger->master, | ||
229 | DA9030_STATUS_CHDET); | ||
230 | } | ||
231 | |||
232 | static void da9030_set_charge(struct da9030_charger *charger, int on) | ||
233 | { | ||
234 | uint8_t val; | ||
235 | |||
236 | if (on) { | ||
237 | val = DA9030_CHRG_CHARGER_ENABLE; | ||
238 | val |= (charger->charge_milliamp / 100) << 3; | ||
239 | val |= (charger->charge_millivolt - 4000) / 50; | ||
240 | charger->is_on = 1; | ||
241 | } else { | ||
242 | val = 0; | ||
243 | charger->is_on = 0; | ||
244 | } | ||
245 | |||
246 | da903x_write(charger->master, DA9030_CHARGE_CONTROL, val); | ||
247 | } | ||
248 | |||
249 | static void da9030_charger_check_state(struct da9030_charger *charger) | ||
250 | { | ||
251 | da9030_charger_update_state(charger); | ||
252 | |||
253 | /* we wake or boot with external power on */ | ||
254 | if (!charger->is_on) { | ||
255 | if ((charger->chdet) && | ||
256 | (charger->adc.vbat_res < | ||
257 | charger->thresholds.vbat_charge_start)) { | ||
258 | da9030_set_charge(charger, 1); | ||
259 | } | ||
260 | } else { | ||
261 | if (charger->adc.vbat_res >= | ||
262 | charger->thresholds.vbat_charge_stop) { | ||
263 | da9030_set_charge(charger, 0); | ||
264 | da903x_write(charger->master, DA9030_VBATMON, | ||
265 | charger->thresholds.vbat_charge_restart); | ||
266 | } else if (charger->adc.vbat_res > | ||
267 | charger->thresholds.vbat_low) { | ||
268 | /* we are charging and passed LOW_THRESH, | ||
269 | so upate DA9030 VBAT threshold | ||
270 | */ | ||
271 | da903x_write(charger->master, DA9030_VBATMON, | ||
272 | charger->thresholds.vbat_low); | ||
273 | } | ||
274 | if (charger->adc.vchmax_res > charger->thresholds.vcharge_max || | ||
275 | charger->adc.vchmin_res < charger->thresholds.vcharge_min || | ||
276 | /* Tempreture readings are negative */ | ||
277 | charger->adc.tbat_res < charger->thresholds.tbat_high || | ||
278 | charger->adc.tbat_res > charger->thresholds.tbat_low) { | ||
279 | /* disable charger */ | ||
280 | da9030_set_charge(charger, 0); | ||
281 | } | ||
282 | } | ||
283 | } | ||
284 | |||
285 | static void da9030_charging_monitor(struct work_struct *work) | ||
286 | { | ||
287 | struct da9030_charger *charger; | ||
288 | |||
289 | charger = container_of(work, struct da9030_charger, work.work); | ||
290 | |||
291 | da9030_charger_check_state(charger); | ||
292 | |||
293 | /* reschedule for the next time */ | ||
294 | schedule_delayed_work(&charger->work, charger->interval); | ||
295 | } | ||
296 | |||
297 | static enum power_supply_property da9030_battery_props[] = { | ||
298 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
299 | POWER_SUPPLY_PROP_STATUS, | ||
300 | POWER_SUPPLY_PROP_HEALTH, | ||
301 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
302 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
303 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
304 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
305 | POWER_SUPPLY_PROP_CURRENT_AVG, | ||
306 | }; | ||
307 | |||
308 | static void da9030_battery_check_status(struct da9030_charger *charger, | ||
309 | union power_supply_propval *val) | ||
310 | { | ||
311 | if (charger->chdet) { | ||
312 | if (charger->is_on) | ||
313 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
314 | else | ||
315 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
316 | } else { | ||
317 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | static void da9030_battery_check_health(struct da9030_charger *charger, | ||
322 | union power_supply_propval *val) | ||
323 | { | ||
324 | if (charger->fault & DA9030_FAULT_LOG_OVER_TEMP) | ||
325 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
326 | else if (charger->fault & DA9030_FAULT_LOG_VBAT_OVER) | ||
327 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
328 | else | ||
329 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
330 | } | ||
331 | |||
332 | static int da9030_battery_get_property(struct power_supply *psy, | ||
333 | enum power_supply_property psp, | ||
334 | union power_supply_propval *val) | ||
335 | { | ||
336 | struct da9030_charger *charger; | ||
337 | charger = container_of(psy, struct da9030_charger, psy); | ||
338 | |||
339 | switch (psp) { | ||
340 | case POWER_SUPPLY_PROP_STATUS: | ||
341 | da9030_battery_check_status(charger, val); | ||
342 | break; | ||
343 | case POWER_SUPPLY_PROP_HEALTH: | ||
344 | da9030_battery_check_health(charger, val); | ||
345 | break; | ||
346 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
347 | val->intval = charger->battery_info->technology; | ||
348 | break; | ||
349 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
350 | val->intval = charger->battery_info->voltage_max_design; | ||
351 | break; | ||
352 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
353 | val->intval = charger->battery_info->voltage_min_design; | ||
354 | break; | ||
355 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
356 | val->intval = da9030_reg_to_mV(charger->adc.vbat_res) * 1000; | ||
357 | break; | ||
358 | case POWER_SUPPLY_PROP_CURRENT_AVG: | ||
359 | val->intval = | ||
360 | da9030_reg_to_mA(charger->adc.ichaverage_res) * 1000; | ||
361 | break; | ||
362 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
363 | val->strval = charger->battery_info->name; | ||
364 | break; | ||
365 | default: | ||
366 | break; | ||
367 | } | ||
368 | |||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | static void da9030_battery_vbat_event(struct da9030_charger *charger) | ||
373 | { | ||
374 | da9030_read_adc(charger, &charger->adc); | ||
375 | |||
376 | if (charger->is_on) | ||
377 | return; | ||
378 | |||
379 | if (charger->adc.vbat_res < charger->thresholds.vbat_low) { | ||
380 | /* set VBAT threshold for critical */ | ||
381 | da903x_write(charger->master, DA9030_VBATMON, | ||
382 | charger->thresholds.vbat_crit); | ||
383 | if (charger->battery_low) | ||
384 | charger->battery_low(); | ||
385 | } else if (charger->adc.vbat_res < | ||
386 | charger->thresholds.vbat_crit) { | ||
387 | /* notify the system of battery critical */ | ||
388 | if (charger->battery_critical) | ||
389 | charger->battery_critical(); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | static int da9030_battery_event(struct notifier_block *nb, unsigned long event, | ||
394 | void *data) | ||
395 | { | ||
396 | struct da9030_charger *charger = | ||
397 | container_of(nb, struct da9030_charger, nb); | ||
398 | int status; | ||
399 | |||
400 | switch (event) { | ||
401 | case DA9030_EVENT_CHDET: | ||
402 | status = da903x_query_status(charger->master, | ||
403 | DA9030_STATUS_CHDET); | ||
404 | da9030_set_charge(charger, status); | ||
405 | break; | ||
406 | case DA9030_EVENT_VBATMON: | ||
407 | da9030_battery_vbat_event(charger); | ||
408 | break; | ||
409 | case DA9030_EVENT_CHIOVER: | ||
410 | case DA9030_EVENT_TBAT: | ||
411 | da9030_set_charge(charger, 0); | ||
412 | break; | ||
413 | } | ||
414 | |||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static void da9030_battery_convert_thresholds(struct da9030_charger *charger, | ||
419 | struct da9030_battery_info *pdata) | ||
420 | { | ||
421 | charger->thresholds.tbat_low = pdata->tbat_low; | ||
422 | charger->thresholds.tbat_high = pdata->tbat_high; | ||
423 | charger->thresholds.tbat_restart = pdata->tbat_restart; | ||
424 | |||
425 | charger->thresholds.vbat_low = | ||
426 | da9030_millivolt_to_reg(pdata->vbat_low); | ||
427 | charger->thresholds.vbat_crit = | ||
428 | da9030_millivolt_to_reg(pdata->vbat_crit); | ||
429 | charger->thresholds.vbat_charge_start = | ||
430 | da9030_millivolt_to_reg(pdata->vbat_charge_start); | ||
431 | charger->thresholds.vbat_charge_stop = | ||
432 | da9030_millivolt_to_reg(pdata->vbat_charge_stop); | ||
433 | charger->thresholds.vbat_charge_restart = | ||
434 | da9030_millivolt_to_reg(pdata->vbat_charge_restart); | ||
435 | |||
436 | charger->thresholds.vcharge_min = | ||
437 | da9030_millivolt_to_reg(pdata->vcharge_min); | ||
438 | charger->thresholds.vcharge_max = | ||
439 | da9030_millivolt_to_reg(pdata->vcharge_max); | ||
440 | } | ||
441 | |||
442 | static void da9030_battery_setup_psy(struct da9030_charger *charger) | ||
443 | { | ||
444 | struct power_supply *psy = &charger->psy; | ||
445 | struct power_supply_info *info = charger->battery_info; | ||
446 | |||
447 | psy->name = info->name; | ||
448 | psy->use_for_apm = info->use_for_apm; | ||
449 | psy->type = POWER_SUPPLY_TYPE_BATTERY; | ||
450 | psy->get_property = da9030_battery_get_property; | ||
451 | |||
452 | psy->properties = da9030_battery_props; | ||
453 | psy->num_properties = ARRAY_SIZE(da9030_battery_props); | ||
454 | }; | ||
455 | |||
456 | static int da9030_battery_charger_init(struct da9030_charger *charger) | ||
457 | { | ||
458 | char v[5]; | ||
459 | int ret; | ||
460 | |||
461 | v[0] = v[1] = charger->thresholds.vbat_low; | ||
462 | v[2] = charger->thresholds.tbat_high; | ||
463 | v[3] = charger->thresholds.tbat_restart; | ||
464 | v[4] = charger->thresholds.tbat_low; | ||
465 | |||
466 | ret = da903x_writes(charger->master, DA9030_VBATMON, 5, v); | ||
467 | if (ret) | ||
468 | return ret; | ||
469 | |||
470 | /* | ||
471 | * Enable reference voltage supply for ADC from the LDO_INTERNAL | ||
472 | * regulator. Must be set before ADC measurements can be made. | ||
473 | */ | ||
474 | ret = da903x_write(charger->master, DA9030_ADC_MAN_CONTROL, | ||
475 | DA9030_ADC_LDO_INT_ENABLE | | ||
476 | DA9030_ADC_TBATREF_ENABLE); | ||
477 | if (ret) | ||
478 | return ret; | ||
479 | |||
480 | /* enable auto ADC measuremnts */ | ||
481 | return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL, | ||
482 | DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON | | ||
483 | DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE | | ||
484 | DA9030_ADC_VBAT_ENABLE | | ||
485 | DA9030_ADC_AUTO_SLEEP_ENABLE); | ||
486 | } | ||
487 | |||
488 | static int da9030_battery_probe(struct platform_device *pdev) | ||
489 | { | ||
490 | struct da9030_charger *charger; | ||
491 | struct da9030_battery_info *pdata = pdev->dev.platform_data; | ||
492 | int ret; | ||
493 | |||
494 | if (pdata == NULL) | ||
495 | return -EINVAL; | ||
496 | |||
497 | if (pdata->charge_milliamp >= 1500 || | ||
498 | pdata->charge_millivolt < 4000 || | ||
499 | pdata->charge_millivolt > 4350) | ||
500 | return -EINVAL; | ||
501 | |||
502 | charger = kzalloc(sizeof(*charger), GFP_KERNEL); | ||
503 | if (charger == NULL) | ||
504 | return -ENOMEM; | ||
505 | |||
506 | charger->master = pdev->dev.parent; | ||
507 | |||
508 | /* 10 seconds between monotor runs unless platfrom defines other | ||
509 | interval */ | ||
510 | charger->interval = msecs_to_jiffies( | ||
511 | (pdata->batmon_interval ? : 10) * 1000); | ||
512 | |||
513 | charger->charge_milliamp = pdata->charge_milliamp; | ||
514 | charger->charge_millivolt = pdata->charge_millivolt; | ||
515 | charger->battery_info = pdata->battery_info; | ||
516 | charger->battery_low = pdata->battery_low; | ||
517 | charger->battery_critical = pdata->battery_critical; | ||
518 | |||
519 | da9030_battery_convert_thresholds(charger, pdata); | ||
520 | |||
521 | ret = da9030_battery_charger_init(charger); | ||
522 | if (ret) | ||
523 | goto err_charger_init; | ||
524 | |||
525 | INIT_DELAYED_WORK(&charger->work, da9030_charging_monitor); | ||
526 | schedule_delayed_work(&charger->work, charger->interval); | ||
527 | |||
528 | charger->nb.notifier_call = da9030_battery_event; | ||
529 | ret = da903x_register_notifier(charger->master, &charger->nb, | ||
530 | DA9030_EVENT_CHDET | | ||
531 | DA9030_EVENT_VBATMON | | ||
532 | DA9030_EVENT_CHIOVER | | ||
533 | DA9030_EVENT_TBAT); | ||
534 | if (ret) | ||
535 | goto err_notifier; | ||
536 | |||
537 | da9030_battery_setup_psy(charger); | ||
538 | ret = power_supply_register(&pdev->dev, &charger->psy); | ||
539 | if (ret) | ||
540 | goto err_ps_register; | ||
541 | |||
542 | charger->debug_file = da9030_bat_create_debugfs(charger); | ||
543 | platform_set_drvdata(pdev, charger); | ||
544 | return 0; | ||
545 | |||
546 | err_ps_register: | ||
547 | da903x_unregister_notifier(charger->master, &charger->nb, | ||
548 | DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | | ||
549 | DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); | ||
550 | err_notifier: | ||
551 | cancel_delayed_work(&charger->work); | ||
552 | |||
553 | err_charger_init: | ||
554 | kfree(charger); | ||
555 | |||
556 | return ret; | ||
557 | } | ||
558 | |||
559 | static int da9030_battery_remove(struct platform_device *dev) | ||
560 | { | ||
561 | struct da9030_charger *charger = platform_get_drvdata(dev); | ||
562 | |||
563 | da9030_bat_remove_debugfs(charger); | ||
564 | |||
565 | da903x_unregister_notifier(charger->master, &charger->nb, | ||
566 | DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON | | ||
567 | DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT); | ||
568 | cancel_delayed_work(&charger->work); | ||
569 | power_supply_unregister(&charger->psy); | ||
570 | |||
571 | kfree(charger); | ||
572 | |||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | static struct platform_driver da903x_battery_driver = { | ||
577 | .driver = { | ||
578 | .name = "da903x-battery", | ||
579 | .owner = THIS_MODULE, | ||
580 | }, | ||
581 | .probe = da9030_battery_probe, | ||
582 | .remove = da9030_battery_remove, | ||
583 | }; | ||
584 | |||
585 | static int da903x_battery_init(void) | ||
586 | { | ||
587 | return platform_driver_register(&da903x_battery_driver); | ||
588 | } | ||
589 | |||
590 | static void da903x_battery_exit(void) | ||
591 | { | ||
592 | platform_driver_unregister(&da903x_battery_driver); | ||
593 | } | ||
594 | |||
595 | module_init(da903x_battery_init); | ||
596 | module_exit(da903x_battery_exit); | ||
597 | |||
598 | MODULE_DESCRIPTION("DA9030 battery charger driver"); | ||
599 | MODULE_AUTHOR("Mike Rapoport, CompuLab"); | ||
600 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 23ae8460f5c1..ac01e06817fb 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -45,7 +45,7 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
45 | }; | 45 | }; |
46 | static char *health_text[] = { | 46 | static char *health_text[] = { |
47 | "Unknown", "Good", "Overheat", "Dead", "Over voltage", | 47 | "Unknown", "Good", "Overheat", "Dead", "Over voltage", |
48 | "Unspecified failure" | 48 | "Unspecified failure", "Cold", |
49 | }; | 49 | }; |
50 | static char *technology_text[] = { | 50 | static char *technology_text[] = { |
51 | "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", | 51 | "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", |
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c new file mode 100644 index 000000000000..1b16bf343f2f --- /dev/null +++ b/drivers/power/wm8350_power.c | |||
@@ -0,0 +1,532 @@ | |||
1 | /* | ||
2 | * Battery driver for wm8350 PMIC | ||
3 | * | ||
4 | * Copyright 2007, 2008 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Based on OLPC Battery Driver | ||
7 | * | ||
8 | * Copyright 2006 David Woodhouse <dwmw2@infradead.org> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/power_supply.h> | ||
19 | #include <linux/mfd/wm8350/supply.h> | ||
20 | #include <linux/mfd/wm8350/core.h> | ||
21 | #include <linux/mfd/wm8350/comparator.h> | ||
22 | |||
23 | static int wm8350_read_battery_uvolts(struct wm8350 *wm8350) | ||
24 | { | ||
25 | return wm8350_read_auxadc(wm8350, WM8350_AUXADC_BATT, 0, 0) | ||
26 | * WM8350_AUX_COEFF; | ||
27 | } | ||
28 | |||
29 | static int wm8350_read_line_uvolts(struct wm8350 *wm8350) | ||
30 | { | ||
31 | return wm8350_read_auxadc(wm8350, WM8350_AUXADC_LINE, 0, 0) | ||
32 | * WM8350_AUX_COEFF; | ||
33 | } | ||
34 | |||
35 | static int wm8350_read_usb_uvolts(struct wm8350 *wm8350) | ||
36 | { | ||
37 | return wm8350_read_auxadc(wm8350, WM8350_AUXADC_USB, 0, 0) | ||
38 | * WM8350_AUX_COEFF; | ||
39 | } | ||
40 | |||
41 | #define WM8350_BATT_SUPPLY 1 | ||
42 | #define WM8350_USB_SUPPLY 2 | ||
43 | #define WM8350_LINE_SUPPLY 4 | ||
44 | |||
45 | static inline int wm8350_charge_time_min(struct wm8350 *wm8350, int min) | ||
46 | { | ||
47 | if (!wm8350->power.rev_g_coeff) | ||
48 | return (((min - 30) / 15) & 0xf) << 8; | ||
49 | else | ||
50 | return (((min - 30) / 30) & 0xf) << 8; | ||
51 | } | ||
52 | |||
53 | static int wm8350_get_supplies(struct wm8350 *wm8350) | ||
54 | { | ||
55 | u16 sm, ov, co, chrg; | ||
56 | int supplies = 0; | ||
57 | |||
58 | sm = wm8350_reg_read(wm8350, WM8350_STATE_MACHINE_STATUS); | ||
59 | ov = wm8350_reg_read(wm8350, WM8350_MISC_OVERRIDES); | ||
60 | co = wm8350_reg_read(wm8350, WM8350_COMPARATOR_OVERRIDES); | ||
61 | chrg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2); | ||
62 | |||
63 | /* USB_SM */ | ||
64 | sm = (sm & WM8350_USB_SM_MASK) >> WM8350_USB_SM_SHIFT; | ||
65 | |||
66 | /* CHG_ISEL */ | ||
67 | chrg &= WM8350_CHG_ISEL_MASK; | ||
68 | |||
69 | /* If the USB state machine is active then we're using that with or | ||
70 | * without battery, otherwise check for wall supply */ | ||
71 | if (((sm == WM8350_USB_SM_100_SLV) || | ||
72 | (sm == WM8350_USB_SM_500_SLV) || | ||
73 | (sm == WM8350_USB_SM_STDBY_SLV)) | ||
74 | && !(ov & WM8350_USB_LIMIT_OVRDE)) | ||
75 | supplies = WM8350_USB_SUPPLY; | ||
76 | else if (((sm == WM8350_USB_SM_100_SLV) || | ||
77 | (sm == WM8350_USB_SM_500_SLV) || | ||
78 | (sm == WM8350_USB_SM_STDBY_SLV)) | ||
79 | && (ov & WM8350_USB_LIMIT_OVRDE) && (chrg == 0)) | ||
80 | supplies = WM8350_USB_SUPPLY | WM8350_BATT_SUPPLY; | ||
81 | else if (co & WM8350_WALL_FB_OVRDE) | ||
82 | supplies = WM8350_LINE_SUPPLY; | ||
83 | else | ||
84 | supplies = WM8350_BATT_SUPPLY; | ||
85 | |||
86 | return supplies; | ||
87 | } | ||
88 | |||
89 | static int wm8350_charger_config(struct wm8350 *wm8350, | ||
90 | struct wm8350_charger_policy *policy) | ||
91 | { | ||
92 | u16 reg, eoc_mA, fast_limit_mA; | ||
93 | |||
94 | if (!policy) { | ||
95 | dev_warn(wm8350->dev, | ||
96 | "No charger policy, charger not configured.\n"); | ||
97 | return -EINVAL; | ||
98 | } | ||
99 | |||
100 | /* make sure USB fast charge current is not > 500mA */ | ||
101 | if (policy->fast_limit_USB_mA > 500) { | ||
102 | dev_err(wm8350->dev, "USB fast charge > 500mA\n"); | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | eoc_mA = WM8350_CHG_EOC_mA(policy->eoc_mA); | ||
107 | |||
108 | wm8350_reg_unlock(wm8350); | ||
109 | |||
110 | reg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1) | ||
111 | & WM8350_CHG_ENA_R168; | ||
112 | wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1, | ||
113 | reg | eoc_mA | policy->trickle_start_mV | | ||
114 | WM8350_CHG_TRICKLE_TEMP_CHOKE | | ||
115 | WM8350_CHG_TRICKLE_USB_CHOKE | | ||
116 | WM8350_CHG_FAST_USB_THROTTLE); | ||
117 | |||
118 | if (wm8350_get_supplies(wm8350) & WM8350_USB_SUPPLY) { | ||
119 | fast_limit_mA = | ||
120 | WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_USB_mA); | ||
121 | wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2, | ||
122 | policy->charge_mV | policy->trickle_charge_USB_mA | | ||
123 | fast_limit_mA | wm8350_charge_time_min(wm8350, | ||
124 | policy->charge_timeout)); | ||
125 | |||
126 | } else { | ||
127 | fast_limit_mA = | ||
128 | WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_mA); | ||
129 | wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2, | ||
130 | policy->charge_mV | policy->trickle_charge_mA | | ||
131 | fast_limit_mA | wm8350_charge_time_min(wm8350, | ||
132 | policy->charge_timeout)); | ||
133 | } | ||
134 | |||
135 | wm8350_reg_lock(wm8350); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int wm8350_batt_status(struct wm8350 *wm8350) | ||
140 | { | ||
141 | u16 state; | ||
142 | |||
143 | state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2); | ||
144 | state &= WM8350_CHG_STS_MASK; | ||
145 | |||
146 | switch (state) { | ||
147 | case WM8350_CHG_STS_OFF: | ||
148 | return POWER_SUPPLY_STATUS_DISCHARGING; | ||
149 | |||
150 | case WM8350_CHG_STS_TRICKLE: | ||
151 | case WM8350_CHG_STS_FAST: | ||
152 | return POWER_SUPPLY_STATUS_CHARGING; | ||
153 | |||
154 | default: | ||
155 | return POWER_SUPPLY_STATUS_UNKNOWN; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | static ssize_t charger_state_show(struct device *dev, | ||
160 | struct device_attribute *attr, char *buf) | ||
161 | { | ||
162 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
163 | char *charge; | ||
164 | int state; | ||
165 | |||
166 | state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) & | ||
167 | WM8350_CHG_STS_MASK; | ||
168 | switch (state) { | ||
169 | case WM8350_CHG_STS_OFF: | ||
170 | charge = "Charger Off"; | ||
171 | break; | ||
172 | case WM8350_CHG_STS_TRICKLE: | ||
173 | charge = "Trickle Charging"; | ||
174 | break; | ||
175 | case WM8350_CHG_STS_FAST: | ||
176 | charge = "Fast Charging"; | ||
177 | break; | ||
178 | default: | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | return sprintf(buf, "%s\n", charge); | ||
183 | } | ||
184 | |||
185 | static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL); | ||
186 | |||
187 | static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data) | ||
188 | { | ||
189 | struct wm8350_power *power = &wm8350->power; | ||
190 | struct wm8350_charger_policy *policy = power->policy; | ||
191 | |||
192 | switch (irq) { | ||
193 | case WM8350_IRQ_CHG_BAT_FAIL: | ||
194 | dev_err(wm8350->dev, "battery failed\n"); | ||
195 | break; | ||
196 | case WM8350_IRQ_CHG_TO: | ||
197 | dev_err(wm8350->dev, "charger timeout\n"); | ||
198 | power_supply_changed(&power->battery); | ||
199 | break; | ||
200 | |||
201 | case WM8350_IRQ_CHG_BAT_HOT: | ||
202 | case WM8350_IRQ_CHG_BAT_COLD: | ||
203 | case WM8350_IRQ_CHG_START: | ||
204 | case WM8350_IRQ_CHG_END: | ||
205 | power_supply_changed(&power->battery); | ||
206 | break; | ||
207 | |||
208 | case WM8350_IRQ_CHG_FAST_RDY: | ||
209 | dev_dbg(wm8350->dev, "fast charger ready\n"); | ||
210 | wm8350_charger_config(wm8350, policy); | ||
211 | wm8350_reg_unlock(wm8350); | ||
212 | wm8350_set_bits(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1, | ||
213 | WM8350_CHG_FAST); | ||
214 | wm8350_reg_lock(wm8350); | ||
215 | break; | ||
216 | |||
217 | case WM8350_IRQ_CHG_VBATT_LT_3P9: | ||
218 | dev_warn(wm8350->dev, "battery < 3.9V\n"); | ||
219 | break; | ||
220 | case WM8350_IRQ_CHG_VBATT_LT_3P1: | ||
221 | dev_warn(wm8350->dev, "battery < 3.1V\n"); | ||
222 | break; | ||
223 | case WM8350_IRQ_CHG_VBATT_LT_2P85: | ||
224 | dev_warn(wm8350->dev, "battery < 2.85V\n"); | ||
225 | break; | ||
226 | |||
227 | /* Supply change. We will overnotify but it should do | ||
228 | * no harm. */ | ||
229 | case WM8350_IRQ_EXT_USB_FB: | ||
230 | case WM8350_IRQ_EXT_WALL_FB: | ||
231 | wm8350_charger_config(wm8350, policy); | ||
232 | case WM8350_IRQ_EXT_BAT_FB: /* Fall through */ | ||
233 | power_supply_changed(&power->battery); | ||
234 | power_supply_changed(&power->usb); | ||
235 | power_supply_changed(&power->ac); | ||
236 | break; | ||
237 | |||
238 | default: | ||
239 | dev_err(wm8350->dev, "Unknown interrupt %d\n", irq); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | /********************************************************************* | ||
244 | * AC Power | ||
245 | *********************************************************************/ | ||
246 | static int wm8350_ac_get_prop(struct power_supply *psy, | ||
247 | enum power_supply_property psp, | ||
248 | union power_supply_propval *val) | ||
249 | { | ||
250 | struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent); | ||
251 | int ret = 0; | ||
252 | |||
253 | switch (psp) { | ||
254 | case POWER_SUPPLY_PROP_ONLINE: | ||
255 | val->intval = !!(wm8350_get_supplies(wm8350) & | ||
256 | WM8350_LINE_SUPPLY); | ||
257 | break; | ||
258 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
259 | val->intval = wm8350_read_line_uvolts(wm8350); | ||
260 | break; | ||
261 | default: | ||
262 | ret = -EINVAL; | ||
263 | break; | ||
264 | } | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static enum power_supply_property wm8350_ac_props[] = { | ||
269 | POWER_SUPPLY_PROP_ONLINE, | ||
270 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
271 | }; | ||
272 | |||
273 | /********************************************************************* | ||
274 | * USB Power | ||
275 | *********************************************************************/ | ||
276 | static int wm8350_usb_get_prop(struct power_supply *psy, | ||
277 | enum power_supply_property psp, | ||
278 | union power_supply_propval *val) | ||
279 | { | ||
280 | struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent); | ||
281 | int ret = 0; | ||
282 | |||
283 | switch (psp) { | ||
284 | case POWER_SUPPLY_PROP_ONLINE: | ||
285 | val->intval = !!(wm8350_get_supplies(wm8350) & | ||
286 | WM8350_USB_SUPPLY); | ||
287 | break; | ||
288 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
289 | val->intval = wm8350_read_usb_uvolts(wm8350); | ||
290 | break; | ||
291 | default: | ||
292 | ret = -EINVAL; | ||
293 | break; | ||
294 | } | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | static enum power_supply_property wm8350_usb_props[] = { | ||
299 | POWER_SUPPLY_PROP_ONLINE, | ||
300 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
301 | }; | ||
302 | |||
303 | /********************************************************************* | ||
304 | * Battery properties | ||
305 | *********************************************************************/ | ||
306 | |||
307 | static int wm8350_bat_check_health(struct wm8350 *wm8350) | ||
308 | { | ||
309 | u16 reg; | ||
310 | |||
311 | if (wm8350_read_battery_uvolts(wm8350) < 2850000) | ||
312 | return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
313 | |||
314 | reg = wm8350_reg_read(wm8350, WM8350_CHARGER_OVERRIDES); | ||
315 | if (reg & WM8350_CHG_BATT_HOT_OVRDE) | ||
316 | return POWER_SUPPLY_HEALTH_OVERHEAT; | ||
317 | |||
318 | if (reg & WM8350_CHG_BATT_COLD_OVRDE) | ||
319 | return POWER_SUPPLY_HEALTH_COLD; | ||
320 | |||
321 | return POWER_SUPPLY_HEALTH_GOOD; | ||
322 | } | ||
323 | |||
324 | static int wm8350_bat_get_property(struct power_supply *psy, | ||
325 | enum power_supply_property psp, | ||
326 | union power_supply_propval *val) | ||
327 | { | ||
328 | struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent); | ||
329 | int ret = 0; | ||
330 | |||
331 | switch (psp) { | ||
332 | case POWER_SUPPLY_PROP_STATUS: | ||
333 | val->intval = wm8350_batt_status(wm8350); | ||
334 | break; | ||
335 | case POWER_SUPPLY_PROP_ONLINE: | ||
336 | val->intval = !!(wm8350_get_supplies(wm8350) & | ||
337 | WM8350_BATT_SUPPLY); | ||
338 | break; | ||
339 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
340 | val->intval = wm8350_read_battery_uvolts(wm8350); | ||
341 | break; | ||
342 | case POWER_SUPPLY_PROP_HEALTH: | ||
343 | val->intval = wm8350_bat_check_health(wm8350); | ||
344 | break; | ||
345 | default: | ||
346 | ret = -EINVAL; | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | static enum power_supply_property wm8350_bat_props[] = { | ||
354 | POWER_SUPPLY_PROP_STATUS, | ||
355 | POWER_SUPPLY_PROP_ONLINE, | ||
356 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
357 | POWER_SUPPLY_PROP_HEALTH, | ||
358 | }; | ||
359 | |||
360 | /********************************************************************* | ||
361 | * Initialisation | ||
362 | *********************************************************************/ | ||
363 | |||
364 | static void wm8350_init_charger(struct wm8350 *wm8350) | ||
365 | { | ||
366 | /* register our interest in charger events */ | ||
367 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, | ||
368 | wm8350_charger_handler, NULL); | ||
369 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); | ||
370 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, | ||
371 | wm8350_charger_handler, NULL); | ||
372 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); | ||
373 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, | ||
374 | wm8350_charger_handler, NULL); | ||
375 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); | ||
376 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, | ||
377 | wm8350_charger_handler, NULL); | ||
378 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO); | ||
379 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, | ||
380 | wm8350_charger_handler, NULL); | ||
381 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END); | ||
382 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, | ||
383 | wm8350_charger_handler, NULL); | ||
384 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START); | ||
385 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, | ||
386 | wm8350_charger_handler, NULL); | ||
387 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY); | ||
388 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, | ||
389 | wm8350_charger_handler, NULL); | ||
390 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); | ||
391 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, | ||
392 | wm8350_charger_handler, NULL); | ||
393 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); | ||
394 | wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, | ||
395 | wm8350_charger_handler, NULL); | ||
396 | wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); | ||
397 | |||
398 | /* and supply change events */ | ||
399 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, | ||
400 | wm8350_charger_handler, NULL); | ||
401 | wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); | ||
402 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, | ||
403 | wm8350_charger_handler, NULL); | ||
404 | wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); | ||
405 | wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, | ||
406 | wm8350_charger_handler, NULL); | ||
407 | wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); | ||
408 | } | ||
409 | |||
410 | static void free_charger_irq(struct wm8350 *wm8350) | ||
411 | { | ||
412 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); | ||
413 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); | ||
414 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); | ||
415 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); | ||
416 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); | ||
417 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); | ||
418 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO); | ||
419 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); | ||
420 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END); | ||
421 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); | ||
422 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START); | ||
423 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); | ||
424 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); | ||
425 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); | ||
426 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); | ||
427 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); | ||
428 | wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); | ||
429 | wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); | ||
430 | wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); | ||
431 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); | ||
432 | wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); | ||
433 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); | ||
434 | wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); | ||
435 | wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); | ||
436 | } | ||
437 | |||
438 | static __devinit int wm8350_power_probe(struct platform_device *pdev) | ||
439 | { | ||
440 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
441 | struct wm8350_power *power = &wm8350->power; | ||
442 | struct wm8350_charger_policy *policy = power->policy; | ||
443 | struct power_supply *usb = &power->usb; | ||
444 | struct power_supply *battery = &power->battery; | ||
445 | struct power_supply *ac = &power->ac; | ||
446 | int ret; | ||
447 | |||
448 | ac->name = "wm8350-ac"; | ||
449 | ac->type = POWER_SUPPLY_TYPE_MAINS; | ||
450 | ac->properties = wm8350_ac_props; | ||
451 | ac->num_properties = ARRAY_SIZE(wm8350_ac_props); | ||
452 | ac->get_property = wm8350_ac_get_prop; | ||
453 | ret = power_supply_register(&pdev->dev, ac); | ||
454 | if (ret) | ||
455 | return ret; | ||
456 | |||
457 | battery->name = "wm8350-battery"; | ||
458 | battery->properties = wm8350_bat_props; | ||
459 | battery->num_properties = ARRAY_SIZE(wm8350_bat_props); | ||
460 | battery->get_property = wm8350_bat_get_property; | ||
461 | battery->use_for_apm = 1; | ||
462 | ret = power_supply_register(&pdev->dev, battery); | ||
463 | if (ret) | ||
464 | goto battery_failed; | ||
465 | |||
466 | usb->name = "wm8350-usb", | ||
467 | usb->type = POWER_SUPPLY_TYPE_USB; | ||
468 | usb->properties = wm8350_usb_props; | ||
469 | usb->num_properties = ARRAY_SIZE(wm8350_usb_props); | ||
470 | usb->get_property = wm8350_usb_get_prop; | ||
471 | ret = power_supply_register(&pdev->dev, usb); | ||
472 | if (ret) | ||
473 | goto usb_failed; | ||
474 | |||
475 | ret = device_create_file(&pdev->dev, &dev_attr_charger_state); | ||
476 | if (ret < 0) | ||
477 | dev_warn(wm8350->dev, "failed to add charge sysfs: %d\n", ret); | ||
478 | ret = 0; | ||
479 | |||
480 | wm8350_init_charger(wm8350); | ||
481 | if (wm8350_charger_config(wm8350, policy) == 0) { | ||
482 | wm8350_reg_unlock(wm8350); | ||
483 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CHG_ENA); | ||
484 | wm8350_reg_lock(wm8350); | ||
485 | } | ||
486 | |||
487 | return ret; | ||
488 | |||
489 | usb_failed: | ||
490 | power_supply_unregister(battery); | ||
491 | battery_failed: | ||
492 | power_supply_unregister(ac); | ||
493 | |||
494 | return ret; | ||
495 | } | ||
496 | |||
497 | static __devexit int wm8350_power_remove(struct platform_device *pdev) | ||
498 | { | ||
499 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
500 | struct wm8350_power *power = &wm8350->power; | ||
501 | |||
502 | free_charger_irq(wm8350); | ||
503 | device_remove_file(&pdev->dev, &dev_attr_charger_state); | ||
504 | power_supply_unregister(&power->battery); | ||
505 | power_supply_unregister(&power->ac); | ||
506 | power_supply_unregister(&power->usb); | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | static struct platform_driver wm8350_power_driver = { | ||
511 | .probe = wm8350_power_probe, | ||
512 | .remove = __devexit_p(wm8350_power_remove), | ||
513 | .driver = { | ||
514 | .name = "wm8350-power", | ||
515 | }, | ||
516 | }; | ||
517 | |||
518 | static int __init wm8350_power_init(void) | ||
519 | { | ||
520 | return platform_driver_register(&wm8350_power_driver); | ||
521 | } | ||
522 | module_init(wm8350_power_init); | ||
523 | |||
524 | static void __exit wm8350_power_exit(void) | ||
525 | { | ||
526 | platform_driver_unregister(&wm8350_power_driver); | ||
527 | } | ||
528 | module_exit(wm8350_power_exit); | ||
529 | |||
530 | MODULE_LICENSE("GPL"); | ||
531 | MODULE_DESCRIPTION("Power supply driver for WM8350"); | ||
532 | MODULE_ALIAS("platform:wm8350-power"); | ||
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 1f44b17e23b1..c68c496b2c49 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c | |||
@@ -1380,6 +1380,13 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg, | |||
1380 | if (wm8350->pmic.pdev[reg]) | 1380 | if (wm8350->pmic.pdev[reg]) |
1381 | return -EBUSY; | 1381 | return -EBUSY; |
1382 | 1382 | ||
1383 | if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 && | ||
1384 | reg > wm8350->pmic.max_dcdc) | ||
1385 | return -ENODEV; | ||
1386 | if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B && | ||
1387 | reg > wm8350->pmic.max_isink) | ||
1388 | return -ENODEV; | ||
1389 | |||
1383 | pdev = platform_device_alloc("wm8350-regulator", reg); | 1390 | pdev = platform_device_alloc("wm8350-regulator", reg); |
1384 | if (!pdev) | 1391 | if (!pdev) |
1385 | return -ENOMEM; | 1392 | return -ENOMEM; |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 123092d8a984..165a81843357 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -102,9 +102,13 @@ config RTC_INTF_DEV_UIE_EMUL | |||
102 | depends on RTC_INTF_DEV | 102 | depends on RTC_INTF_DEV |
103 | help | 103 | help |
104 | Provides an emulation for RTC_UIE if the underlying rtc chip | 104 | Provides an emulation for RTC_UIE if the underlying rtc chip |
105 | driver does not expose RTC_UIE ioctls. Those requests generate | 105 | driver does not expose RTC_UIE ioctls. Those requests generate |
106 | once-per-second update interrupts, used for synchronization. | 106 | once-per-second update interrupts, used for synchronization. |
107 | 107 | ||
108 | The emulation code will read the time from the hardware | ||
109 | clock several times per second, please enable this option | ||
110 | only if you know that you really need it. | ||
111 | |||
108 | config RTC_DRV_TEST | 112 | config RTC_DRV_TEST |
109 | tristate "Test driver/device" | 113 | tristate "Test driver/device" |
110 | help | 114 | help |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index a04c1b6b1575..fd2c652504ff 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -307,6 +307,60 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
307 | } | 307 | } |
308 | EXPORT_SYMBOL_GPL(rtc_set_alarm); | 308 | EXPORT_SYMBOL_GPL(rtc_set_alarm); |
309 | 309 | ||
310 | int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | ||
311 | { | ||
312 | int err = mutex_lock_interruptible(&rtc->ops_lock); | ||
313 | if (err) | ||
314 | return err; | ||
315 | |||
316 | if (!rtc->ops) | ||
317 | err = -ENODEV; | ||
318 | else if (!rtc->ops->alarm_irq_enable) | ||
319 | err = -EINVAL; | ||
320 | else | ||
321 | err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled); | ||
322 | |||
323 | mutex_unlock(&rtc->ops_lock); | ||
324 | return err; | ||
325 | } | ||
326 | EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); | ||
327 | |||
328 | int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | ||
329 | { | ||
330 | int err = mutex_lock_interruptible(&rtc->ops_lock); | ||
331 | if (err) | ||
332 | return err; | ||
333 | |||
334 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
335 | if (enabled == 0 && rtc->uie_irq_active) { | ||
336 | mutex_unlock(&rtc->ops_lock); | ||
337 | return rtc_dev_update_irq_enable_emul(rtc, enabled); | ||
338 | } | ||
339 | #endif | ||
340 | |||
341 | if (!rtc->ops) | ||
342 | err = -ENODEV; | ||
343 | else if (!rtc->ops->update_irq_enable) | ||
344 | err = -EINVAL; | ||
345 | else | ||
346 | err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled); | ||
347 | |||
348 | mutex_unlock(&rtc->ops_lock); | ||
349 | |||
350 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
351 | /* | ||
352 | * Enable emulation if the driver did not provide | ||
353 | * the update_irq_enable function pointer or if returned | ||
354 | * -EINVAL to signal that it has been configured without | ||
355 | * interrupts or that are not available at the moment. | ||
356 | */ | ||
357 | if (err == -EINVAL) | ||
358 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); | ||
359 | #endif | ||
360 | return err; | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); | ||
363 | |||
310 | /** | 364 | /** |
311 | * rtc_update_irq - report RTC periodic, alarm, and/or update irqs | 365 | * rtc_update_irq - report RTC periodic, alarm, and/or update irqs |
312 | * @rtc: the rtc device | 366 | * @rtc: the rtc device |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index ecdea44ae4e5..45152f4952d6 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -92,10 +92,10 @@ static void rtc_uie_timer(unsigned long data) | |||
92 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | 92 | spin_unlock_irqrestore(&rtc->irq_lock, flags); |
93 | } | 93 | } |
94 | 94 | ||
95 | static void clear_uie(struct rtc_device *rtc) | 95 | static int clear_uie(struct rtc_device *rtc) |
96 | { | 96 | { |
97 | spin_lock_irq(&rtc->irq_lock); | 97 | spin_lock_irq(&rtc->irq_lock); |
98 | if (rtc->irq_active) { | 98 | if (rtc->uie_irq_active) { |
99 | rtc->stop_uie_polling = 1; | 99 | rtc->stop_uie_polling = 1; |
100 | if (rtc->uie_timer_active) { | 100 | if (rtc->uie_timer_active) { |
101 | spin_unlock_irq(&rtc->irq_lock); | 101 | spin_unlock_irq(&rtc->irq_lock); |
@@ -108,9 +108,10 @@ static void clear_uie(struct rtc_device *rtc) | |||
108 | flush_scheduled_work(); | 108 | flush_scheduled_work(); |
109 | spin_lock_irq(&rtc->irq_lock); | 109 | spin_lock_irq(&rtc->irq_lock); |
110 | } | 110 | } |
111 | rtc->irq_active = 0; | 111 | rtc->uie_irq_active = 0; |
112 | } | 112 | } |
113 | spin_unlock_irq(&rtc->irq_lock); | 113 | spin_unlock_irq(&rtc->irq_lock); |
114 | return 0; | ||
114 | } | 115 | } |
115 | 116 | ||
116 | static int set_uie(struct rtc_device *rtc) | 117 | static int set_uie(struct rtc_device *rtc) |
@@ -122,8 +123,8 @@ static int set_uie(struct rtc_device *rtc) | |||
122 | if (err) | 123 | if (err) |
123 | return err; | 124 | return err; |
124 | spin_lock_irq(&rtc->irq_lock); | 125 | spin_lock_irq(&rtc->irq_lock); |
125 | if (!rtc->irq_active) { | 126 | if (!rtc->uie_irq_active) { |
126 | rtc->irq_active = 1; | 127 | rtc->uie_irq_active = 1; |
127 | rtc->stop_uie_polling = 0; | 128 | rtc->stop_uie_polling = 0; |
128 | rtc->oldsecs = tm.tm_sec; | 129 | rtc->oldsecs = tm.tm_sec; |
129 | rtc->uie_task_active = 1; | 130 | rtc->uie_task_active = 1; |
@@ -134,6 +135,16 @@ static int set_uie(struct rtc_device *rtc) | |||
134 | spin_unlock_irq(&rtc->irq_lock); | 135 | spin_unlock_irq(&rtc->irq_lock); |
135 | return 0; | 136 | return 0; |
136 | } | 137 | } |
138 | |||
139 | int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled) | ||
140 | { | ||
141 | if (enabled) | ||
142 | return set_uie(rtc); | ||
143 | else | ||
144 | return clear_uie(rtc); | ||
145 | } | ||
146 | EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul); | ||
147 | |||
137 | #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ | 148 | #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ |
138 | 149 | ||
139 | static ssize_t | 150 | static ssize_t |
@@ -357,6 +368,22 @@ static long rtc_dev_ioctl(struct file *file, | |||
357 | err = rtc_irq_set_state(rtc, NULL, 0); | 368 | err = rtc_irq_set_state(rtc, NULL, 0); |
358 | break; | 369 | break; |
359 | 370 | ||
371 | case RTC_AIE_ON: | ||
372 | mutex_unlock(&rtc->ops_lock); | ||
373 | return rtc_alarm_irq_enable(rtc, 1); | ||
374 | |||
375 | case RTC_AIE_OFF: | ||
376 | mutex_unlock(&rtc->ops_lock); | ||
377 | return rtc_alarm_irq_enable(rtc, 0); | ||
378 | |||
379 | case RTC_UIE_ON: | ||
380 | mutex_unlock(&rtc->ops_lock); | ||
381 | return rtc_update_irq_enable(rtc, 1); | ||
382 | |||
383 | case RTC_UIE_OFF: | ||
384 | mutex_unlock(&rtc->ops_lock); | ||
385 | return rtc_update_irq_enable(rtc, 0); | ||
386 | |||
360 | case RTC_IRQP_SET: | 387 | case RTC_IRQP_SET: |
361 | err = rtc_irq_set_freq(rtc, NULL, arg); | 388 | err = rtc_irq_set_freq(rtc, NULL, arg); |
362 | break; | 389 | break; |
@@ -401,17 +428,6 @@ static long rtc_dev_ioctl(struct file *file, | |||
401 | err = -EFAULT; | 428 | err = -EFAULT; |
402 | return err; | 429 | return err; |
403 | 430 | ||
404 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
405 | case RTC_UIE_OFF: | ||
406 | mutex_unlock(&rtc->ops_lock); | ||
407 | clear_uie(rtc); | ||
408 | return 0; | ||
409 | |||
410 | case RTC_UIE_ON: | ||
411 | mutex_unlock(&rtc->ops_lock); | ||
412 | err = set_uie(rtc); | ||
413 | return err; | ||
414 | #endif | ||
415 | default: | 431 | default: |
416 | err = -ENOTTY; | 432 | err = -ENOTTY; |
417 | break; | 433 | break; |
@@ -440,7 +456,10 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
440 | * Leave the alarm alone; it may be set to trigger a system wakeup | 456 | * Leave the alarm alone; it may be set to trigger a system wakeup |
441 | * later, or be used by kernel code, and is a one-shot event anyway. | 457 | * later, or be used by kernel code, and is a one-shot event anyway. |
442 | */ | 458 | */ |
459 | |||
460 | /* Keep ioctl until all drivers are converted */ | ||
443 | rtc_dev_ioctl(file, RTC_UIE_OFF, 0); | 461 | rtc_dev_ioctl(file, RTC_UIE_OFF, 0); |
462 | rtc_update_irq_enable(rtc, 0); | ||
444 | rtc_irq_set_state(rtc, NULL, 0); | 463 | rtc_irq_set_state(rtc, NULL, 0); |
445 | 464 | ||
446 | if (rtc->ops->release) | 465 | if (rtc->ops->release) |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d5ccce1643e4..e0c45574b0c8 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -643,7 +643,6 @@ struct qeth_card_options { | |||
643 | int macaddr_mode; | 643 | int macaddr_mode; |
644 | int fake_broadcast; | 644 | int fake_broadcast; |
645 | int add_hhlen; | 645 | int add_hhlen; |
646 | int fake_ll; | ||
647 | int layer2; | 646 | int layer2; |
648 | enum qeth_large_send_types large_send; | 647 | enum qeth_large_send_types large_send; |
649 | int performance_stats; | 648 | int performance_stats; |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index e783644a2105..6811dd529f48 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -287,8 +287,15 @@ int qeth_set_large_send(struct qeth_card *card, | |||
287 | card->options.large_send = type; | 287 | card->options.large_send = type; |
288 | switch (card->options.large_send) { | 288 | switch (card->options.large_send) { |
289 | case QETH_LARGE_SEND_EDDP: | 289 | case QETH_LARGE_SEND_EDDP: |
290 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG | | 290 | if (card->info.type != QETH_CARD_TYPE_IQD) { |
291 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG | | ||
291 | NETIF_F_HW_CSUM; | 292 | NETIF_F_HW_CSUM; |
293 | } else { | ||
294 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
295 | NETIF_F_HW_CSUM); | ||
296 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
297 | rc = -EOPNOTSUPP; | ||
298 | } | ||
292 | break; | 299 | break; |
293 | case QETH_LARGE_SEND_TSO: | 300 | case QETH_LARGE_SEND_TSO: |
294 | if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { | 301 | if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { |
@@ -572,6 +579,10 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel, | |||
572 | card = CARD_FROM_CDEV(channel->ccwdev); | 579 | card = CARD_FROM_CDEV(channel->ccwdev); |
573 | if (qeth_check_idx_response(iob->data)) { | 580 | if (qeth_check_idx_response(iob->data)) { |
574 | qeth_clear_ipacmd_list(card); | 581 | qeth_clear_ipacmd_list(card); |
582 | if (((iob->data[2] & 0xc0) == 0xc0) && iob->data[4] == 0xf6) | ||
583 | dev_err(&card->gdev->dev, | ||
584 | "The qeth device is not configured " | ||
585 | "for the OSI layer required by z/VM\n"); | ||
575 | qeth_schedule_recovery(card); | 586 | qeth_schedule_recovery(card); |
576 | goto out; | 587 | goto out; |
577 | } | 588 | } |
@@ -1072,7 +1083,6 @@ static void qeth_set_intial_options(struct qeth_card *card) | |||
1072 | card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL; | 1083 | card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL; |
1073 | card->options.fake_broadcast = 0; | 1084 | card->options.fake_broadcast = 0; |
1074 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; | 1085 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; |
1075 | card->options.fake_ll = 0; | ||
1076 | card->options.performance_stats = 0; | 1086 | card->options.performance_stats = 0; |
1077 | card->options.rx_sg_cb = QETH_RX_SG_CB; | 1087 | card->options.rx_sg_cb = QETH_RX_SG_CB; |
1078 | } | 1088 | } |
@@ -1682,6 +1692,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, | |||
1682 | unsigned long flags; | 1692 | unsigned long flags; |
1683 | struct qeth_reply *reply = NULL; | 1693 | struct qeth_reply *reply = NULL; |
1684 | unsigned long timeout; | 1694 | unsigned long timeout; |
1695 | struct qeth_ipa_cmd *cmd; | ||
1685 | 1696 | ||
1686 | QETH_DBF_TEXT(TRACE, 2, "sendctl"); | 1697 | QETH_DBF_TEXT(TRACE, 2, "sendctl"); |
1687 | 1698 | ||
@@ -1728,17 +1739,34 @@ int qeth_send_control_data(struct qeth_card *card, int len, | |||
1728 | wake_up(&card->wait_q); | 1739 | wake_up(&card->wait_q); |
1729 | return rc; | 1740 | return rc; |
1730 | } | 1741 | } |
1731 | while (!atomic_read(&reply->received)) { | 1742 | |
1732 | if (time_after(jiffies, timeout)) { | 1743 | /* we have only one long running ipassist, since we can ensure |
1733 | spin_lock_irqsave(&reply->card->lock, flags); | 1744 | process context of this command we can sleep */ |
1734 | list_del_init(&reply->list); | 1745 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); |
1735 | spin_unlock_irqrestore(&reply->card->lock, flags); | 1746 | if ((cmd->hdr.command == IPA_CMD_SETIP) && |
1736 | reply->rc = -ETIME; | 1747 | (cmd->hdr.prot_version == QETH_PROT_IPV4)) { |
1737 | atomic_inc(&reply->received); | 1748 | if (!wait_event_timeout(reply->wait_q, |
1738 | wake_up(&reply->wait_q); | 1749 | atomic_read(&reply->received), timeout)) |
1739 | } | 1750 | goto time_err; |
1740 | cpu_relax(); | 1751 | } else { |
1741 | }; | 1752 | while (!atomic_read(&reply->received)) { |
1753 | if (time_after(jiffies, timeout)) | ||
1754 | goto time_err; | ||
1755 | cpu_relax(); | ||
1756 | }; | ||
1757 | } | ||
1758 | |||
1759 | rc = reply->rc; | ||
1760 | qeth_put_reply(reply); | ||
1761 | return rc; | ||
1762 | |||
1763 | time_err: | ||
1764 | spin_lock_irqsave(&reply->card->lock, flags); | ||
1765 | list_del_init(&reply->list); | ||
1766 | spin_unlock_irqrestore(&reply->card->lock, flags); | ||
1767 | reply->rc = -ETIME; | ||
1768 | atomic_inc(&reply->received); | ||
1769 | wake_up(&reply->wait_q); | ||
1742 | rc = reply->rc; | 1770 | rc = reply->rc; |
1743 | qeth_put_reply(reply); | 1771 | qeth_put_reply(reply); |
1744 | return rc; | 1772 | return rc; |
@@ -2250,7 +2278,8 @@ void qeth_print_status_message(struct qeth_card *card) | |||
2250 | } | 2278 | } |
2251 | /* fallthrough */ | 2279 | /* fallthrough */ |
2252 | case QETH_CARD_TYPE_IQD: | 2280 | case QETH_CARD_TYPE_IQD: |
2253 | if (card->info.guestlan) { | 2281 | if ((card->info.guestlan) || |
2282 | (card->info.mcl_level[0] & 0x80)) { | ||
2254 | card->info.mcl_level[0] = (char) _ebcasc[(__u8) | 2283 | card->info.mcl_level[0] = (char) _ebcasc[(__u8) |
2255 | card->info.mcl_level[0]]; | 2284 | card->info.mcl_level[0]]; |
2256 | card->info.mcl_level[1] = (char) _ebcasc[(__u8) | 2285 | card->info.mcl_level[1] = (char) _ebcasc[(__u8) |
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 2c48591ced44..21627ba3093b 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -1126,9 +1126,11 @@ static int qeth_l2_recover(void *ptr) | |||
1126 | dev_info(&card->gdev->dev, | 1126 | dev_info(&card->gdev->dev, |
1127 | "Device successfully recovered!\n"); | 1127 | "Device successfully recovered!\n"); |
1128 | else { | 1128 | else { |
1129 | rtnl_lock(); | 1129 | if (card->dev) { |
1130 | dev_close(card->dev); | 1130 | rtnl_lock(); |
1131 | rtnl_unlock(); | 1131 | dev_close(card->dev); |
1132 | rtnl_unlock(); | ||
1133 | } | ||
1132 | dev_warn(&card->gdev->dev, "The qeth device driver " | 1134 | dev_warn(&card->gdev->dev, "The qeth device driver " |
1133 | "failed to recover an error on the device\n"); | 1135 | "failed to recover an error on the device\n"); |
1134 | } | 1136 | } |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index c0b30b25a5f1..cfda1ecffdf2 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -1047,7 +1047,7 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) | |||
1047 | rc = qeth_setadpparms_change_macaddr(card); | 1047 | rc = qeth_setadpparms_change_macaddr(card); |
1048 | if (rc) | 1048 | if (rc) |
1049 | dev_warn(&card->gdev->dev, "Reading the adapter MAC" | 1049 | dev_warn(&card->gdev->dev, "Reading the adapter MAC" |
1050 | " address failed\n", rc); | 1050 | " address failed\n"); |
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | if ((card->info.link_type == QETH_LINK_TYPE_HSTR) || | 1053 | if ((card->info.link_type == QETH_LINK_TYPE_HSTR) || |
@@ -1207,12 +1207,9 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card) | |||
1207 | 1207 | ||
1208 | QETH_DBF_TEXT(TRACE, 3, "stsrcmac"); | 1208 | QETH_DBF_TEXT(TRACE, 3, "stsrcmac"); |
1209 | 1209 | ||
1210 | if (!card->options.fake_ll) | ||
1211 | return -EOPNOTSUPP; | ||
1212 | |||
1213 | if (!qeth_is_supported(card, IPA_SOURCE_MAC)) { | 1210 | if (!qeth_is_supported(card, IPA_SOURCE_MAC)) { |
1214 | dev_info(&card->gdev->dev, | 1211 | dev_info(&card->gdev->dev, |
1215 | "Inbound source address not supported on %s\n", | 1212 | "Inbound source MAC-address not supported on %s\n", |
1216 | QETH_CARD_IFNAME(card)); | 1213 | QETH_CARD_IFNAME(card)); |
1217 | return -EOPNOTSUPP; | 1214 | return -EOPNOTSUPP; |
1218 | } | 1215 | } |
@@ -1221,7 +1218,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card) | |||
1221 | IPA_CMD_ASS_START, 0); | 1218 | IPA_CMD_ASS_START, 0); |
1222 | if (rc) | 1219 | if (rc) |
1223 | dev_warn(&card->gdev->dev, | 1220 | dev_warn(&card->gdev->dev, |
1224 | "Starting proxy ARP support for %s failed\n", | 1221 | "Starting source MAC-address support for %s failed\n", |
1225 | QETH_CARD_IFNAME(card)); | 1222 | QETH_CARD_IFNAME(card)); |
1226 | return rc; | 1223 | return rc; |
1227 | } | 1224 | } |
@@ -1921,8 +1918,13 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, | |||
1921 | memcpy(tg_addr, card->dev->dev_addr, | 1918 | memcpy(tg_addr, card->dev->dev_addr, |
1922 | card->dev->addr_len); | 1919 | card->dev->addr_len); |
1923 | } | 1920 | } |
1924 | card->dev->header_ops->create(skb, card->dev, prot, tg_addr, | 1921 | if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) |
1925 | "FAKELL", card->dev->addr_len); | 1922 | card->dev->header_ops->create(skb, card->dev, prot, |
1923 | tg_addr, &hdr->hdr.l3.dest_addr[2], | ||
1924 | card->dev->addr_len); | ||
1925 | else | ||
1926 | card->dev->header_ops->create(skb, card->dev, prot, | ||
1927 | tg_addr, "FAKELL", card->dev->addr_len); | ||
1926 | } | 1928 | } |
1927 | 1929 | ||
1928 | #ifdef CONFIG_TR | 1930 | #ifdef CONFIG_TR |
@@ -2080,9 +2082,11 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) | |||
2080 | if (recovery_mode) | 2082 | if (recovery_mode) |
2081 | qeth_l3_stop(card->dev); | 2083 | qeth_l3_stop(card->dev); |
2082 | else { | 2084 | else { |
2083 | rtnl_lock(); | 2085 | if (card->dev) { |
2084 | dev_close(card->dev); | 2086 | rtnl_lock(); |
2085 | rtnl_unlock(); | 2087 | dev_close(card->dev); |
2088 | rtnl_unlock(); | ||
2089 | } | ||
2086 | } | 2090 | } |
2087 | if (!card->use_hard_stop) { | 2091 | if (!card->use_hard_stop) { |
2088 | rc = qeth_send_stoplan(card); | 2092 | rc = qeth_send_stoplan(card); |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 185be760833e..2a129cb7bb56 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -279,7 +279,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de | |||
279 | inode->i_mode = mode; | 279 | inode->i_mode = mode; |
280 | inode->i_uid = current_fsuid(); | 280 | inode->i_uid = current_fsuid(); |
281 | inode->i_gid = current_fsgid(); | 281 | inode->i_gid = current_fsgid(); |
282 | inode->i_blocks = 0; | ||
283 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 282 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
284 | switch (mode & S_IFMT) { | 283 | switch (mode & S_IFMT) { |
285 | default: | 284 | default: |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index c4e62a6297d7..2e71368f45b4 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -1863,26 +1863,10 @@ static int do_write(struct fsg_dev *fsg) | |||
1863 | static int fsync_sub(struct lun *curlun) | 1863 | static int fsync_sub(struct lun *curlun) |
1864 | { | 1864 | { |
1865 | struct file *filp = curlun->filp; | 1865 | struct file *filp = curlun->filp; |
1866 | struct inode *inode; | ||
1867 | int rc, err; | ||
1868 | 1866 | ||
1869 | if (curlun->ro || !filp) | 1867 | if (curlun->ro || !filp) |
1870 | return 0; | 1868 | return 0; |
1871 | if (!filp->f_op->fsync) | 1869 | return vfs_fsync(filp, filp->f_path.dentry, 1); |
1872 | return -EINVAL; | ||
1873 | |||
1874 | inode = filp->f_path.dentry->d_inode; | ||
1875 | mutex_lock(&inode->i_mutex); | ||
1876 | rc = filemap_fdatawrite(inode->i_mapping); | ||
1877 | err = filp->f_op->fsync(filp, filp->f_path.dentry, 1); | ||
1878 | if (!rc) | ||
1879 | rc = err; | ||
1880 | err = filemap_fdatawait(inode->i_mapping); | ||
1881 | if (!rc) | ||
1882 | rc = err; | ||
1883 | mutex_unlock(&inode->i_mutex); | ||
1884 | VLDBG(curlun, "fdatasync -> %d\n", rc); | ||
1885 | return rc; | ||
1886 | } | 1870 | } |
1887 | 1871 | ||
1888 | static void fsync_all(struct fsg_dev *fsg) | 1872 | static void fsync_all(struct fsg_dev *fsg) |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index eeb26c0f88e5..317b48fdbf01 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -2001,7 +2001,6 @@ gadgetfs_make_inode (struct super_block *sb, | |||
2001 | inode->i_mode = mode; | 2001 | inode->i_mode = mode; |
2002 | inode->i_uid = default_uid; | 2002 | inode->i_uid = default_uid; |
2003 | inode->i_gid = default_gid; | 2003 | inode->i_gid = default_gid; |
2004 | inode->i_blocks = 0; | ||
2005 | inode->i_atime = inode->i_mtime = inode->i_ctime | 2004 | inode->i_atime = inode->i_mtime = inode->i_ctime |
2006 | = CURRENT_TIME; | 2005 | = CURRENT_TIME; |
2007 | inode->i_private = data; | 2006 | inode->i_private = data; |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 73ac754ad801..e21fe5b6f9ff 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -546,23 +546,25 @@ static int viafb_blank(int blank_mode, struct fb_info *info) | |||
546 | 546 | ||
547 | static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | 547 | static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) |
548 | { | 548 | { |
549 | struct viafb_ioctl_mode viamode; | 549 | union { |
550 | struct viafb_ioctl_samm viasamm; | 550 | struct viafb_ioctl_mode viamode; |
551 | struct viafb_driver_version driver_version; | 551 | struct viafb_ioctl_samm viasamm; |
552 | struct fb_var_screeninfo sec_var; | 552 | struct viafb_driver_version driver_version; |
553 | struct _panel_size_pos_info panel_pos_size_para; | 553 | struct fb_var_screeninfo sec_var; |
554 | struct _panel_size_pos_info panel_pos_size_para; | ||
555 | struct viafb_ioctl_setting viafb_setting; | ||
556 | struct device_t active_dev; | ||
557 | } u; | ||
554 | u32 state_info = 0; | 558 | u32 state_info = 0; |
555 | u32 viainfo_size = sizeof(struct viafb_ioctl_info); | ||
556 | u32 *viafb_gamma_table; | 559 | u32 *viafb_gamma_table; |
557 | char driver_name[] = "viafb"; | 560 | char driver_name[] = "viafb"; |
558 | 561 | ||
559 | u32 __user *argp = (u32 __user *) arg; | 562 | u32 __user *argp = (u32 __user *) arg; |
560 | u32 gpu32; | 563 | u32 gpu32; |
561 | u32 video_dev_info = 0; | 564 | u32 video_dev_info = 0; |
562 | struct viafb_ioctl_setting viafb_setting = {}; | ||
563 | struct device_t active_dev = {}; | ||
564 | 565 | ||
565 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); | 566 | DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); |
567 | memset(&u, 0, sizeof(u)); | ||
566 | 568 | ||
567 | switch (cmd) { | 569 | switch (cmd) { |
568 | case VIAFB_GET_CHIP_INFO: | 570 | case VIAFB_GET_CHIP_INFO: |
@@ -571,7 +573,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
571 | return -EFAULT; | 573 | return -EFAULT; |
572 | break; | 574 | break; |
573 | case VIAFB_GET_INFO_SIZE: | 575 | case VIAFB_GET_INFO_SIZE: |
574 | return put_user(viainfo_size, argp); | 576 | return put_user((u32)sizeof(struct viafb_ioctl_info), argp); |
575 | case VIAFB_GET_INFO: | 577 | case VIAFB_GET_INFO: |
576 | return viafb_ioctl_get_viafb_info(arg); | 578 | return viafb_ioctl_get_viafb_info(arg); |
577 | case VIAFB_HOTPLUG: | 579 | case VIAFB_HOTPLUG: |
@@ -584,60 +586,60 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
584 | viafb_hotplug = (gpu32) ? 1 : 0; | 586 | viafb_hotplug = (gpu32) ? 1 : 0; |
585 | break; | 587 | break; |
586 | case VIAFB_GET_RESOLUTION: | 588 | case VIAFB_GET_RESOLUTION: |
587 | viamode.xres = (u32) viafb_hotplug_Xres; | 589 | u.viamode.xres = (u32) viafb_hotplug_Xres; |
588 | viamode.yres = (u32) viafb_hotplug_Yres; | 590 | u.viamode.yres = (u32) viafb_hotplug_Yres; |
589 | viamode.refresh = (u32) viafb_hotplug_refresh; | 591 | u.viamode.refresh = (u32) viafb_hotplug_refresh; |
590 | viamode.bpp = (u32) viafb_hotplug_bpp; | 592 | u.viamode.bpp = (u32) viafb_hotplug_bpp; |
591 | if (viafb_SAMM_ON == 1) { | 593 | if (viafb_SAMM_ON == 1) { |
592 | viamode.xres_sec = viafb_second_xres; | 594 | u.viamode.xres_sec = viafb_second_xres; |
593 | viamode.yres_sec = viafb_second_yres; | 595 | u.viamode.yres_sec = viafb_second_yres; |
594 | viamode.virtual_xres_sec = viafb_second_virtual_xres; | 596 | u.viamode.virtual_xres_sec = viafb_second_virtual_xres; |
595 | viamode.virtual_yres_sec = viafb_second_virtual_yres; | 597 | u.viamode.virtual_yres_sec = viafb_second_virtual_yres; |
596 | viamode.refresh_sec = viafb_refresh1; | 598 | u.viamode.refresh_sec = viafb_refresh1; |
597 | viamode.bpp_sec = viafb_bpp1; | 599 | u.viamode.bpp_sec = viafb_bpp1; |
598 | } else { | 600 | } else { |
599 | viamode.xres_sec = 0; | 601 | u.viamode.xres_sec = 0; |
600 | viamode.yres_sec = 0; | 602 | u.viamode.yres_sec = 0; |
601 | viamode.virtual_xres_sec = 0; | 603 | u.viamode.virtual_xres_sec = 0; |
602 | viamode.virtual_yres_sec = 0; | 604 | u.viamode.virtual_yres_sec = 0; |
603 | viamode.refresh_sec = 0; | 605 | u.viamode.refresh_sec = 0; |
604 | viamode.bpp_sec = 0; | 606 | u.viamode.bpp_sec = 0; |
605 | } | 607 | } |
606 | if (copy_to_user(argp, &viamode, sizeof(viamode))) | 608 | if (copy_to_user(argp, &u.viamode, sizeof(u.viamode))) |
607 | return -EFAULT; | 609 | return -EFAULT; |
608 | break; | 610 | break; |
609 | case VIAFB_GET_SAMM_INFO: | 611 | case VIAFB_GET_SAMM_INFO: |
610 | viasamm.samm_status = viafb_SAMM_ON; | 612 | u.viasamm.samm_status = viafb_SAMM_ON; |
611 | 613 | ||
612 | if (viafb_SAMM_ON == 1) { | 614 | if (viafb_SAMM_ON == 1) { |
613 | if (viafb_dual_fb) { | 615 | if (viafb_dual_fb) { |
614 | viasamm.size_prim = viaparinfo->fbmem_free; | 616 | u.viasamm.size_prim = viaparinfo->fbmem_free; |
615 | viasamm.size_sec = viaparinfo1->fbmem_free; | 617 | u.viasamm.size_sec = viaparinfo1->fbmem_free; |
616 | } else { | 618 | } else { |
617 | if (viafb_second_size) { | 619 | if (viafb_second_size) { |
618 | viasamm.size_prim = | 620 | u.viasamm.size_prim = |
619 | viaparinfo->fbmem_free - | 621 | viaparinfo->fbmem_free - |
620 | viafb_second_size * 1024 * 1024; | 622 | viafb_second_size * 1024 * 1024; |
621 | viasamm.size_sec = | 623 | u.viasamm.size_sec = |
622 | viafb_second_size * 1024 * 1024; | 624 | viafb_second_size * 1024 * 1024; |
623 | } else { | 625 | } else { |
624 | viasamm.size_prim = | 626 | u.viasamm.size_prim = |
625 | viaparinfo->fbmem_free >> 1; | 627 | viaparinfo->fbmem_free >> 1; |
626 | viasamm.size_sec = | 628 | u.viasamm.size_sec = |
627 | (viaparinfo->fbmem_free >> 1); | 629 | (viaparinfo->fbmem_free >> 1); |
628 | } | 630 | } |
629 | } | 631 | } |
630 | viasamm.mem_base = viaparinfo->fbmem; | 632 | u.viasamm.mem_base = viaparinfo->fbmem; |
631 | viasamm.offset_sec = viafb_second_offset; | 633 | u.viasamm.offset_sec = viafb_second_offset; |
632 | } else { | 634 | } else { |
633 | viasamm.size_prim = | 635 | u.viasamm.size_prim = |
634 | viaparinfo->memsize - viaparinfo->fbmem_used; | 636 | viaparinfo->memsize - viaparinfo->fbmem_used; |
635 | viasamm.size_sec = 0; | 637 | u.viasamm.size_sec = 0; |
636 | viasamm.mem_base = viaparinfo->fbmem; | 638 | u.viasamm.mem_base = viaparinfo->fbmem; |
637 | viasamm.offset_sec = 0; | 639 | u.viasamm.offset_sec = 0; |
638 | } | 640 | } |
639 | 641 | ||
640 | if (copy_to_user(argp, &viasamm, sizeof(viasamm))) | 642 | if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm))) |
641 | return -EFAULT; | 643 | return -EFAULT; |
642 | 644 | ||
643 | break; | 645 | break; |
@@ -662,74 +664,75 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
662 | viafb_lcd_disable(); | 664 | viafb_lcd_disable(); |
663 | break; | 665 | break; |
664 | case VIAFB_SET_DEVICE: | 666 | case VIAFB_SET_DEVICE: |
665 | if (copy_from_user(&active_dev, (void *)argp, | 667 | if (copy_from_user(&u.active_dev, (void *)argp, |
666 | sizeof(active_dev))) | 668 | sizeof(u.active_dev))) |
667 | return -EFAULT; | 669 | return -EFAULT; |
668 | viafb_set_device(active_dev); | 670 | viafb_set_device(u.active_dev); |
669 | viafb_set_par(info); | 671 | viafb_set_par(info); |
670 | break; | 672 | break; |
671 | case VIAFB_GET_DEVICE: | 673 | case VIAFB_GET_DEVICE: |
672 | active_dev.crt = viafb_CRT_ON; | 674 | u.active_dev.crt = viafb_CRT_ON; |
673 | active_dev.dvi = viafb_DVI_ON; | 675 | u.active_dev.dvi = viafb_DVI_ON; |
674 | active_dev.lcd = viafb_LCD_ON; | 676 | u.active_dev.lcd = viafb_LCD_ON; |
675 | active_dev.samm = viafb_SAMM_ON; | 677 | u.active_dev.samm = viafb_SAMM_ON; |
676 | active_dev.primary_dev = viafb_primary_dev; | 678 | u.active_dev.primary_dev = viafb_primary_dev; |
677 | 679 | ||
678 | active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; | 680 | u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; |
679 | active_dev.lcd_panel_id = viafb_lcd_panel_id; | 681 | u.active_dev.lcd_panel_id = viafb_lcd_panel_id; |
680 | active_dev.lcd_mode = viafb_lcd_mode; | 682 | u.active_dev.lcd_mode = viafb_lcd_mode; |
681 | 683 | ||
682 | active_dev.xres = viafb_hotplug_Xres; | 684 | u.active_dev.xres = viafb_hotplug_Xres; |
683 | active_dev.yres = viafb_hotplug_Yres; | 685 | u.active_dev.yres = viafb_hotplug_Yres; |
684 | 686 | ||
685 | active_dev.xres1 = viafb_second_xres; | 687 | u.active_dev.xres1 = viafb_second_xres; |
686 | active_dev.yres1 = viafb_second_yres; | 688 | u.active_dev.yres1 = viafb_second_yres; |
687 | 689 | ||
688 | active_dev.bpp = viafb_bpp; | 690 | u.active_dev.bpp = viafb_bpp; |
689 | active_dev.bpp1 = viafb_bpp1; | 691 | u.active_dev.bpp1 = viafb_bpp1; |
690 | active_dev.refresh = viafb_refresh; | 692 | u.active_dev.refresh = viafb_refresh; |
691 | active_dev.refresh1 = viafb_refresh1; | 693 | u.active_dev.refresh1 = viafb_refresh1; |
692 | 694 | ||
693 | active_dev.epia_dvi = viafb_platform_epia_dvi; | 695 | u.active_dev.epia_dvi = viafb_platform_epia_dvi; |
694 | active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; | 696 | u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; |
695 | active_dev.bus_width = viafb_bus_width; | 697 | u.active_dev.bus_width = viafb_bus_width; |
696 | 698 | ||
697 | if (copy_to_user(argp, &active_dev, sizeof(active_dev))) | 699 | if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev))) |
698 | return -EFAULT; | 700 | return -EFAULT; |
699 | break; | 701 | break; |
700 | 702 | ||
701 | case VIAFB_GET_DRIVER_VERSION: | 703 | case VIAFB_GET_DRIVER_VERSION: |
702 | driver_version.iMajorNum = VERSION_MAJOR; | 704 | u.driver_version.iMajorNum = VERSION_MAJOR; |
703 | driver_version.iKernelNum = VERSION_KERNEL; | 705 | u.driver_version.iKernelNum = VERSION_KERNEL; |
704 | driver_version.iOSNum = VERSION_OS; | 706 | u.driver_version.iOSNum = VERSION_OS; |
705 | driver_version.iMinorNum = VERSION_MINOR; | 707 | u.driver_version.iMinorNum = VERSION_MINOR; |
706 | 708 | ||
707 | if (copy_to_user(argp, &driver_version, | 709 | if (copy_to_user(argp, &u.driver_version, |
708 | sizeof(driver_version))) | 710 | sizeof(u.driver_version))) |
709 | return -EFAULT; | 711 | return -EFAULT; |
710 | 712 | ||
711 | break; | 713 | break; |
712 | 714 | ||
713 | case VIAFB_SET_DEVICE_INFO: | 715 | case VIAFB_SET_DEVICE_INFO: |
714 | if (copy_from_user(&viafb_setting, | 716 | if (copy_from_user(&u.viafb_setting, |
715 | argp, sizeof(viafb_setting))) | 717 | argp, sizeof(u.viafb_setting))) |
716 | return -EFAULT; | 718 | return -EFAULT; |
717 | if (apply_device_setting(viafb_setting, info) < 0) | 719 | if (apply_device_setting(u.viafb_setting, info) < 0) |
718 | return -EINVAL; | 720 | return -EINVAL; |
719 | 721 | ||
720 | break; | 722 | break; |
721 | 723 | ||
722 | case VIAFB_SET_SECOND_MODE: | 724 | case VIAFB_SET_SECOND_MODE: |
723 | if (copy_from_user(&sec_var, argp, sizeof(sec_var))) | 725 | if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var))) |
724 | return -EFAULT; | 726 | return -EFAULT; |
725 | apply_second_mode_setting(&sec_var); | 727 | apply_second_mode_setting(&u.sec_var); |
726 | break; | 728 | break; |
727 | 729 | ||
728 | case VIAFB_GET_DEVICE_INFO: | 730 | case VIAFB_GET_DEVICE_INFO: |
729 | 731 | ||
730 | retrieve_device_setting(&viafb_setting); | 732 | retrieve_device_setting(&u.viafb_setting); |
731 | 733 | ||
732 | if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting))) | 734 | if (copy_to_user(argp, &u.viafb_setting, |
735 | sizeof(u.viafb_setting))) | ||
733 | return -EFAULT; | 736 | return -EFAULT; |
734 | 737 | ||
735 | break; | 738 | break; |
@@ -806,51 +809,51 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
806 | break; | 809 | break; |
807 | 810 | ||
808 | case VIAFB_GET_PANEL_MAX_SIZE: | 811 | case VIAFB_GET_PANEL_MAX_SIZE: |
809 | if (copy_from_user | 812 | if (copy_from_user(&u.panel_pos_size_para, argp, |
810 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 813 | sizeof(u.panel_pos_size_para))) |
811 | return -EFAULT; | 814 | return -EFAULT; |
812 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 815 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
813 | if (copy_to_user(argp, &panel_pos_size_para, | 816 | if (copy_to_user(argp, &u.panel_pos_size_para, |
814 | sizeof(panel_pos_size_para))) | 817 | sizeof(u.panel_pos_size_para))) |
815 | return -EFAULT; | 818 | return -EFAULT; |
816 | break; | 819 | break; |
817 | case VIAFB_GET_PANEL_MAX_POSITION: | 820 | case VIAFB_GET_PANEL_MAX_POSITION: |
818 | if (copy_from_user | 821 | if (copy_from_user(&u.panel_pos_size_para, argp, |
819 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 822 | sizeof(u.panel_pos_size_para))) |
820 | return -EFAULT; | 823 | return -EFAULT; |
821 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 824 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
822 | if (copy_to_user(argp, &panel_pos_size_para, | 825 | if (copy_to_user(argp, &u.panel_pos_size_para, |
823 | sizeof(panel_pos_size_para))) | 826 | sizeof(u.panel_pos_size_para))) |
824 | return -EFAULT; | 827 | return -EFAULT; |
825 | break; | 828 | break; |
826 | 829 | ||
827 | case VIAFB_GET_PANEL_POSITION: | 830 | case VIAFB_GET_PANEL_POSITION: |
828 | if (copy_from_user | 831 | if (copy_from_user(&u.panel_pos_size_para, argp, |
829 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 832 | sizeof(u.panel_pos_size_para))) |
830 | return -EFAULT; | 833 | return -EFAULT; |
831 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 834 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
832 | if (copy_to_user(argp, &panel_pos_size_para, | 835 | if (copy_to_user(argp, &u.panel_pos_size_para, |
833 | sizeof(panel_pos_size_para))) | 836 | sizeof(u.panel_pos_size_para))) |
834 | return -EFAULT; | 837 | return -EFAULT; |
835 | break; | 838 | break; |
836 | case VIAFB_GET_PANEL_SIZE: | 839 | case VIAFB_GET_PANEL_SIZE: |
837 | if (copy_from_user | 840 | if (copy_from_user(&u.panel_pos_size_para, argp, |
838 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 841 | sizeof(u.panel_pos_size_para))) |
839 | return -EFAULT; | 842 | return -EFAULT; |
840 | panel_pos_size_para.x = panel_pos_size_para.y = 0; | 843 | u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; |
841 | if (copy_to_user(argp, &panel_pos_size_para, | 844 | if (copy_to_user(argp, &u.panel_pos_size_para, |
842 | sizeof(panel_pos_size_para))) | 845 | sizeof(u.panel_pos_size_para))) |
843 | return -EFAULT; | 846 | return -EFAULT; |
844 | break; | 847 | break; |
845 | 848 | ||
846 | case VIAFB_SET_PANEL_POSITION: | 849 | case VIAFB_SET_PANEL_POSITION: |
847 | if (copy_from_user | 850 | if (copy_from_user(&u.panel_pos_size_para, argp, |
848 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 851 | sizeof(u.panel_pos_size_para))) |
849 | return -EFAULT; | 852 | return -EFAULT; |
850 | break; | 853 | break; |
851 | case VIAFB_SET_PANEL_SIZE: | 854 | case VIAFB_SET_PANEL_SIZE: |
852 | if (copy_from_user | 855 | if (copy_from_user(&u.panel_pos_size_para, argp, |
853 | (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) | 856 | sizeof(u.panel_pos_size_para))) |
854 | return -EFAULT; | 857 | return -EFAULT; |
855 | break; | 858 | break; |
856 | 859 | ||
@@ -1052,10 +1055,8 @@ static void viafb_imageblit(struct fb_info *info, | |||
1052 | 1055 | ||
1053 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 1056 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) |
1054 | { | 1057 | { |
1055 | u8 data[CURSOR_SIZE / 8]; | ||
1056 | u32 data_bak[CURSOR_SIZE / 32]; | ||
1057 | u32 temp, xx, yy, bg_col = 0, fg_col = 0; | 1058 | u32 temp, xx, yy, bg_col = 0, fg_col = 0; |
1058 | int size, i, j = 0; | 1059 | int i, j = 0; |
1059 | static int hw_cursor; | 1060 | static int hw_cursor; |
1060 | struct viafb_par *p_viafb_par; | 1061 | struct viafb_par *p_viafb_par; |
1061 | 1062 | ||
@@ -1178,22 +1179,29 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1178 | } | 1179 | } |
1179 | 1180 | ||
1180 | if (cursor->set & FB_CUR_SETSHAPE) { | 1181 | if (cursor->set & FB_CUR_SETSHAPE) { |
1181 | size = | 1182 | struct { |
1183 | u8 data[CURSOR_SIZE / 8]; | ||
1184 | u32 bak[CURSOR_SIZE / 32]; | ||
1185 | } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC); | ||
1186 | int size = | ||
1182 | ((viacursor.image.width + 7) >> 3) * | 1187 | ((viacursor.image.width + 7) >> 3) * |
1183 | viacursor.image.height; | 1188 | viacursor.image.height; |
1184 | 1189 | ||
1190 | if (cr_data == NULL) | ||
1191 | goto out; | ||
1192 | |||
1185 | if (MAX_CURS == 32) { | 1193 | if (MAX_CURS == 32) { |
1186 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { | 1194 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { |
1187 | data_bak[i] = 0x0; | 1195 | cr_data->bak[i] = 0x0; |
1188 | data_bak[i + 1] = 0xFFFFFFFF; | 1196 | cr_data->bak[i + 1] = 0xFFFFFFFF; |
1189 | i += 1; | 1197 | i += 1; |
1190 | } | 1198 | } |
1191 | } else if (MAX_CURS == 64) { | 1199 | } else if (MAX_CURS == 64) { |
1192 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { | 1200 | for (i = 0; i < (CURSOR_SIZE / 32); i++) { |
1193 | data_bak[i] = 0x0; | 1201 | cr_data->bak[i] = 0x0; |
1194 | data_bak[i + 1] = 0x0; | 1202 | cr_data->bak[i + 1] = 0x0; |
1195 | data_bak[i + 2] = 0xFFFFFFFF; | 1203 | cr_data->bak[i + 2] = 0xFFFFFFFF; |
1196 | data_bak[i + 3] = 0xFFFFFFFF; | 1204 | cr_data->bak[i + 3] = 0xFFFFFFFF; |
1197 | i += 3; | 1205 | i += 3; |
1198 | } | 1206 | } |
1199 | } | 1207 | } |
@@ -1201,12 +1209,12 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1201 | switch (viacursor.rop) { | 1209 | switch (viacursor.rop) { |
1202 | case ROP_XOR: | 1210 | case ROP_XOR: |
1203 | for (i = 0; i < size; i++) | 1211 | for (i = 0; i < size; i++) |
1204 | data[i] = viacursor.mask[i]; | 1212 | cr_data->data[i] = viacursor.mask[i]; |
1205 | break; | 1213 | break; |
1206 | case ROP_COPY: | 1214 | case ROP_COPY: |
1207 | 1215 | ||
1208 | for (i = 0; i < size; i++) | 1216 | for (i = 0; i < size; i++) |
1209 | data[i] = viacursor.mask[i]; | 1217 | cr_data->data[i] = viacursor.mask[i]; |
1210 | break; | 1218 | break; |
1211 | default: | 1219 | default: |
1212 | break; | 1220 | break; |
@@ -1214,23 +1222,25 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1214 | 1222 | ||
1215 | if (MAX_CURS == 32) { | 1223 | if (MAX_CURS == 32) { |
1216 | for (i = 0; i < size; i++) { | 1224 | for (i = 0; i < size; i++) { |
1217 | data_bak[j] = (u32) data[i]; | 1225 | cr_data->bak[j] = (u32) cr_data->data[i]; |
1218 | data_bak[j + 1] = ~data_bak[j]; | 1226 | cr_data->bak[j + 1] = ~cr_data->bak[j]; |
1219 | j += 2; | 1227 | j += 2; |
1220 | } | 1228 | } |
1221 | } else if (MAX_CURS == 64) { | 1229 | } else if (MAX_CURS == 64) { |
1222 | for (i = 0; i < size; i++) { | 1230 | for (i = 0; i < size; i++) { |
1223 | data_bak[j] = (u32) data[i]; | 1231 | cr_data->bak[j] = (u32) cr_data->data[i]; |
1224 | data_bak[j + 1] = 0x0; | 1232 | cr_data->bak[j + 1] = 0x0; |
1225 | data_bak[j + 2] = ~data_bak[j]; | 1233 | cr_data->bak[j + 2] = ~cr_data->bak[j]; |
1226 | data_bak[j + 3] = ~data_bak[j + 1]; | 1234 | cr_data->bak[j + 3] = ~cr_data->bak[j + 1]; |
1227 | j += 4; | 1235 | j += 4; |
1228 | } | 1236 | } |
1229 | } | 1237 | } |
1230 | 1238 | ||
1231 | memcpy(((struct viafb_par *)(info->par))->fbmem_virt + | 1239 | memcpy(((struct viafb_par *)(info->par))->fbmem_virt + |
1232 | ((struct viafb_par *)(info->par))->cursor_start, | 1240 | ((struct viafb_par *)(info->par))->cursor_start, |
1233 | data_bak, CURSOR_SIZE); | 1241 | cr_data->bak, CURSOR_SIZE); |
1242 | out: | ||
1243 | kfree(cr_data); | ||
1234 | } | 1244 | } |
1235 | 1245 | ||
1236 | if (viacursor.enable) | 1246 | if (viacursor.enable) |