diff options
Diffstat (limited to 'drivers')
77 files changed, 5369 insertions, 2703 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 368ae6d3a096..a2b902f4d437 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -96,8 +96,6 @@ source "drivers/edac/Kconfig" | |||
| 96 | 96 | ||
| 97 | source "drivers/rtc/Kconfig" | 97 | source "drivers/rtc/Kconfig" |
| 98 | 98 | ||
| 99 | source "drivers/clocksource/Kconfig" | ||
| 100 | |||
| 101 | source "drivers/dma/Kconfig" | 99 | source "drivers/dma/Kconfig" |
| 102 | 100 | ||
| 103 | source "drivers/dca/Kconfig" | 101 | source "drivers/dca/Kconfig" |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig deleted file mode 100644 index 08f726c5fee5..000000000000 --- a/drivers/clocksource/Kconfig +++ /dev/null | |||
| @@ -1,9 +0,0 @@ | |||
| 1 | config CS5535_CLOCK_EVENT_SRC | ||
| 2 | tristate "CS5535/CS5536 high-res timer (MFGPT) events" | ||
| 3 | depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT | ||
| 4 | help | ||
| 5 | This driver provides a clock event source based on the MFGPT | ||
| 6 | timer(s) in the CS5535 and CS5536 companion chips. | ||
| 7 | MFGPTs have a better resolution and max interval than the | ||
| 8 | generic PIT, and are suitable for use as high-res timers. | ||
| 9 | |||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 73655aeb3a60..1aea7157d8ff 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
| @@ -100,8 +100,8 @@ struct menu_device { | |||
| 100 | int needs_update; | 100 | int needs_update; |
| 101 | 101 | ||
| 102 | unsigned int expected_us; | 102 | unsigned int expected_us; |
| 103 | u64 predicted_us; | ||
| 104 | unsigned int measured_us; | 103 | unsigned int measured_us; |
| 104 | u64 predicted_us; | ||
| 105 | unsigned int exit_us; | 105 | unsigned int exit_us; |
| 106 | unsigned int bucket; | 106 | unsigned int bucket; |
| 107 | u64 correction_factor[BUCKETS]; | 107 | u64 correction_factor[BUCKETS]; |
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 5d0e42b263df..af14c9a5b8d4 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c | |||
| @@ -71,7 +71,7 @@ static irqreturn_t ioat_dma_do_interrupt(int irq, void *data) | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET); | 73 | attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET); |
| 74 | for_each_bit(bit, &attnstatus, BITS_PER_LONG) { | 74 | for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) { |
| 75 | chan = ioat_chan_by_index(instance, bit); | 75 | chan = ioat_chan_by_index(instance, bit); |
| 76 | tasklet_schedule(&chan->cleanup_task); | 76 | tasklet_schedule(&chan->cleanup_task); |
| 77 | } | 77 | } |
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 66958b3f10b4..806c77bfd434 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c | |||
| @@ -39,10 +39,10 @@ static unsigned int enable_dev_count; | |||
| 39 | static int disable_dev[EISA_MAX_FORCED_DEV]; | 39 | static int disable_dev[EISA_MAX_FORCED_DEV]; |
| 40 | static unsigned int disable_dev_count; | 40 | static unsigned int disable_dev_count; |
| 41 | 41 | ||
| 42 | static int is_forced_dev (int *forced_tab, | 42 | static int is_forced_dev(int *forced_tab, |
| 43 | int forced_count, | 43 | int forced_count, |
| 44 | struct eisa_root_device *root, | 44 | struct eisa_root_device *root, |
| 45 | struct eisa_device *edev) | 45 | struct eisa_device *edev) |
| 46 | { | 46 | { |
| 47 | int i, x; | 47 | int i, x; |
| 48 | 48 | ||
| @@ -55,21 +55,21 @@ static int is_forced_dev (int *forced_tab, | |||
| 55 | return 0; | 55 | return 0; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static void __init eisa_name_device (struct eisa_device *edev) | 58 | static void __init eisa_name_device(struct eisa_device *edev) |
| 59 | { | 59 | { |
| 60 | #ifdef CONFIG_EISA_NAMES | 60 | #ifdef CONFIG_EISA_NAMES |
| 61 | int i; | 61 | int i; |
| 62 | for (i = 0; i < EISA_INFOS; i++) { | 62 | for (i = 0; i < EISA_INFOS; i++) { |
| 63 | if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) { | 63 | if (!strcmp(edev->id.sig, eisa_table[i].id.sig)) { |
| 64 | strlcpy (edev->pretty_name, | 64 | strlcpy(edev->pretty_name, |
| 65 | eisa_table[i].name, | 65 | eisa_table[i].name, |
| 66 | sizeof(edev->pretty_name)); | 66 | sizeof(edev->pretty_name)); |
| 67 | return; | 67 | return; |
| 68 | } | 68 | } |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | /* No name was found */ | 71 | /* No name was found */ |
| 72 | sprintf (edev->pretty_name, "EISA device %.7s", edev->id.sig); | 72 | sprintf(edev->pretty_name, "EISA device %.7s", edev->id.sig); |
| 73 | #endif | 73 | #endif |
| 74 | } | 74 | } |
| 75 | 75 | ||
| @@ -91,7 +91,7 @@ static char __init *decode_eisa_sig(unsigned long addr) | |||
| 91 | */ | 91 | */ |
| 92 | outb(0x80 + i, addr); | 92 | outb(0x80 + i, addr); |
| 93 | #endif | 93 | #endif |
| 94 | sig[i] = inb (addr + i); | 94 | sig[i] = inb(addr + i); |
| 95 | 95 | ||
| 96 | if (!i && (sig[0] & 0x80)) | 96 | if (!i && (sig[0] & 0x80)) |
| 97 | return NULL; | 97 | return NULL; |
| @@ -106,17 +106,17 @@ static char __init *decode_eisa_sig(unsigned long addr) | |||
| 106 | return sig_str; | 106 | return sig_str; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static int eisa_bus_match (struct device *dev, struct device_driver *drv) | 109 | static int eisa_bus_match(struct device *dev, struct device_driver *drv) |
| 110 | { | 110 | { |
| 111 | struct eisa_device *edev = to_eisa_device (dev); | 111 | struct eisa_device *edev = to_eisa_device(dev); |
| 112 | struct eisa_driver *edrv = to_eisa_driver (drv); | 112 | struct eisa_driver *edrv = to_eisa_driver(drv); |
| 113 | const struct eisa_device_id *eids = edrv->id_table; | 113 | const struct eisa_device_id *eids = edrv->id_table; |
| 114 | 114 | ||
| 115 | if (!eids) | 115 | if (!eids) |
| 116 | return 0; | 116 | return 0; |
| 117 | 117 | ||
| 118 | while (strlen (eids->sig)) { | 118 | while (strlen(eids->sig)) { |
| 119 | if (!strcmp (eids->sig, edev->id.sig) && | 119 | if (!strcmp(eids->sig, edev->id.sig) && |
| 120 | edev->state & EISA_CONFIG_ENABLED) { | 120 | edev->state & EISA_CONFIG_ENABLED) { |
| 121 | edev->id.driver_data = eids->driver_data; | 121 | edev->id.driver_data = eids->driver_data; |
| 122 | return 1; | 122 | return 1; |
| @@ -141,61 +141,71 @@ struct bus_type eisa_bus_type = { | |||
| 141 | .match = eisa_bus_match, | 141 | .match = eisa_bus_match, |
| 142 | .uevent = eisa_bus_uevent, | 142 | .uevent = eisa_bus_uevent, |
| 143 | }; | 143 | }; |
| 144 | EXPORT_SYMBOL(eisa_bus_type); | ||
| 144 | 145 | ||
| 145 | int eisa_driver_register (struct eisa_driver *edrv) | 146 | int eisa_driver_register(struct eisa_driver *edrv) |
| 146 | { | 147 | { |
| 147 | edrv->driver.bus = &eisa_bus_type; | 148 | edrv->driver.bus = &eisa_bus_type; |
| 148 | return driver_register (&edrv->driver); | 149 | return driver_register(&edrv->driver); |
| 149 | } | 150 | } |
| 151 | EXPORT_SYMBOL(eisa_driver_register); | ||
| 150 | 152 | ||
| 151 | void eisa_driver_unregister (struct eisa_driver *edrv) | 153 | void eisa_driver_unregister(struct eisa_driver *edrv) |
| 152 | { | 154 | { |
| 153 | driver_unregister (&edrv->driver); | 155 | driver_unregister(&edrv->driver); |
| 154 | } | 156 | } |
| 157 | EXPORT_SYMBOL(eisa_driver_unregister); | ||
| 155 | 158 | ||
| 156 | static ssize_t eisa_show_sig (struct device *dev, struct device_attribute *attr, char *buf) | 159 | static ssize_t eisa_show_sig(struct device *dev, struct device_attribute *attr, |
| 160 | char *buf) | ||
| 157 | { | 161 | { |
| 158 | struct eisa_device *edev = to_eisa_device (dev); | 162 | struct eisa_device *edev = to_eisa_device(dev); |
| 159 | return sprintf (buf,"%s\n", edev->id.sig); | 163 | return sprintf(buf, "%s\n", edev->id.sig); |
| 160 | } | 164 | } |
| 161 | 165 | ||
| 162 | static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL); | 166 | static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL); |
| 163 | 167 | ||
| 164 | static ssize_t eisa_show_state (struct device *dev, struct device_attribute *attr, char *buf) | 168 | static ssize_t eisa_show_state(struct device *dev, |
| 169 | struct device_attribute *attr, | ||
| 170 | char *buf) | ||
| 165 | { | 171 | { |
| 166 | struct eisa_device *edev = to_eisa_device (dev); | 172 | struct eisa_device *edev = to_eisa_device(dev); |
| 167 | return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED); | 173 | return sprintf(buf, "%d\n", edev->state & EISA_CONFIG_ENABLED); |
| 168 | } | 174 | } |
| 169 | 175 | ||
| 170 | static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL); | 176 | static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL); |
| 171 | 177 | ||
| 172 | static ssize_t eisa_show_modalias (struct device *dev, struct device_attribute *attr, char *buf) | 178 | static ssize_t eisa_show_modalias(struct device *dev, |
| 179 | struct device_attribute *attr, | ||
| 180 | char *buf) | ||
| 173 | { | 181 | { |
| 174 | struct eisa_device *edev = to_eisa_device (dev); | 182 | struct eisa_device *edev = to_eisa_device(dev); |
| 175 | return sprintf (buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig); | 183 | return sprintf(buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig); |
| 176 | } | 184 | } |
| 177 | 185 | ||
| 178 | static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL); | 186 | static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL); |
| 179 | 187 | ||
| 180 | static int __init eisa_init_device (struct eisa_root_device *root, | 188 | static int __init eisa_init_device(struct eisa_root_device *root, |
| 181 | struct eisa_device *edev, | 189 | struct eisa_device *edev, |
| 182 | int slot) | 190 | int slot) |
| 183 | { | 191 | { |
| 184 | char *sig; | 192 | char *sig; |
| 185 | unsigned long sig_addr; | 193 | unsigned long sig_addr; |
| 186 | int i; | 194 | int i; |
| 187 | 195 | ||
| 188 | sig_addr = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET; | 196 | sig_addr = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET; |
| 189 | 197 | ||
| 190 | if (!(sig = decode_eisa_sig (sig_addr))) | 198 | sig = decode_eisa_sig(sig_addr); |
| 199 | if (!sig) | ||
| 191 | return -1; /* No EISA device here */ | 200 | return -1; /* No EISA device here */ |
| 192 | 201 | ||
| 193 | memcpy (edev->id.sig, sig, EISA_SIG_LEN); | 202 | memcpy(edev->id.sig, sig, EISA_SIG_LEN); |
| 194 | edev->slot = slot; | 203 | edev->slot = slot; |
| 195 | edev->state = inb (SLOT_ADDRESS (root, slot) + EISA_CONFIG_OFFSET) & EISA_CONFIG_ENABLED; | 204 | edev->state = inb(SLOT_ADDRESS(root, slot) + EISA_CONFIG_OFFSET) |
| 196 | edev->base_addr = SLOT_ADDRESS (root, slot); | 205 | & EISA_CONFIG_ENABLED; |
| 206 | edev->base_addr = SLOT_ADDRESS(root, slot); | ||
| 197 | edev->dma_mask = root->dma_mask; /* Default DMA mask */ | 207 | edev->dma_mask = root->dma_mask; /* Default DMA mask */ |
| 198 | eisa_name_device (edev); | 208 | eisa_name_device(edev); |
| 199 | edev->dev.parent = root->dev; | 209 | edev->dev.parent = root->dev; |
| 200 | edev->dev.bus = &eisa_bus_type; | 210 | edev->dev.bus = &eisa_bus_type; |
| 201 | edev->dev.dma_mask = &edev->dma_mask; | 211 | edev->dev.dma_mask = &edev->dma_mask; |
| @@ -210,42 +220,45 @@ static int __init eisa_init_device (struct eisa_root_device *root, | |||
| 210 | #endif | 220 | #endif |
| 211 | } | 221 | } |
| 212 | 222 | ||
| 213 | if (is_forced_dev (enable_dev, enable_dev_count, root, edev)) | 223 | if (is_forced_dev(enable_dev, enable_dev_count, root, edev)) |
| 214 | edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED; | 224 | edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED; |
| 215 | 225 | ||
| 216 | if (is_forced_dev (disable_dev, disable_dev_count, root, edev)) | 226 | if (is_forced_dev(disable_dev, disable_dev_count, root, edev)) |
| 217 | edev->state = EISA_CONFIG_FORCED; | 227 | edev->state = EISA_CONFIG_FORCED; |
| 218 | 228 | ||
| 219 | return 0; | 229 | return 0; |
| 220 | } | 230 | } |
| 221 | 231 | ||
| 222 | static int __init eisa_register_device (struct eisa_device *edev) | 232 | static int __init eisa_register_device(struct eisa_device *edev) |
| 223 | { | 233 | { |
| 224 | int rc = device_register (&edev->dev); | 234 | int rc = device_register(&edev->dev); |
| 225 | if (rc) | 235 | if (rc) |
| 226 | return rc; | 236 | return rc; |
| 227 | 237 | ||
| 228 | rc = device_create_file (&edev->dev, &dev_attr_signature); | 238 | rc = device_create_file(&edev->dev, &dev_attr_signature); |
| 229 | if (rc) goto err_devreg; | 239 | if (rc) |
| 230 | rc = device_create_file (&edev->dev, &dev_attr_enabled); | 240 | goto err_devreg; |
| 231 | if (rc) goto err_sig; | 241 | rc = device_create_file(&edev->dev, &dev_attr_enabled); |
| 232 | rc = device_create_file (&edev->dev, &dev_attr_modalias); | 242 | if (rc) |
| 233 | if (rc) goto err_enab; | 243 | goto err_sig; |
| 244 | rc = device_create_file(&edev->dev, &dev_attr_modalias); | ||
| 245 | if (rc) | ||
| 246 | goto err_enab; | ||
| 234 | 247 | ||
| 235 | return 0; | 248 | return 0; |
| 236 | 249 | ||
| 237 | err_enab: | 250 | err_enab: |
| 238 | device_remove_file (&edev->dev, &dev_attr_enabled); | 251 | device_remove_file(&edev->dev, &dev_attr_enabled); |
| 239 | err_sig: | 252 | err_sig: |
| 240 | device_remove_file (&edev->dev, &dev_attr_signature); | 253 | device_remove_file(&edev->dev, &dev_attr_signature); |
| 241 | err_devreg: | 254 | err_devreg: |
| 242 | device_unregister(&edev->dev); | 255 | device_unregister(&edev->dev); |
| 243 | return rc; | 256 | return rc; |
| 244 | } | 257 | } |
| 245 | 258 | ||
| 246 | static int __init eisa_request_resources (struct eisa_root_device *root, | 259 | static int __init eisa_request_resources(struct eisa_root_device *root, |
| 247 | struct eisa_device *edev, | 260 | struct eisa_device *edev, |
| 248 | int slot) | 261 | int slot) |
| 249 | { | 262 | { |
| 250 | int i; | 263 | int i; |
| 251 | 264 | ||
| @@ -263,17 +276,19 @@ static int __init eisa_request_resources (struct eisa_root_device *root, | |||
| 263 | 276 | ||
| 264 | if (slot) { | 277 | if (slot) { |
| 265 | edev->res[i].name = NULL; | 278 | edev->res[i].name = NULL; |
| 266 | edev->res[i].start = SLOT_ADDRESS (root, slot) + (i * 0x400); | 279 | edev->res[i].start = SLOT_ADDRESS(root, slot) |
| 280 | + (i * 0x400); | ||
| 267 | edev->res[i].end = edev->res[i].start + 0xff; | 281 | edev->res[i].end = edev->res[i].start + 0xff; |
| 268 | edev->res[i].flags = IORESOURCE_IO; | 282 | edev->res[i].flags = IORESOURCE_IO; |
| 269 | } else { | 283 | } else { |
| 270 | edev->res[i].name = NULL; | 284 | edev->res[i].name = NULL; |
| 271 | edev->res[i].start = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET; | 285 | edev->res[i].start = SLOT_ADDRESS(root, slot) |
| 286 | + EISA_VENDOR_ID_OFFSET; | ||
| 272 | edev->res[i].end = edev->res[i].start + 3; | 287 | edev->res[i].end = edev->res[i].start + 3; |
| 273 | edev->res[i].flags = IORESOURCE_BUSY; | 288 | edev->res[i].flags = IORESOURCE_BUSY; |
| 274 | } | 289 | } |
| 275 | 290 | ||
| 276 | if (request_resource (root->res, &edev->res[i])) | 291 | if (request_resource(root->res, &edev->res[i])) |
| 277 | goto failed; | 292 | goto failed; |
| 278 | } | 293 | } |
| 279 | 294 | ||
| @@ -281,99 +296,100 @@ static int __init eisa_request_resources (struct eisa_root_device *root, | |||
| 281 | 296 | ||
| 282 | failed: | 297 | failed: |
| 283 | while (--i >= 0) | 298 | while (--i >= 0) |
| 284 | release_resource (&edev->res[i]); | 299 | release_resource(&edev->res[i]); |
| 285 | 300 | ||
| 286 | return -1; | 301 | return -1; |
| 287 | } | 302 | } |
| 288 | 303 | ||
| 289 | static void __init eisa_release_resources (struct eisa_device *edev) | 304 | static void __init eisa_release_resources(struct eisa_device *edev) |
| 290 | { | 305 | { |
| 291 | int i; | 306 | int i; |
| 292 | 307 | ||
| 293 | for (i = 0; i < EISA_MAX_RESOURCES; i++) | 308 | for (i = 0; i < EISA_MAX_RESOURCES; i++) |
| 294 | if (edev->res[i].start || edev->res[i].end) | 309 | if (edev->res[i].start || edev->res[i].end) |
| 295 | release_resource (&edev->res[i]); | 310 | release_resource(&edev->res[i]); |
| 296 | } | 311 | } |
| 297 | 312 | ||
| 298 | static int __init eisa_probe (struct eisa_root_device *root) | 313 | static int __init eisa_probe(struct eisa_root_device *root) |
| 299 | { | 314 | { |
| 300 | int i, c; | 315 | int i, c; |
| 301 | struct eisa_device *edev; | 316 | struct eisa_device *edev; |
| 302 | 317 | ||
| 303 | printk (KERN_INFO "EISA: Probing bus %d at %s\n", | 318 | printk(KERN_INFO "EISA: Probing bus %d at %s\n", |
| 304 | root->bus_nr, dev_name(root->dev)); | 319 | root->bus_nr, dev_name(root->dev)); |
| 305 | 320 | ||
| 306 | /* First try to get hold of slot 0. If there is no device | 321 | /* First try to get hold of slot 0. If there is no device |
| 307 | * here, simply fail, unless root->force_probe is set. */ | 322 | * here, simply fail, unless root->force_probe is set. */ |
| 308 | 323 | ||
| 309 | if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) { | 324 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); |
| 310 | printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n"); | 325 | if (!edev) { |
| 326 | printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n"); | ||
| 311 | return -ENOMEM; | 327 | return -ENOMEM; |
| 312 | } | 328 | } |
| 313 | 329 | ||
| 314 | if (eisa_request_resources (root, edev, 0)) { | 330 | if (eisa_request_resources(root, edev, 0)) { |
| 315 | printk (KERN_WARNING \ | 331 | printk(KERN_WARNING \ |
| 316 | "EISA: Cannot allocate resource for mainboard\n"); | 332 | "EISA: Cannot allocate resource for mainboard\n"); |
| 317 | kfree (edev); | 333 | kfree(edev); |
| 318 | if (!root->force_probe) | 334 | if (!root->force_probe) |
| 319 | return -EBUSY; | 335 | return -EBUSY; |
| 320 | goto force_probe; | 336 | goto force_probe; |
| 321 | } | 337 | } |
| 322 | 338 | ||
| 323 | if (eisa_init_device (root, edev, 0)) { | 339 | if (eisa_init_device(root, edev, 0)) { |
| 324 | eisa_release_resources (edev); | 340 | eisa_release_resources(edev); |
| 325 | kfree (edev); | 341 | kfree(edev); |
| 326 | if (!root->force_probe) | 342 | if (!root->force_probe) |
| 327 | return -ENODEV; | 343 | return -ENODEV; |
| 328 | goto force_probe; | 344 | goto force_probe; |
| 329 | } | 345 | } |
| 330 | 346 | ||
| 331 | printk (KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig); | 347 | printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig); |
| 332 | 348 | ||
| 333 | if (eisa_register_device (edev)) { | 349 | if (eisa_register_device(edev)) { |
| 334 | printk (KERN_ERR "EISA: Failed to register %s\n", | 350 | printk(KERN_ERR "EISA: Failed to register %s\n", |
| 335 | edev->id.sig); | 351 | edev->id.sig); |
| 336 | eisa_release_resources (edev); | 352 | eisa_release_resources(edev); |
| 337 | kfree (edev); | 353 | kfree(edev); |
| 338 | } | 354 | } |
| 339 | 355 | ||
| 340 | force_probe: | 356 | force_probe: |
| 341 | 357 | ||
| 342 | for (c = 0, i = 1; i <= root->slots; i++) { | 358 | for (c = 0, i = 1; i <= root->slots; i++) { |
| 343 | if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) { | 359 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); |
| 344 | printk (KERN_ERR "EISA: Out of memory for slot %d\n", | 360 | if (!edev) { |
| 345 | i); | 361 | printk(KERN_ERR "EISA: Out of memory for slot %d\n", i); |
| 346 | continue; | 362 | continue; |
| 347 | } | 363 | } |
| 348 | 364 | ||
| 349 | if (eisa_request_resources (root, edev, i)) { | 365 | if (eisa_request_resources(root, edev, i)) { |
| 350 | printk (KERN_WARNING \ | 366 | printk(KERN_WARNING \ |
| 351 | "Cannot allocate resource for EISA slot %d\n", | 367 | "Cannot allocate resource for EISA slot %d\n", |
| 352 | i); | 368 | i); |
| 353 | kfree (edev); | 369 | kfree(edev); |
| 354 | continue; | 370 | continue; |
| 355 | } | 371 | } |
| 356 | 372 | ||
| 357 | if (eisa_init_device (root, edev, i)) { | 373 | if (eisa_init_device(root, edev, i)) { |
| 358 | eisa_release_resources (edev); | 374 | eisa_release_resources(edev); |
| 359 | kfree (edev); | 375 | kfree(edev); |
| 360 | continue; | 376 | continue; |
| 361 | } | 377 | } |
| 362 | 378 | ||
| 363 | printk (KERN_INFO "EISA: slot %d : %s detected", | 379 | printk(KERN_INFO "EISA: slot %d : %s detected", |
| 364 | i, edev->id.sig); | 380 | i, edev->id.sig); |
| 365 | 381 | ||
| 366 | switch (edev->state) { | 382 | switch (edev->state) { |
| 367 | case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED: | 383 | case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED: |
| 368 | printk (" (forced enabled)"); | 384 | printk(" (forced enabled)"); |
| 369 | break; | 385 | break; |
| 370 | 386 | ||
| 371 | case EISA_CONFIG_FORCED: | 387 | case EISA_CONFIG_FORCED: |
| 372 | printk (" (forced disabled)"); | 388 | printk(" (forced disabled)"); |
| 373 | break; | 389 | break; |
| 374 | 390 | ||
| 375 | case 0: | 391 | case 0: |
| 376 | printk (" (disabled)"); | 392 | printk(" (disabled)"); |
| 377 | break; | 393 | break; |
| 378 | } | 394 | } |
| 379 | 395 | ||
| @@ -381,15 +397,15 @@ static int __init eisa_probe (struct eisa_root_device *root) | |||
| 381 | 397 | ||
| 382 | c++; | 398 | c++; |
| 383 | 399 | ||
| 384 | if (eisa_register_device (edev)) { | 400 | if (eisa_register_device(edev)) { |
| 385 | printk (KERN_ERR "EISA: Failed to register %s\n", | 401 | printk(KERN_ERR "EISA: Failed to register %s\n", |
| 386 | edev->id.sig); | 402 | edev->id.sig); |
| 387 | eisa_release_resources (edev); | 403 | eisa_release_resources(edev); |
| 388 | kfree (edev); | 404 | kfree(edev); |
| 389 | } | 405 | } |
| 390 | } | 406 | } |
| 391 | 407 | ||
| 392 | printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s"); | 408 | printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s"); |
| 393 | 409 | ||
| 394 | return 0; | 410 | return 0; |
| 395 | } | 411 | } |
| @@ -403,7 +419,7 @@ static struct resource eisa_root_res = { | |||
| 403 | 419 | ||
| 404 | static int eisa_bus_count; | 420 | static int eisa_bus_count; |
| 405 | 421 | ||
| 406 | int __init eisa_root_register (struct eisa_root_device *root) | 422 | int __init eisa_root_register(struct eisa_root_device *root) |
| 407 | { | 423 | { |
| 408 | int err; | 424 | int err; |
| 409 | 425 | ||
| @@ -417,35 +433,35 @@ int __init eisa_root_register (struct eisa_root_device *root) | |||
| 417 | root->eisa_root_res.end = root->res->end; | 433 | root->eisa_root_res.end = root->res->end; |
| 418 | root->eisa_root_res.flags = IORESOURCE_BUSY; | 434 | root->eisa_root_res.flags = IORESOURCE_BUSY; |
| 419 | 435 | ||
| 420 | if ((err = request_resource (&eisa_root_res, &root->eisa_root_res))) | 436 | err = request_resource(&eisa_root_res, &root->eisa_root_res); |
| 437 | if (err) | ||
| 421 | return err; | 438 | return err; |
| 422 | 439 | ||
| 423 | root->bus_nr = eisa_bus_count++; | 440 | root->bus_nr = eisa_bus_count++; |
| 424 | 441 | ||
| 425 | if ((err = eisa_probe (root))) | 442 | err = eisa_probe(root); |
| 426 | release_resource (&root->eisa_root_res); | 443 | if (err) |
| 444 | release_resource(&root->eisa_root_res); | ||
| 427 | 445 | ||
| 428 | return err; | 446 | return err; |
| 429 | } | 447 | } |
| 430 | 448 | ||
| 431 | static int __init eisa_init (void) | 449 | static int __init eisa_init(void) |
| 432 | { | 450 | { |
| 433 | int r; | 451 | int r; |
| 434 | 452 | ||
| 435 | if ((r = bus_register (&eisa_bus_type))) | 453 | r = bus_register(&eisa_bus_type); |
| 454 | if (r) | ||
| 436 | return r; | 455 | return r; |
| 437 | 456 | ||
| 438 | printk (KERN_INFO "EISA bus registered\n"); | 457 | printk(KERN_INFO "EISA bus registered\n"); |
| 439 | return 0; | 458 | return 0; |
| 440 | } | 459 | } |
| 441 | 460 | ||
| 442 | module_param_array(enable_dev, int, &enable_dev_count, 0444); | 461 | module_param_array(enable_dev, int, &enable_dev_count, 0444); |
| 443 | module_param_array(disable_dev, int, &disable_dev_count, 0444); | 462 | module_param_array(disable_dev, int, &disable_dev_count, 0444); |
| 444 | 463 | ||
| 445 | postcore_initcall (eisa_init); | 464 | postcore_initcall(eisa_init); |
| 446 | 465 | ||
| 447 | int EISA_bus; /* for legacy drivers */ | 466 | int EISA_bus; /* for legacy drivers */ |
| 448 | EXPORT_SYMBOL (EISA_bus); | 467 | EXPORT_SYMBOL(EISA_bus); |
| 449 | EXPORT_SYMBOL (eisa_bus_type); | ||
| 450 | EXPORT_SYMBOL (eisa_driver_register); | ||
| 451 | EXPORT_SYMBOL (eisa_driver_unregister); | ||
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index 56f9234781fa..20f645743ead 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c | |||
| @@ -122,29 +122,53 @@ static int firmware_map_add_entry(u64 start, u64 end, | |||
| 122 | return 0; | 122 | return 0; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | /* | ||
| 126 | * Add memmap entry on sysfs | ||
| 127 | */ | ||
| 128 | static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry) | ||
| 129 | { | ||
| 130 | static int map_entries_nr; | ||
| 131 | static struct kset *mmap_kset; | ||
| 132 | |||
| 133 | if (!mmap_kset) { | ||
| 134 | mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj); | ||
| 135 | if (!mmap_kset) | ||
| 136 | return -ENOMEM; | ||
| 137 | } | ||
| 138 | |||
| 139 | entry->kobj.kset = mmap_kset; | ||
| 140 | if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++)) | ||
| 141 | kobject_put(&entry->kobj); | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 125 | /** | 146 | /** |
| 126 | * firmware_map_add() - Adds a firmware mapping entry. | 147 | * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do |
| 148 | * memory hotplug. | ||
| 127 | * @start: Start of the memory range. | 149 | * @start: Start of the memory range. |
| 128 | * @end: End of the memory range (inclusive). | 150 | * @end: End of the memory range (inclusive). |
| 129 | * @type: Type of the memory range. | 151 | * @type: Type of the memory range. |
| 130 | * | 152 | * |
| 131 | * This function uses kmalloc() for memory | 153 | * Adds a firmware mapping entry. This function is for memory hotplug, it is |
| 132 | * allocation. Use firmware_map_add_early() if you want to use the bootmem | 154 | * similar to function firmware_map_add_early(). The only difference is that |
| 133 | * allocator. | 155 | * it will create the syfs entry dynamically. |
| 134 | * | ||
| 135 | * That function must be called before late_initcall. | ||
| 136 | * | 156 | * |
| 137 | * Returns 0 on success, or -ENOMEM if no memory could be allocated. | 157 | * Returns 0 on success, or -ENOMEM if no memory could be allocated. |
| 138 | **/ | 158 | **/ |
| 139 | int firmware_map_add(u64 start, u64 end, const char *type) | 159 | int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type) |
| 140 | { | 160 | { |
| 141 | struct firmware_map_entry *entry; | 161 | struct firmware_map_entry *entry; |
| 142 | 162 | ||
| 143 | entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC); | 163 | entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC); |
| 144 | if (!entry) | 164 | if (!entry) |
| 145 | return -ENOMEM; | 165 | return -ENOMEM; |
| 146 | 166 | ||
| 147 | return firmware_map_add_entry(start, end, type, entry); | 167 | firmware_map_add_entry(start, end, type, entry); |
| 168 | /* create the memmap entry */ | ||
| 169 | add_sysfs_fw_map_entry(entry); | ||
| 170 | |||
| 171 | return 0; | ||
| 148 | } | 172 | } |
| 149 | 173 | ||
| 150 | /** | 174 | /** |
| @@ -154,7 +178,7 @@ int firmware_map_add(u64 start, u64 end, const char *type) | |||
| 154 | * @type: Type of the memory range. | 178 | * @type: Type of the memory range. |
| 155 | * | 179 | * |
| 156 | * Adds a firmware mapping entry. This function uses the bootmem allocator | 180 | * Adds a firmware mapping entry. This function uses the bootmem allocator |
| 157 | * for memory allocation. Use firmware_map_add() if you want to use kmalloc(). | 181 | * for memory allocation. |
| 158 | * | 182 | * |
| 159 | * That function must be called before late_initcall. | 183 | * That function must be called before late_initcall. |
| 160 | * | 184 | * |
| @@ -214,19 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj, | |||
| 214 | */ | 238 | */ |
| 215 | static int __init memmap_init(void) | 239 | static int __init memmap_init(void) |
| 216 | { | 240 | { |
| 217 | int i = 0; | ||
| 218 | struct firmware_map_entry *entry; | 241 | struct firmware_map_entry *entry; |
| 219 | struct kset *memmap_kset; | ||
| 220 | |||
| 221 | memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj); | ||
| 222 | if (WARN_ON(!memmap_kset)) | ||
| 223 | return -ENOMEM; | ||
| 224 | 242 | ||
| 225 | list_for_each_entry(entry, &map_entries, list) { | 243 | list_for_each_entry(entry, &map_entries, list) |
| 226 | entry->kobj.kset = memmap_kset; | 244 | add_sysfs_fw_map_entry(entry); |
| 227 | if (kobject_add(&entry->kobj, NULL, "%d", i++)) | ||
| 228 | kobject_put(&entry->kobj); | ||
| 229 | } | ||
| 230 | 245 | ||
| 231 | return 0; | 246 | return 0; |
| 232 | } | 247 | } |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 1f1d88ae68d6..a4cdbd51b1c6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -65,8 +65,17 @@ config GPIO_SYSFS | |||
| 65 | 65 | ||
| 66 | # put expanders in the right section, in alphabetical order | 66 | # put expanders in the right section, in alphabetical order |
| 67 | 67 | ||
| 68 | config GPIO_MAX730X | ||
| 69 | tristate | ||
| 70 | |||
| 68 | comment "Memory mapped GPIO expanders:" | 71 | comment "Memory mapped GPIO expanders:" |
| 69 | 72 | ||
| 73 | config GPIO_IT8761E | ||
| 74 | tristate "IT8761E GPIO support" | ||
| 75 | depends on GPIOLIB | ||
| 76 | help | ||
| 77 | Say yes here to support GPIO functionality of IT8761E super I/O chip. | ||
| 78 | |||
| 70 | config GPIO_PL061 | 79 | config GPIO_PL061 |
| 71 | bool "PrimeCell PL061 GPIO support" | 80 | bool "PrimeCell PL061 GPIO support" |
| 72 | depends on ARM_AMBA | 81 | depends on ARM_AMBA |
| @@ -87,6 +96,13 @@ config GPIO_VR41XX | |||
| 87 | 96 | ||
| 88 | comment "I2C GPIO expanders:" | 97 | comment "I2C GPIO expanders:" |
| 89 | 98 | ||
| 99 | config GPIO_MAX7300 | ||
| 100 | tristate "Maxim MAX7300 GPIO expander" | ||
| 101 | depends on I2C | ||
| 102 | select GPIO_MAX730X | ||
| 103 | help | ||
| 104 | GPIO driver for Maxim MAX7301 I2C-based GPIO expander. | ||
| 105 | |||
| 90 | config GPIO_MAX732X | 106 | config GPIO_MAX732X |
| 91 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" | 107 | tristate "MAX7319, MAX7320-7327 I2C Port Expanders" |
| 92 | depends on I2C | 108 | depends on I2C |
| @@ -124,6 +140,13 @@ config GPIO_PCA953X | |||
| 124 | This driver can also be built as a module. If so, the module | 140 | This driver can also be built as a module. If so, the module |
| 125 | will be called pca953x. | 141 | will be called pca953x. |
| 126 | 142 | ||
| 143 | config GPIO_PCA953X_IRQ | ||
| 144 | bool "Interrupt controller support for PCA953x" | ||
| 145 | depends on GPIO_PCA953X=y | ||
| 146 | help | ||
| 147 | Say yes here to enable the pca953x to be used as an interrupt | ||
| 148 | controller. It requires the driver to be built in the kernel. | ||
| 149 | |||
| 127 | config GPIO_PCF857X | 150 | config GPIO_PCF857X |
| 128 | tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" | 151 | tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders" |
| 129 | depends on I2C | 152 | depends on I2C |
| @@ -226,8 +249,9 @@ comment "SPI GPIO expanders:" | |||
| 226 | config GPIO_MAX7301 | 249 | config GPIO_MAX7301 |
| 227 | tristate "Maxim MAX7301 GPIO expander" | 250 | tristate "Maxim MAX7301 GPIO expander" |
| 228 | depends on SPI_MASTER | 251 | depends on SPI_MASTER |
| 252 | select GPIO_MAX730X | ||
| 229 | help | 253 | help |
| 230 | gpio driver for Maxim MAX7301 SPI GPIO expander. | 254 | GPIO driver for Maxim MAX7301 SPI-based GPIO expander. |
| 231 | 255 | ||
| 232 | config GPIO_MCP23S08 | 256 | config GPIO_MCP23S08 |
| 233 | tristate "Microchip MCP23S08 I/O expander" | 257 | tristate "Microchip MCP23S08 I/O expander" |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 48687238edb1..128abf8a98da 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -7,6 +7,8 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o | |||
| 7 | obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o | 7 | obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o |
| 8 | obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o | 8 | obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o |
| 9 | obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o | 9 | obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o |
| 10 | obj-$(CONFIG_GPIO_MAX730X) += max730x.o | ||
| 11 | obj-$(CONFIG_GPIO_MAX7300) += max7300.o | ||
| 10 | obj-$(CONFIG_GPIO_MAX7301) += max7301.o | 12 | obj-$(CONFIG_GPIO_MAX7301) += max7301.o |
| 11 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o | 13 | obj-$(CONFIG_GPIO_MAX732X) += max732x.o |
| 12 | obj-$(CONFIG_GPIO_MC33880) += mc33880.o | 14 | obj-$(CONFIG_GPIO_MC33880) += mc33880.o |
| @@ -20,5 +22,6 @@ obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o | |||
| 20 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o | 22 | obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o |
| 21 | obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o | 23 | obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o |
| 22 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o | 24 | obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o |
| 25 | obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o | ||
| 23 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | 26 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o |
| 24 | obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o | 27 | obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o |
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 0fdbe94f24a3..0c3c498f2260 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c | |||
| @@ -154,7 +154,7 @@ static int chip_gpio_request(struct gpio_chip *c, unsigned offset) | |||
| 154 | 154 | ||
| 155 | static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) | 155 | static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) |
| 156 | { | 156 | { |
| 157 | return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL); | 157 | return cs5535_gpio_isset(offset, GPIO_READ_BACK); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | 160 | static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val) |
| @@ -172,6 +172,7 @@ static int chip_direction_input(struct gpio_chip *c, unsigned offset) | |||
| 172 | 172 | ||
| 173 | spin_lock_irqsave(&chip->lock, flags); | 173 | spin_lock_irqsave(&chip->lock, flags); |
| 174 | __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); | 174 | __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); |
| 175 | __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE); | ||
| 175 | spin_unlock_irqrestore(&chip->lock, flags); | 176 | spin_unlock_irqrestore(&chip->lock, flags); |
| 176 | 177 | ||
| 177 | return 0; | 178 | return 0; |
| @@ -184,6 +185,7 @@ static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) | |||
| 184 | 185 | ||
| 185 | spin_lock_irqsave(&chip->lock, flags); | 186 | spin_lock_irqsave(&chip->lock, flags); |
| 186 | 187 | ||
| 188 | __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); | ||
| 187 | __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE); | 189 | __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE); |
| 188 | if (val) | 190 | if (val) |
| 189 | __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL); | 191 | __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL); |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 350842ad3632..9006fdb26fea 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -1237,6 +1237,64 @@ void gpio_free(unsigned gpio) | |||
| 1237 | } | 1237 | } |
| 1238 | EXPORT_SYMBOL_GPL(gpio_free); | 1238 | EXPORT_SYMBOL_GPL(gpio_free); |
| 1239 | 1239 | ||
| 1240 | /** | ||
| 1241 | * gpio_request_one - request a single GPIO with initial configuration | ||
| 1242 | * @gpio: the GPIO number | ||
| 1243 | * @flags: GPIO configuration as specified by GPIOF_* | ||
| 1244 | * @label: a literal description string of this GPIO | ||
| 1245 | */ | ||
| 1246 | int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) | ||
| 1247 | { | ||
| 1248 | int err; | ||
| 1249 | |||
| 1250 | err = gpio_request(gpio, label); | ||
| 1251 | if (err) | ||
| 1252 | return err; | ||
| 1253 | |||
| 1254 | if (flags & GPIOF_DIR_IN) | ||
| 1255 | err = gpio_direction_input(gpio); | ||
| 1256 | else | ||
| 1257 | err = gpio_direction_output(gpio, | ||
| 1258 | (flags & GPIOF_INIT_HIGH) ? 1 : 0); | ||
| 1259 | |||
| 1260 | return err; | ||
| 1261 | } | ||
| 1262 | EXPORT_SYMBOL_GPL(gpio_request_one); | ||
| 1263 | |||
| 1264 | /** | ||
| 1265 | * gpio_request_array - request multiple GPIOs in a single call | ||
| 1266 | * @array: array of the 'struct gpio' | ||
| 1267 | * @num: how many GPIOs in the array | ||
| 1268 | */ | ||
| 1269 | int gpio_request_array(struct gpio *array, size_t num) | ||
| 1270 | { | ||
| 1271 | int i, err; | ||
| 1272 | |||
| 1273 | for (i = 0; i < num; i++, array++) { | ||
| 1274 | err = gpio_request_one(array->gpio, array->flags, array->label); | ||
| 1275 | if (err) | ||
| 1276 | goto err_free; | ||
| 1277 | } | ||
| 1278 | return 0; | ||
| 1279 | |||
| 1280 | err_free: | ||
| 1281 | while (i--) | ||
| 1282 | gpio_free((--array)->gpio); | ||
| 1283 | return err; | ||
| 1284 | } | ||
| 1285 | EXPORT_SYMBOL_GPL(gpio_request_array); | ||
| 1286 | |||
| 1287 | /** | ||
| 1288 | * gpio_free_array - release multiple GPIOs in a single call | ||
| 1289 | * @array: array of the 'struct gpio' | ||
| 1290 | * @num: how many GPIOs in the array | ||
| 1291 | */ | ||
| 1292 | void gpio_free_array(struct gpio *array, size_t num) | ||
| 1293 | { | ||
| 1294 | while (num--) | ||
| 1295 | gpio_free((array++)->gpio); | ||
| 1296 | } | ||
| 1297 | EXPORT_SYMBOL_GPL(gpio_free_array); | ||
| 1240 | 1298 | ||
| 1241 | /** | 1299 | /** |
| 1242 | * gpiochip_is_requested - return string iff signal was requested | 1300 | * gpiochip_is_requested - return string iff signal was requested |
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c new file mode 100644 index 000000000000..753219cf993a --- /dev/null +++ b/drivers/gpio/it8761e_gpio.c | |||
| @@ -0,0 +1,231 @@ | |||
| 1 | /* | ||
| 2 | * it8761_gpio.c - GPIO interface for IT8761E Super I/O chip | ||
| 3 | * | ||
| 4 | * Author: Denis Turischev <denis@compulab.co.il> | ||
| 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 2 as published | ||
| 8 | * by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; see the file COPYING. If not, write to | ||
| 17 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/io.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | #include <linux/ioport.h> | ||
| 26 | |||
| 27 | #include <linux/gpio.h> | ||
| 28 | |||
| 29 | #define SIO_CHIP_ID 0x8761 | ||
| 30 | #define CHIP_ID_HIGH_BYTE 0x20 | ||
| 31 | #define CHIP_ID_LOW_BYTE 0x21 | ||
| 32 | |||
| 33 | static u8 ports[2] = { 0x2e, 0x4e }; | ||
| 34 | static u8 port; | ||
| 35 | |||
| 36 | static DEFINE_SPINLOCK(sio_lock); | ||
| 37 | |||
| 38 | #define GPIO_NAME "it8761-gpio" | ||
| 39 | #define GPIO_BA_HIGH_BYTE 0x60 | ||
| 40 | #define GPIO_BA_LOW_BYTE 0x61 | ||
| 41 | #define GPIO_IOSIZE 4 | ||
| 42 | #define GPIO1X_IO 0xf0 | ||
| 43 | #define GPIO2X_IO 0xf1 | ||
| 44 | |||
| 45 | static u16 gpio_ba; | ||
| 46 | |||
| 47 | static u8 read_reg(u8 addr, u8 port) | ||
| 48 | { | ||
| 49 | outb(addr, port); | ||
| 50 | return inb(port + 1); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void write_reg(u8 data, u8 addr, u8 port) | ||
| 54 | { | ||
| 55 | outb(addr, port); | ||
| 56 | outb(data, port + 1); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void enter_conf_mode(u8 port) | ||
| 60 | { | ||
| 61 | outb(0x87, port); | ||
| 62 | outb(0x61, port); | ||
| 63 | outb(0x55, port); | ||
| 64 | outb((port == 0x2e) ? 0x55 : 0xaa, port); | ||
| 65 | } | ||
| 66 | |||
| 67 | static void exit_conf_mode(u8 port) | ||
| 68 | { | ||
| 69 | outb(0x2, port); | ||
| 70 | outb(0x2, port + 1); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void enter_gpio_mode(u8 port) | ||
| 74 | { | ||
| 75 | write_reg(0x2, 0x7, port); | ||
| 76 | } | ||
| 77 | |||
| 78 | static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) | ||
| 79 | { | ||
| 80 | u16 reg; | ||
| 81 | u8 bit; | ||
| 82 | |||
| 83 | bit = gpio_num % 7; | ||
| 84 | reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; | ||
| 85 | |||
| 86 | return !!(inb(reg) & (1 << bit)); | ||
| 87 | } | ||
| 88 | |||
| 89 | static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) | ||
| 90 | { | ||
| 91 | u8 curr_dirs; | ||
| 92 | u8 io_reg, bit; | ||
| 93 | |||
| 94 | bit = gpio_num % 7; | ||
| 95 | io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; | ||
| 96 | |||
| 97 | spin_lock(&sio_lock); | ||
| 98 | |||
| 99 | enter_conf_mode(port); | ||
| 100 | enter_gpio_mode(port); | ||
| 101 | |||
| 102 | curr_dirs = read_reg(io_reg, port); | ||
| 103 | |||
| 104 | if (curr_dirs & (1 << bit)) | ||
| 105 | write_reg(curr_dirs & ~(1 << bit), io_reg, port); | ||
| 106 | |||
| 107 | exit_conf_mode(port); | ||
| 108 | |||
| 109 | spin_unlock(&sio_lock); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 113 | static void it8761e_gpio_set(struct gpio_chip *gc, | ||
| 114 | unsigned gpio_num, int val) | ||
| 115 | { | ||
| 116 | u8 curr_vals, bit; | ||
| 117 | u16 reg; | ||
| 118 | |||
| 119 | bit = gpio_num % 7; | ||
| 120 | reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; | ||
| 121 | |||
| 122 | spin_lock(&sio_lock); | ||
| 123 | |||
| 124 | curr_vals = inb(reg); | ||
| 125 | if (val) | ||
| 126 | outb(curr_vals | (1 << bit) , reg); | ||
| 127 | else | ||
| 128 | outb(curr_vals & ~(1 << bit), reg); | ||
| 129 | |||
| 130 | spin_unlock(&sio_lock); | ||
| 131 | } | ||
| 132 | |||
| 133 | static int it8761e_gpio_direction_out(struct gpio_chip *gc, | ||
| 134 | unsigned gpio_num, int val) | ||
| 135 | { | ||
| 136 | u8 curr_dirs, io_reg, bit; | ||
| 137 | |||
| 138 | bit = gpio_num % 7; | ||
| 139 | io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; | ||
| 140 | |||
| 141 | it8761e_gpio_set(gc, gpio_num, val); | ||
| 142 | |||
| 143 | spin_lock(&sio_lock); | ||
| 144 | |||
| 145 | enter_conf_mode(port); | ||
| 146 | enter_gpio_mode(port); | ||
| 147 | |||
| 148 | curr_dirs = read_reg(io_reg, port); | ||
| 149 | |||
| 150 | if (!(curr_dirs & (1 << bit))) | ||
| 151 | write_reg(curr_dirs | (1 << bit), io_reg, port); | ||
| 152 | |||
| 153 | exit_conf_mode(port); | ||
| 154 | |||
| 155 | spin_unlock(&sio_lock); | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static struct gpio_chip it8761e_gpio_chip = { | ||
| 160 | .label = GPIO_NAME, | ||
| 161 | .owner = THIS_MODULE, | ||
| 162 | .get = it8761e_gpio_get, | ||
| 163 | .direction_input = it8761e_gpio_direction_in, | ||
| 164 | .set = it8761e_gpio_set, | ||
| 165 | .direction_output = it8761e_gpio_direction_out, | ||
| 166 | }; | ||
| 167 | |||
| 168 | static int __init it8761e_gpio_init(void) | ||
| 169 | { | ||
| 170 | int i, id, err; | ||
| 171 | |||
| 172 | /* chip and port detection */ | ||
| 173 | for (i = 0; i < ARRAY_SIZE(ports); i++) { | ||
| 174 | spin_lock(&sio_lock); | ||
| 175 | enter_conf_mode(ports[i]); | ||
| 176 | |||
| 177 | id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) + | ||
| 178 | read_reg(CHIP_ID_LOW_BYTE, ports[i]); | ||
| 179 | |||
| 180 | exit_conf_mode(ports[i]); | ||
| 181 | spin_unlock(&sio_lock); | ||
| 182 | |||
| 183 | if (id == SIO_CHIP_ID) { | ||
| 184 | port = ports[i]; | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | if (!port) | ||
| 190 | return -ENODEV; | ||
| 191 | |||
| 192 | /* fetch GPIO base address */ | ||
| 193 | enter_conf_mode(port); | ||
| 194 | enter_gpio_mode(port); | ||
| 195 | gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) + | ||
| 196 | read_reg(GPIO_BA_LOW_BYTE, port); | ||
| 197 | exit_conf_mode(port); | ||
| 198 | |||
| 199 | if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME)) | ||
| 200 | return -EBUSY; | ||
| 201 | |||
| 202 | it8761e_gpio_chip.base = -1; | ||
| 203 | it8761e_gpio_chip.ngpio = 14; | ||
| 204 | |||
| 205 | err = gpiochip_add(&it8761e_gpio_chip); | ||
| 206 | if (err < 0) | ||
| 207 | goto gpiochip_add_err; | ||
| 208 | |||
| 209 | return 0; | ||
| 210 | |||
| 211 | gpiochip_add_err: | ||
| 212 | release_region(gpio_ba, GPIO_IOSIZE); | ||
| 213 | gpio_ba = 0; | ||
| 214 | return err; | ||
| 215 | } | ||
| 216 | |||
| 217 | static void __exit it8761e_gpio_exit(void) | ||
| 218 | { | ||
| 219 | if (gpio_ba) { | ||
| 220 | gpiochip_remove(&it8761e_gpio_chip); | ||
| 221 | |||
| 222 | release_region(gpio_ba, GPIO_IOSIZE); | ||
| 223 | gpio_ba = 0; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | module_init(it8761e_gpio_init); | ||
| 227 | module_exit(it8761e_gpio_exit); | ||
| 228 | |||
| 229 | MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>"); | ||
| 230 | MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip"); | ||
| 231 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/max7300.c b/drivers/gpio/max7300.c new file mode 100644 index 000000000000..9d74eef1157a --- /dev/null +++ b/drivers/gpio/max7300.c | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | /* | ||
| 2 | * drivers/gpio/max7300.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Wolfram Sang, Pengutronix | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Check max730x.c for further details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/spi/max7301.h> | ||
| 19 | |||
| 20 | static int max7300_i2c_write(struct device *dev, unsigned int reg, | ||
| 21 | unsigned int val) | ||
| 22 | { | ||
| 23 | struct i2c_client *client = to_i2c_client(dev); | ||
| 24 | |||
| 25 | return i2c_smbus_write_byte_data(client, reg, val); | ||
| 26 | } | ||
| 27 | |||
| 28 | static int max7300_i2c_read(struct device *dev, unsigned int reg) | ||
| 29 | { | ||
| 30 | struct i2c_client *client = to_i2c_client(dev); | ||
| 31 | |||
| 32 | return i2c_smbus_read_byte_data(client, reg); | ||
| 33 | } | ||
| 34 | |||
| 35 | static int __devinit max7300_probe(struct i2c_client *client, | ||
| 36 | const struct i2c_device_id *id) | ||
| 37 | { | ||
| 38 | struct max7301 *ts; | ||
| 39 | int ret; | ||
| 40 | |||
| 41 | if (!i2c_check_functionality(client->adapter, | ||
| 42 | I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 43 | return -EIO; | ||
| 44 | |||
| 45 | ts = kzalloc(sizeof(struct max7301), GFP_KERNEL); | ||
| 46 | if (!ts) | ||
| 47 | return -ENOMEM; | ||
| 48 | |||
| 49 | ts->read = max7300_i2c_read; | ||
| 50 | ts->write = max7300_i2c_write; | ||
| 51 | ts->dev = &client->dev; | ||
| 52 | |||
| 53 | ret = __max730x_probe(ts); | ||
| 54 | if (ret) | ||
| 55 | kfree(ts); | ||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int __devexit max7300_remove(struct i2c_client *client) | ||
| 60 | { | ||
| 61 | return __max730x_remove(&client->dev); | ||
| 62 | } | ||
| 63 | |||
| 64 | static const struct i2c_device_id max7300_id[] = { | ||
| 65 | { "max7300", 0 }, | ||
| 66 | { } | ||
| 67 | }; | ||
| 68 | MODULE_DEVICE_TABLE(i2c, max7300_id); | ||
| 69 | |||
| 70 | static struct i2c_driver max7300_driver = { | ||
| 71 | .driver = { | ||
| 72 | .name = "max7300", | ||
| 73 | .owner = THIS_MODULE, | ||
| 74 | }, | ||
| 75 | .probe = max7300_probe, | ||
| 76 | .remove = __devexit_p(max7300_remove), | ||
| 77 | .id_table = max7300_id, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static int __init max7300_init(void) | ||
| 81 | { | ||
| 82 | return i2c_add_driver(&max7300_driver); | ||
| 83 | } | ||
| 84 | subsys_initcall(max7300_init); | ||
| 85 | |||
| 86 | static void __exit max7300_exit(void) | ||
| 87 | { | ||
| 88 | i2c_del_driver(&max7300_driver); | ||
| 89 | } | ||
| 90 | module_exit(max7300_exit); | ||
| 91 | |||
| 92 | MODULE_AUTHOR("Wolfram Sang"); | ||
| 93 | MODULE_LICENSE("GPL v2"); | ||
| 94 | MODULE_DESCRIPTION("MAX7300 GPIO-Expander"); | ||
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c index 480956f1ca50..965d9b1ea13e 100644 --- a/drivers/gpio/max7301.c +++ b/drivers/gpio/max7301.c | |||
| @@ -1,98 +1,41 @@ | |||
| 1 | /** | 1 | /* |
| 2 | * drivers/gpio/max7301.c | 2 | * drivers/gpio/max7301.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2006 Juergen Beisert, Pengutronix | 4 | * Copyright (C) 2006 Juergen Beisert, Pengutronix |
| 5 | * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix | 5 | * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix |
| 6 | * Copyright (C) 2009 Wolfram Sang, Pengutronix | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * 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 | * it under the terms of the GNU General Public License version 2 as |
| 9 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
| 10 | * | 11 | * |
| 11 | * The Maxim's MAX7301 device is an SPI driven GPIO expander. There are | 12 | * Check max730x.c for further details. |
| 12 | * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more | ||
| 13 | * details | ||
| 14 | * Note: | ||
| 15 | * - DIN must be stable at the rising edge of clock. | ||
| 16 | * - when writing: | ||
| 17 | * - always clock in 16 clocks at once | ||
| 18 | * - at DIN: D15 first, D0 last | ||
| 19 | * - D0..D7 = databyte, D8..D14 = commandbyte | ||
| 20 | * - D15 = low -> write command | ||
| 21 | * - when reading | ||
| 22 | * - always clock in 16 clocks at once | ||
| 23 | * - at DIN: D15 first, D0 last | ||
| 24 | * - D0..D7 = dummy, D8..D14 = register address | ||
| 25 | * - D15 = high -> read command | ||
| 26 | * - raise CS and assert it again | ||
| 27 | * - always clock in 16 clocks at once | ||
| 28 | * - at DOUT: D15 first, D0 last | ||
| 29 | * - D0..D7 contains the data from the first cycle | ||
| 30 | * | ||
| 31 | * The driver exports a standard gpiochip interface | ||
| 32 | */ | 13 | */ |
| 33 | 14 | ||
| 15 | #include <linux/module.h> | ||
| 34 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 35 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 36 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
| 37 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
| 38 | #include <linux/spi/max7301.h> | 20 | #include <linux/spi/max7301.h> |
| 39 | #include <linux/gpio.h> | ||
| 40 | |||
| 41 | #define DRIVER_NAME "max7301" | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Pin configurations, see MAX7301 datasheet page 6 | ||
| 45 | */ | ||
| 46 | #define PIN_CONFIG_MASK 0x03 | ||
| 47 | #define PIN_CONFIG_IN_PULLUP 0x03 | ||
| 48 | #define PIN_CONFIG_IN_WO_PULLUP 0x02 | ||
| 49 | #define PIN_CONFIG_OUT 0x01 | ||
| 50 | |||
| 51 | #define PIN_NUMBER 28 | ||
| 52 | |||
| 53 | |||
| 54 | /* | ||
| 55 | * Some registers must be read back to modify. | ||
| 56 | * To save time we cache them here in memory | ||
| 57 | */ | ||
| 58 | struct max7301 { | ||
| 59 | struct mutex lock; | ||
| 60 | u8 port_config[8]; /* field 0 is unused */ | ||
| 61 | u32 out_level; /* cached output levels */ | ||
| 62 | struct gpio_chip chip; | ||
| 63 | struct spi_device *spi; | ||
| 64 | }; | ||
| 65 | 21 | ||
| 66 | /** | 22 | /* A write to the MAX7301 means one message with one transfer */ |
| 67 | * max7301_write - Write a new register content | 23 | static int max7301_spi_write(struct device *dev, unsigned int reg, |
| 68 | * @spi: The SPI device | 24 | unsigned int val) |
| 69 | * @reg: Register offset | ||
| 70 | * @val: Value to write | ||
| 71 | * | ||
| 72 | * A write to the MAX7301 means one message with one transfer | ||
| 73 | * | ||
| 74 | * Returns 0 if successful or a negative value on error | ||
| 75 | */ | ||
| 76 | static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val) | ||
| 77 | { | 25 | { |
| 26 | struct spi_device *spi = to_spi_device(dev); | ||
| 78 | u16 word = ((reg & 0x7F) << 8) | (val & 0xFF); | 27 | u16 word = ((reg & 0x7F) << 8) | (val & 0xFF); |
| 28 | |||
| 79 | return spi_write(spi, (const u8 *)&word, sizeof(word)); | 29 | return spi_write(spi, (const u8 *)&word, sizeof(word)); |
| 80 | } | 30 | } |
| 81 | 31 | ||
| 82 | /** | 32 | /* A read from the MAX7301 means two transfers; here, one message each */ |
| 83 | * max7301_read - Read back register content | 33 | |
| 84 | * @spi: The SPI device | 34 | static int max7301_spi_read(struct device *dev, unsigned int reg) |
| 85 | * @reg: Register offset | ||
| 86 | * | ||
| 87 | * A read from the MAX7301 means two transfers; here, one message each | ||
| 88 | * | ||
| 89 | * Returns positive 8 bit value from device if successful or a | ||
| 90 | * negative value on error | ||
| 91 | */ | ||
| 92 | static int max7301_read(struct spi_device *spi, unsigned int reg) | ||
| 93 | { | 35 | { |
| 94 | int ret; | 36 | int ret; |
| 95 | u16 word; | 37 | u16 word; |
| 38 | struct spi_device *spi = to_spi_device(dev); | ||
| 96 | 39 | ||
| 97 | word = 0x8000 | (reg << 8); | 40 | word = 0x8000 | (reg << 8); |
| 98 | ret = spi_write(spi, (const u8 *)&word, sizeof(word)); | 41 | ret = spi_write(spi, (const u8 *)&word, sizeof(word)); |
| @@ -108,125 +51,13 @@ static int max7301_read(struct spi_device *spi, unsigned int reg) | |||
| 108 | return word & 0xff; | 51 | return word & 0xff; |
| 109 | } | 52 | } |
| 110 | 53 | ||
| 111 | static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) | ||
| 112 | { | ||
| 113 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 114 | u8 *config; | ||
| 115 | int ret; | ||
| 116 | |||
| 117 | /* First 4 pins are unused in the controller */ | ||
| 118 | offset += 4; | ||
| 119 | |||
| 120 | config = &ts->port_config[offset >> 2]; | ||
| 121 | |||
| 122 | mutex_lock(&ts->lock); | ||
| 123 | |||
| 124 | /* Standard GPIO API doesn't support pull-ups, has to be extended. | ||
| 125 | * Hard-coding no pollup for now. */ | ||
| 126 | *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3)); | ||
| 127 | |||
| 128 | ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config); | ||
| 129 | |||
| 130 | mutex_unlock(&ts->lock); | ||
| 131 | |||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int __max7301_set(struct max7301 *ts, unsigned offset, int value) | ||
| 136 | { | ||
| 137 | if (value) { | ||
| 138 | ts->out_level |= 1 << offset; | ||
| 139 | return max7301_write(ts->spi, 0x20 + offset, 0x01); | ||
| 140 | } else { | ||
| 141 | ts->out_level &= ~(1 << offset); | ||
| 142 | return max7301_write(ts->spi, 0x20 + offset, 0x00); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | static int max7301_direction_output(struct gpio_chip *chip, unsigned offset, | ||
| 147 | int value) | ||
| 148 | { | ||
| 149 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 150 | u8 *config; | ||
| 151 | int ret; | ||
| 152 | |||
| 153 | /* First 4 pins are unused in the controller */ | ||
| 154 | offset += 4; | ||
| 155 | |||
| 156 | config = &ts->port_config[offset >> 2]; | ||
| 157 | |||
| 158 | mutex_lock(&ts->lock); | ||
| 159 | |||
| 160 | *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3)); | ||
| 161 | |||
| 162 | ret = __max7301_set(ts, offset, value); | ||
| 163 | |||
| 164 | if (!ret) | ||
| 165 | ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config); | ||
| 166 | |||
| 167 | mutex_unlock(&ts->lock); | ||
| 168 | |||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int max7301_get(struct gpio_chip *chip, unsigned offset) | ||
| 173 | { | ||
| 174 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 175 | int config, level = -EINVAL; | ||
| 176 | |||
| 177 | /* First 4 pins are unused in the controller */ | ||
| 178 | offset += 4; | ||
| 179 | |||
| 180 | mutex_lock(&ts->lock); | ||
| 181 | |||
| 182 | config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3; | ||
| 183 | |||
| 184 | switch (config) { | ||
| 185 | case 1: | ||
| 186 | /* Output: return cached level */ | ||
| 187 | level = !!(ts->out_level & (1 << offset)); | ||
| 188 | break; | ||
| 189 | case 2: | ||
| 190 | case 3: | ||
| 191 | /* Input: read out */ | ||
| 192 | level = max7301_read(ts->spi, 0x20 + offset) & 0x01; | ||
| 193 | } | ||
| 194 | mutex_unlock(&ts->lock); | ||
| 195 | |||
| 196 | return level; | ||
| 197 | } | ||
| 198 | |||
| 199 | static void max7301_set(struct gpio_chip *chip, unsigned offset, int value) | ||
| 200 | { | ||
| 201 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 202 | |||
| 203 | /* First 4 pins are unused in the controller */ | ||
| 204 | offset += 4; | ||
| 205 | |||
| 206 | mutex_lock(&ts->lock); | ||
| 207 | |||
| 208 | __max7301_set(ts, offset, value); | ||
| 209 | |||
| 210 | mutex_unlock(&ts->lock); | ||
| 211 | } | ||
| 212 | |||
| 213 | static int __devinit max7301_probe(struct spi_device *spi) | 54 | static int __devinit max7301_probe(struct spi_device *spi) |
| 214 | { | 55 | { |
| 215 | struct max7301 *ts; | 56 | struct max7301 *ts; |
| 216 | struct max7301_platform_data *pdata; | 57 | int ret; |
| 217 | int i, ret; | ||
| 218 | |||
| 219 | pdata = spi->dev.platform_data; | ||
| 220 | if (!pdata || !pdata->base) { | ||
| 221 | dev_dbg(&spi->dev, "incorrect or missing platform data\n"); | ||
| 222 | return -EINVAL; | ||
| 223 | } | ||
| 224 | 58 | ||
| 225 | /* | 59 | /* bits_per_word cannot be configured in platform data */ |
| 226 | * bits_per_word cannot be configured in platform data | ||
| 227 | */ | ||
| 228 | spi->bits_per_word = 16; | 60 | spi->bits_per_word = 16; |
| 229 | |||
| 230 | ret = spi_setup(spi); | 61 | ret = spi_setup(spi); |
| 231 | if (ret < 0) | 62 | if (ret < 0) |
| 232 | return ret; | 63 | return ret; |
| @@ -235,90 +66,35 @@ static int __devinit max7301_probe(struct spi_device *spi) | |||
| 235 | if (!ts) | 66 | if (!ts) |
| 236 | return -ENOMEM; | 67 | return -ENOMEM; |
| 237 | 68 | ||
| 238 | mutex_init(&ts->lock); | 69 | ts->read = max7301_spi_read; |
| 239 | 70 | ts->write = max7301_spi_write; | |
| 240 | dev_set_drvdata(&spi->dev, ts); | 71 | ts->dev = &spi->dev; |
| 241 | 72 | ||
| 242 | /* Power up the chip and disable IRQ output */ | 73 | ret = __max730x_probe(ts); |
| 243 | max7301_write(spi, 0x04, 0x01); | ||
| 244 | |||
| 245 | ts->spi = spi; | ||
| 246 | |||
| 247 | ts->chip.label = DRIVER_NAME, | ||
| 248 | |||
| 249 | ts->chip.direction_input = max7301_direction_input; | ||
| 250 | ts->chip.get = max7301_get; | ||
| 251 | ts->chip.direction_output = max7301_direction_output; | ||
| 252 | ts->chip.set = max7301_set; | ||
| 253 | |||
| 254 | ts->chip.base = pdata->base; | ||
| 255 | ts->chip.ngpio = PIN_NUMBER; | ||
| 256 | ts->chip.can_sleep = 1; | ||
| 257 | ts->chip.dev = &spi->dev; | ||
| 258 | ts->chip.owner = THIS_MODULE; | ||
| 259 | |||
| 260 | /* | ||
| 261 | * tristate all pins in hardware and cache the | ||
| 262 | * register values for later use. | ||
| 263 | */ | ||
| 264 | for (i = 1; i < 8; i++) { | ||
| 265 | int j; | ||
| 266 | /* 0xAA means input with internal pullup disabled */ | ||
| 267 | max7301_write(spi, 0x08 + i, 0xAA); | ||
| 268 | ts->port_config[i] = 0xAA; | ||
| 269 | for (j = 0; j < 4; j++) { | ||
| 270 | int offset = (i - 1) * 4 + j; | ||
| 271 | ret = max7301_direction_input(&ts->chip, offset); | ||
| 272 | if (ret) | ||
| 273 | goto exit_destroy; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | ret = gpiochip_add(&ts->chip); | ||
| 278 | if (ret) | 74 | if (ret) |
| 279 | goto exit_destroy; | 75 | kfree(ts); |
| 280 | |||
| 281 | return ret; | ||
| 282 | |||
| 283 | exit_destroy: | ||
| 284 | dev_set_drvdata(&spi->dev, NULL); | ||
| 285 | mutex_destroy(&ts->lock); | ||
| 286 | kfree(ts); | ||
| 287 | return ret; | 76 | return ret; |
| 288 | } | 77 | } |
| 289 | 78 | ||
| 290 | static int __devexit max7301_remove(struct spi_device *spi) | 79 | static int __devexit max7301_remove(struct spi_device *spi) |
| 291 | { | 80 | { |
| 292 | struct max7301 *ts; | 81 | return __max730x_remove(&spi->dev); |
| 293 | int ret; | ||
| 294 | |||
| 295 | ts = dev_get_drvdata(&spi->dev); | ||
| 296 | if (ts == NULL) | ||
| 297 | return -ENODEV; | ||
| 298 | |||
| 299 | dev_set_drvdata(&spi->dev, NULL); | ||
| 300 | |||
| 301 | /* Power down the chip and disable IRQ output */ | ||
| 302 | max7301_write(spi, 0x04, 0x00); | ||
| 303 | |||
| 304 | ret = gpiochip_remove(&ts->chip); | ||
| 305 | if (!ret) { | ||
| 306 | mutex_destroy(&ts->lock); | ||
| 307 | kfree(ts); | ||
| 308 | } else | ||
| 309 | dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", | ||
| 310 | ret); | ||
| 311 | |||
| 312 | return ret; | ||
| 313 | } | 82 | } |
| 314 | 83 | ||
| 84 | static const struct spi_device_id max7301_id[] = { | ||
| 85 | { "max7301", 0 }, | ||
| 86 | { } | ||
| 87 | }; | ||
| 88 | MODULE_DEVICE_TABLE(spi, max7301_id); | ||
| 89 | |||
| 315 | static struct spi_driver max7301_driver = { | 90 | static struct spi_driver max7301_driver = { |
| 316 | .driver = { | 91 | .driver = { |
| 317 | .name = DRIVER_NAME, | 92 | .name = "max7301", |
| 318 | .owner = THIS_MODULE, | 93 | .owner = THIS_MODULE, |
| 319 | }, | 94 | }, |
| 320 | .probe = max7301_probe, | 95 | .probe = max7301_probe, |
| 321 | .remove = __devexit_p(max7301_remove), | 96 | .remove = __devexit_p(max7301_remove), |
| 97 | .id_table = max7301_id, | ||
| 322 | }; | 98 | }; |
| 323 | 99 | ||
| 324 | static int __init max7301_init(void) | 100 | static int __init max7301_init(void) |
| @@ -336,7 +112,6 @@ static void __exit max7301_exit(void) | |||
| 336 | } | 112 | } |
| 337 | module_exit(max7301_exit); | 113 | module_exit(max7301_exit); |
| 338 | 114 | ||
| 339 | MODULE_AUTHOR("Juergen Beisert"); | 115 | MODULE_AUTHOR("Juergen Beisert, Wolfram Sang"); |
| 340 | MODULE_LICENSE("GPL v2"); | 116 | MODULE_LICENSE("GPL v2"); |
| 341 | MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander"); | 117 | MODULE_DESCRIPTION("MAX7301 GPIO-Expander"); |
| 342 | MODULE_ALIAS("spi:" DRIVER_NAME); | ||
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c new file mode 100644 index 000000000000..c9bced55f82b --- /dev/null +++ b/drivers/gpio/max730x.c | |||
| @@ -0,0 +1,244 @@ | |||
| 1 | /** | ||
| 2 | * drivers/gpio/max7301.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Juergen Beisert, Pengutronix | ||
| 5 | * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix | ||
| 6 | * Copyright (C) 2009 Wolfram Sang, Pengutronix | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are | ||
| 13 | * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more | ||
| 14 | * details | ||
| 15 | * Note: | ||
| 16 | * - DIN must be stable at the rising edge of clock. | ||
| 17 | * - when writing: | ||
| 18 | * - always clock in 16 clocks at once | ||
| 19 | * - at DIN: D15 first, D0 last | ||
| 20 | * - D0..D7 = databyte, D8..D14 = commandbyte | ||
| 21 | * - D15 = low -> write command | ||
| 22 | * - when reading | ||
| 23 | * - always clock in 16 clocks at once | ||
| 24 | * - at DIN: D15 first, D0 last | ||
| 25 | * - D0..D7 = dummy, D8..D14 = register address | ||
| 26 | * - D15 = high -> read command | ||
| 27 | * - raise CS and assert it again | ||
| 28 | * - always clock in 16 clocks at once | ||
| 29 | * - at DOUT: D15 first, D0 last | ||
| 30 | * - D0..D7 contains the data from the first cycle | ||
| 31 | * | ||
| 32 | * The driver exports a standard gpiochip interface | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include <linux/module.h> | ||
| 36 | #include <linux/init.h> | ||
| 37 | #include <linux/platform_device.h> | ||
| 38 | #include <linux/mutex.h> | ||
| 39 | #include <linux/spi/max7301.h> | ||
| 40 | #include <linux/gpio.h> | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Pin configurations, see MAX7301 datasheet page 6 | ||
| 44 | */ | ||
| 45 | #define PIN_CONFIG_MASK 0x03 | ||
| 46 | #define PIN_CONFIG_IN_PULLUP 0x03 | ||
| 47 | #define PIN_CONFIG_IN_WO_PULLUP 0x02 | ||
| 48 | #define PIN_CONFIG_OUT 0x01 | ||
| 49 | |||
| 50 | #define PIN_NUMBER 28 | ||
| 51 | |||
| 52 | static int max7301_direction_input(struct gpio_chip *chip, unsigned offset) | ||
| 53 | { | ||
| 54 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 55 | u8 *config; | ||
| 56 | u8 offset_bits; | ||
| 57 | int ret; | ||
| 58 | |||
| 59 | /* First 4 pins are unused in the controller */ | ||
| 60 | offset += 4; | ||
| 61 | offset_bits = (offset & 3) << 1; | ||
| 62 | |||
| 63 | config = &ts->port_config[offset >> 2]; | ||
| 64 | |||
| 65 | mutex_lock(&ts->lock); | ||
| 66 | |||
| 67 | /* Standard GPIO API doesn't support pull-ups, has to be extended. | ||
| 68 | * Hard-coding no pollup for now. */ | ||
| 69 | *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) | ||
| 70 | | (PIN_CONFIG_IN_WO_PULLUP << offset_bits); | ||
| 71 | |||
| 72 | ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); | ||
| 73 | |||
| 74 | mutex_unlock(&ts->lock); | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int __max7301_set(struct max7301 *ts, unsigned offset, int value) | ||
| 80 | { | ||
| 81 | if (value) { | ||
| 82 | ts->out_level |= 1 << offset; | ||
| 83 | return ts->write(ts->dev, 0x20 + offset, 0x01); | ||
| 84 | } else { | ||
| 85 | ts->out_level &= ~(1 << offset); | ||
| 86 | return ts->write(ts->dev, 0x20 + offset, 0x00); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | static int max7301_direction_output(struct gpio_chip *chip, unsigned offset, | ||
| 91 | int value) | ||
| 92 | { | ||
| 93 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 94 | u8 *config; | ||
| 95 | u8 offset_bits; | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | /* First 4 pins are unused in the controller */ | ||
| 99 | offset += 4; | ||
| 100 | offset_bits = (offset & 3) << 1; | ||
| 101 | |||
| 102 | config = &ts->port_config[offset >> 2]; | ||
| 103 | |||
| 104 | mutex_lock(&ts->lock); | ||
| 105 | |||
| 106 | *config = (*config & ~(PIN_CONFIG_MASK << offset_bits)) | ||
| 107 | | (PIN_CONFIG_OUT << offset_bits); | ||
| 108 | |||
| 109 | ret = __max7301_set(ts, offset, value); | ||
| 110 | |||
| 111 | if (!ret) | ||
| 112 | ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config); | ||
| 113 | |||
| 114 | mutex_unlock(&ts->lock); | ||
| 115 | |||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | static int max7301_get(struct gpio_chip *chip, unsigned offset) | ||
| 120 | { | ||
| 121 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 122 | int config, level = -EINVAL; | ||
| 123 | |||
| 124 | /* First 4 pins are unused in the controller */ | ||
| 125 | offset += 4; | ||
| 126 | |||
| 127 | mutex_lock(&ts->lock); | ||
| 128 | |||
| 129 | config = (ts->port_config[offset >> 2] >> ((offset & 3) << 1)) | ||
| 130 | & PIN_CONFIG_MASK; | ||
| 131 | |||
| 132 | switch (config) { | ||
| 133 | case PIN_CONFIG_OUT: | ||
| 134 | /* Output: return cached level */ | ||
| 135 | level = !!(ts->out_level & (1 << offset)); | ||
| 136 | break; | ||
| 137 | case PIN_CONFIG_IN_WO_PULLUP: | ||
| 138 | case PIN_CONFIG_IN_PULLUP: | ||
| 139 | /* Input: read out */ | ||
| 140 | level = ts->read(ts->dev, 0x20 + offset) & 0x01; | ||
| 141 | } | ||
| 142 | mutex_unlock(&ts->lock); | ||
| 143 | |||
| 144 | return level; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void max7301_set(struct gpio_chip *chip, unsigned offset, int value) | ||
| 148 | { | ||
| 149 | struct max7301 *ts = container_of(chip, struct max7301, chip); | ||
| 150 | |||
| 151 | /* First 4 pins are unused in the controller */ | ||
| 152 | offset += 4; | ||
| 153 | |||
| 154 | mutex_lock(&ts->lock); | ||
| 155 | |||
| 156 | __max7301_set(ts, offset, value); | ||
| 157 | |||
| 158 | mutex_unlock(&ts->lock); | ||
| 159 | } | ||
| 160 | |||
| 161 | int __devinit __max730x_probe(struct max7301 *ts) | ||
| 162 | { | ||
| 163 | struct device *dev = ts->dev; | ||
| 164 | struct max7301_platform_data *pdata; | ||
| 165 | int i, ret; | ||
| 166 | |||
| 167 | pdata = dev->platform_data; | ||
| 168 | if (!pdata || !pdata->base) { | ||
| 169 | dev_err(dev, "incorrect or missing platform data\n"); | ||
| 170 | return -EINVAL; | ||
| 171 | } | ||
| 172 | |||
| 173 | mutex_init(&ts->lock); | ||
| 174 | dev_set_drvdata(dev, ts); | ||
| 175 | |||
| 176 | /* Power up the chip and disable IRQ output */ | ||
| 177 | ts->write(dev, 0x04, 0x01); | ||
| 178 | |||
| 179 | ts->chip.label = dev->driver->name; | ||
| 180 | |||
| 181 | ts->chip.direction_input = max7301_direction_input; | ||
| 182 | ts->chip.get = max7301_get; | ||
| 183 | ts->chip.direction_output = max7301_direction_output; | ||
| 184 | ts->chip.set = max7301_set; | ||
| 185 | |||
| 186 | ts->chip.base = pdata->base; | ||
| 187 | ts->chip.ngpio = PIN_NUMBER; | ||
| 188 | ts->chip.can_sleep = 1; | ||
| 189 | ts->chip.dev = dev; | ||
| 190 | ts->chip.owner = THIS_MODULE; | ||
| 191 | |||
| 192 | /* | ||
| 193 | * tristate all pins in hardware and cache the | ||
| 194 | * register values for later use. | ||
| 195 | */ | ||
| 196 | for (i = 1; i < 8; i++) { | ||
| 197 | int j; | ||
| 198 | /* 0xAA means input with internal pullup disabled */ | ||
| 199 | ts->write(dev, 0x08 + i, 0xAA); | ||
| 200 | ts->port_config[i] = 0xAA; | ||
| 201 | for (j = 0; j < 4; j++) { | ||
| 202 | int offset = (i - 1) * 4 + j; | ||
| 203 | ret = max7301_direction_input(&ts->chip, offset); | ||
| 204 | if (ret) | ||
| 205 | goto exit_destroy; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | ret = gpiochip_add(&ts->chip); | ||
| 210 | if (ret) | ||
| 211 | goto exit_destroy; | ||
| 212 | |||
| 213 | return ret; | ||
| 214 | |||
| 215 | exit_destroy: | ||
| 216 | dev_set_drvdata(dev, NULL); | ||
| 217 | mutex_destroy(&ts->lock); | ||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | EXPORT_SYMBOL_GPL(__max730x_probe); | ||
| 221 | |||
| 222 | int __devexit __max730x_remove(struct device *dev) | ||
| 223 | { | ||
| 224 | struct max7301 *ts = dev_get_drvdata(dev); | ||
| 225 | int ret; | ||
| 226 | |||
| 227 | if (ts == NULL) | ||
| 228 | return -ENODEV; | ||
| 229 | |||
| 230 | dev_set_drvdata(dev, NULL); | ||
| 231 | |||
| 232 | /* Power down the chip and disable IRQ output */ | ||
| 233 | ts->write(dev, 0x04, 0x00); | ||
| 234 | |||
| 235 | ret = gpiochip_remove(&ts->chip); | ||
| 236 | if (!ret) { | ||
| 237 | mutex_destroy(&ts->lock); | ||
| 238 | kfree(ts); | ||
| 239 | } else | ||
| 240 | dev_err(dev, "Failed to remove GPIO controller: %d\n", ret); | ||
| 241 | |||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | EXPORT_SYMBOL_GPL(__max730x_remove); | ||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 6a2fb3fbb3d9..ab5daab14bc2 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/irq.h> | ||
| 17 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
| 18 | #include <linux/i2c/pca953x.h> | 20 | #include <linux/i2c/pca953x.h> |
| 19 | #ifdef CONFIG_OF_GPIO | 21 | #ifdef CONFIG_OF_GPIO |
| @@ -26,23 +28,28 @@ | |||
| 26 | #define PCA953X_INVERT 2 | 28 | #define PCA953X_INVERT 2 |
| 27 | #define PCA953X_DIRECTION 3 | 29 | #define PCA953X_DIRECTION 3 |
| 28 | 30 | ||
| 31 | #define PCA953X_GPIOS 0x00FF | ||
| 32 | #define PCA953X_INT 0x0100 | ||
| 33 | |||
| 29 | static const struct i2c_device_id pca953x_id[] = { | 34 | static const struct i2c_device_id pca953x_id[] = { |
| 30 | { "pca9534", 8, }, | 35 | { "pca9534", 8 | PCA953X_INT, }, |
| 31 | { "pca9535", 16, }, | 36 | { "pca9535", 16 | PCA953X_INT, }, |
| 32 | { "pca9536", 4, }, | 37 | { "pca9536", 4, }, |
| 33 | { "pca9537", 4, }, | 38 | { "pca9537", 4 | PCA953X_INT, }, |
| 34 | { "pca9538", 8, }, | 39 | { "pca9538", 8 | PCA953X_INT, }, |
| 35 | { "pca9539", 16, }, | 40 | { "pca9539", 16 | PCA953X_INT, }, |
| 36 | { "pca9554", 8, }, | 41 | { "pca9554", 8 | PCA953X_INT, }, |
| 37 | { "pca9555", 16, }, | 42 | { "pca9555", 16 | PCA953X_INT, }, |
| 38 | { "pca9556", 8, }, | 43 | { "pca9556", 8, }, |
| 39 | { "pca9557", 8, }, | 44 | { "pca9557", 8, }, |
| 40 | 45 | ||
| 41 | { "max7310", 8, }, | 46 | { "max7310", 8, }, |
| 42 | { "max7315", 8, }, | 47 | { "max7312", 16 | PCA953X_INT, }, |
| 43 | { "pca6107", 8, }, | 48 | { "max7313", 16 | PCA953X_INT, }, |
| 44 | { "tca6408", 8, }, | 49 | { "max7315", 8 | PCA953X_INT, }, |
| 45 | { "tca6416", 16, }, | 50 | { "pca6107", 8 | PCA953X_INT, }, |
| 51 | { "tca6408", 8 | PCA953X_INT, }, | ||
| 52 | { "tca6416", 16 | PCA953X_INT, }, | ||
| 46 | /* NYET: { "tca6424", 24, }, */ | 53 | /* NYET: { "tca6424", 24, }, */ |
| 47 | { } | 54 | { } |
| 48 | }; | 55 | }; |
| @@ -53,6 +60,15 @@ struct pca953x_chip { | |||
| 53 | uint16_t reg_output; | 60 | uint16_t reg_output; |
| 54 | uint16_t reg_direction; | 61 | uint16_t reg_direction; |
| 55 | 62 | ||
| 63 | #ifdef CONFIG_GPIO_PCA953X_IRQ | ||
| 64 | struct mutex irq_lock; | ||
| 65 | uint16_t irq_mask; | ||
| 66 | uint16_t irq_stat; | ||
| 67 | uint16_t irq_trig_raise; | ||
| 68 | uint16_t irq_trig_fall; | ||
| 69 | int irq_base; | ||
| 70 | #endif | ||
| 71 | |||
| 56 | struct i2c_client *client; | 72 | struct i2c_client *client; |
| 57 | struct pca953x_platform_data *dyn_pdata; | 73 | struct pca953x_platform_data *dyn_pdata; |
| 58 | struct gpio_chip gpio_chip; | 74 | struct gpio_chip gpio_chip; |
| @@ -202,6 +218,210 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | |||
| 202 | gc->names = chip->names; | 218 | gc->names = chip->names; |
| 203 | } | 219 | } |
| 204 | 220 | ||
| 221 | #ifdef CONFIG_GPIO_PCA953X_IRQ | ||
| 222 | static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) | ||
| 223 | { | ||
| 224 | struct pca953x_chip *chip; | ||
| 225 | |||
| 226 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
| 227 | return chip->irq_base + off; | ||
| 228 | } | ||
| 229 | |||
| 230 | static void pca953x_irq_mask(unsigned int irq) | ||
| 231 | { | ||
| 232 | struct pca953x_chip *chip = get_irq_chip_data(irq); | ||
| 233 | |||
| 234 | chip->irq_mask &= ~(1 << (irq - chip->irq_base)); | ||
| 235 | } | ||
| 236 | |||
| 237 | static void pca953x_irq_unmask(unsigned int irq) | ||
| 238 | { | ||
| 239 | struct pca953x_chip *chip = get_irq_chip_data(irq); | ||
| 240 | |||
| 241 | chip->irq_mask |= 1 << (irq - chip->irq_base); | ||
| 242 | } | ||
| 243 | |||
| 244 | static void pca953x_irq_bus_lock(unsigned int irq) | ||
| 245 | { | ||
| 246 | struct pca953x_chip *chip = get_irq_chip_data(irq); | ||
| 247 | |||
| 248 | mutex_lock(&chip->irq_lock); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void pca953x_irq_bus_sync_unlock(unsigned int irq) | ||
| 252 | { | ||
| 253 | struct pca953x_chip *chip = get_irq_chip_data(irq); | ||
| 254 | |||
| 255 | mutex_unlock(&chip->irq_lock); | ||
| 256 | } | ||
| 257 | |||
| 258 | static int pca953x_irq_set_type(unsigned int irq, unsigned int type) | ||
| 259 | { | ||
| 260 | struct pca953x_chip *chip = get_irq_chip_data(irq); | ||
| 261 | uint16_t level = irq - chip->irq_base; | ||
| 262 | uint16_t mask = 1 << level; | ||
| 263 | |||
| 264 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { | ||
| 265 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", | ||
| 266 | irq, type); | ||
| 267 | return -EINVAL; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
| 271 | chip->irq_trig_fall |= mask; | ||
| 272 | else | ||
| 273 | chip->irq_trig_fall &= ~mask; | ||
| 274 | |||
| 275 | if (type & IRQ_TYPE_EDGE_RISING) | ||
| 276 | chip->irq_trig_raise |= mask; | ||
| 277 | else | ||
| 278 | chip->irq_trig_raise &= ~mask; | ||
| 279 | |||
| 280 | return pca953x_gpio_direction_input(&chip->gpio_chip, level); | ||
| 281 | } | ||
| 282 | |||
| 283 | static struct irq_chip pca953x_irq_chip = { | ||
| 284 | .name = "pca953x", | ||
| 285 | .mask = pca953x_irq_mask, | ||
| 286 | .unmask = pca953x_irq_unmask, | ||
| 287 | .bus_lock = pca953x_irq_bus_lock, | ||
| 288 | .bus_sync_unlock = pca953x_irq_bus_sync_unlock, | ||
| 289 | .set_type = pca953x_irq_set_type, | ||
| 290 | }; | ||
| 291 | |||
| 292 | static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) | ||
| 293 | { | ||
| 294 | uint16_t cur_stat; | ||
| 295 | uint16_t old_stat; | ||
| 296 | uint16_t pending; | ||
| 297 | uint16_t trigger; | ||
| 298 | int ret; | ||
| 299 | |||
| 300 | ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat); | ||
| 301 | if (ret) | ||
| 302 | return 0; | ||
| 303 | |||
| 304 | /* Remove output pins from the equation */ | ||
| 305 | cur_stat &= chip->reg_direction; | ||
| 306 | |||
| 307 | old_stat = chip->irq_stat; | ||
| 308 | trigger = (cur_stat ^ old_stat) & chip->irq_mask; | ||
| 309 | |||
| 310 | if (!trigger) | ||
| 311 | return 0; | ||
| 312 | |||
| 313 | chip->irq_stat = cur_stat; | ||
| 314 | |||
| 315 | pending = (old_stat & chip->irq_trig_fall) | | ||
| 316 | (cur_stat & chip->irq_trig_raise); | ||
| 317 | pending &= trigger; | ||
| 318 | |||
| 319 | return pending; | ||
| 320 | } | ||
| 321 | |||
| 322 | static irqreturn_t pca953x_irq_handler(int irq, void *devid) | ||
| 323 | { | ||
| 324 | struct pca953x_chip *chip = devid; | ||
| 325 | uint16_t pending; | ||
| 326 | uint16_t level; | ||
| 327 | |||
| 328 | pending = pca953x_irq_pending(chip); | ||
| 329 | |||
| 330 | if (!pending) | ||
| 331 | return IRQ_HANDLED; | ||
| 332 | |||
| 333 | do { | ||
| 334 | level = __ffs(pending); | ||
| 335 | handle_nested_irq(level + chip->irq_base); | ||
| 336 | |||
| 337 | pending &= ~(1 << level); | ||
| 338 | } while (pending); | ||
| 339 | |||
| 340 | return IRQ_HANDLED; | ||
| 341 | } | ||
| 342 | |||
| 343 | static int pca953x_irq_setup(struct pca953x_chip *chip, | ||
| 344 | const struct i2c_device_id *id) | ||
| 345 | { | ||
| 346 | struct i2c_client *client = chip->client; | ||
| 347 | struct pca953x_platform_data *pdata = client->dev.platform_data; | ||
| 348 | int ret; | ||
| 349 | |||
| 350 | if (pdata->irq_base && (id->driver_data & PCA953X_INT)) { | ||
| 351 | int lvl; | ||
| 352 | |||
| 353 | ret = pca953x_read_reg(chip, PCA953X_INPUT, | ||
| 354 | &chip->irq_stat); | ||
| 355 | if (ret) | ||
| 356 | goto out_failed; | ||
| 357 | |||
| 358 | /* | ||
| 359 | * There is no way to know which GPIO line generated the | ||
| 360 | * interrupt. We have to rely on the previous read for | ||
| 361 | * this purpose. | ||
| 362 | */ | ||
| 363 | chip->irq_stat &= chip->reg_direction; | ||
| 364 | chip->irq_base = pdata->irq_base; | ||
| 365 | mutex_init(&chip->irq_lock); | ||
| 366 | |||
| 367 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { | ||
| 368 | int irq = lvl + chip->irq_base; | ||
| 369 | |||
| 370 | set_irq_chip_data(irq, chip); | ||
| 371 | set_irq_chip_and_handler(irq, &pca953x_irq_chip, | ||
| 372 | handle_edge_irq); | ||
| 373 | set_irq_nested_thread(irq, 1); | ||
| 374 | #ifdef CONFIG_ARM | ||
| 375 | set_irq_flags(irq, IRQF_VALID); | ||
| 376 | #else | ||
| 377 | set_irq_noprobe(irq); | ||
| 378 | #endif | ||
| 379 | } | ||
| 380 | |||
| 381 | ret = request_threaded_irq(client->irq, | ||
| 382 | NULL, | ||
| 383 | pca953x_irq_handler, | ||
| 384 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 385 | dev_name(&client->dev), chip); | ||
| 386 | if (ret) { | ||
| 387 | dev_err(&client->dev, "failed to request irq %d\n", | ||
| 388 | client->irq); | ||
| 389 | goto out_failed; | ||
| 390 | } | ||
| 391 | |||
| 392 | chip->gpio_chip.to_irq = pca953x_gpio_to_irq; | ||
| 393 | } | ||
| 394 | |||
| 395 | return 0; | ||
| 396 | |||
| 397 | out_failed: | ||
| 398 | chip->irq_base = 0; | ||
| 399 | return ret; | ||
| 400 | } | ||
| 401 | |||
| 402 | static void pca953x_irq_teardown(struct pca953x_chip *chip) | ||
| 403 | { | ||
| 404 | if (chip->irq_base) | ||
| 405 | free_irq(chip->client->irq, chip); | ||
| 406 | } | ||
| 407 | #else /* CONFIG_GPIO_PCA953X_IRQ */ | ||
| 408 | static int pca953x_irq_setup(struct pca953x_chip *chip, | ||
| 409 | const struct i2c_device_id *id) | ||
| 410 | { | ||
| 411 | struct i2c_client *client = chip->client; | ||
| 412 | struct pca953x_platform_data *pdata = client->dev.platform_data; | ||
| 413 | |||
| 414 | if (pdata->irq_base && (id->driver_data & PCA953X_INT)) | ||
| 415 | dev_warn(&client->dev, "interrupt support not compiled in\n"); | ||
| 416 | |||
| 417 | return 0; | ||
| 418 | } | ||
| 419 | |||
| 420 | static void pca953x_irq_teardown(struct pca953x_chip *chip) | ||
| 421 | { | ||
| 422 | } | ||
| 423 | #endif | ||
| 424 | |||
| 205 | /* | 425 | /* |
| 206 | * Handlers for alternative sources of platform_data | 426 | * Handlers for alternative sources of platform_data |
| 207 | */ | 427 | */ |
| @@ -286,7 +506,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
| 286 | /* initialize cached registers from their original values. | 506 | /* initialize cached registers from their original values. |
| 287 | * we can't share this chip with another i2c master. | 507 | * we can't share this chip with another i2c master. |
| 288 | */ | 508 | */ |
| 289 | pca953x_setup_gpio(chip, id->driver_data); | 509 | pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS); |
| 290 | 510 | ||
| 291 | ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); | 511 | ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); |
| 292 | if (ret) | 512 | if (ret) |
| @@ -301,6 +521,9 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
| 301 | if (ret) | 521 | if (ret) |
| 302 | goto out_failed; | 522 | goto out_failed; |
| 303 | 523 | ||
| 524 | ret = pca953x_irq_setup(chip, id); | ||
| 525 | if (ret) | ||
| 526 | goto out_failed; | ||
| 304 | 527 | ||
| 305 | ret = gpiochip_add(&chip->gpio_chip); | 528 | ret = gpiochip_add(&chip->gpio_chip); |
| 306 | if (ret) | 529 | if (ret) |
| @@ -317,6 +540,7 @@ static int __devinit pca953x_probe(struct i2c_client *client, | |||
| 317 | return 0; | 540 | return 0; |
| 318 | 541 | ||
| 319 | out_failed: | 542 | out_failed: |
| 543 | pca953x_irq_teardown(chip); | ||
| 320 | kfree(chip->dyn_pdata); | 544 | kfree(chip->dyn_pdata); |
| 321 | kfree(chip); | 545 | kfree(chip); |
| 322 | return ret; | 546 | return ret; |
| @@ -345,6 +569,7 @@ static int pca953x_remove(struct i2c_client *client) | |||
| 345 | return ret; | 569 | return ret; |
| 346 | } | 570 | } |
| 347 | 571 | ||
| 572 | pca953x_irq_teardown(chip); | ||
| 348 | kfree(chip->dyn_pdata); | 573 | kfree(chip->dyn_pdata); |
| 349 | kfree(chip); | 574 | kfree(chip); |
| 350 | return 0; | 575 | return 0; |
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 4ee4c8367a3f..3ad1eeb49609 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c | |||
| @@ -219,7 +219,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
| 219 | if (pending == 0) | 219 | if (pending == 0) |
| 220 | continue; | 220 | continue; |
| 221 | 221 | ||
| 222 | for_each_bit(offset, &pending, PL061_GPIO_NR) | 222 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) |
| 223 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); | 223 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); |
| 224 | } | 224 | } |
| 225 | desc->chip->unmask(irq); | 225 | desc->chip->unmask(irq); |
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index a4d344ba8e5c..d4295fa5369e 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/irq.h> | ||
| 26 | #include <linux/io.h> | 27 | #include <linux/io.h> |
| 27 | #include <linux/timb_gpio.h> | 28 | #include <linux/timb_gpio.h> |
| 28 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| @@ -37,6 +38,8 @@ | |||
| 37 | #define TGPIO_ICR 0x14 | 38 | #define TGPIO_ICR 0x14 |
| 38 | #define TGPIO_FLR 0x18 | 39 | #define TGPIO_FLR 0x18 |
| 39 | #define TGPIO_LVR 0x1c | 40 | #define TGPIO_LVR 0x1c |
| 41 | #define TGPIO_VER 0x20 | ||
| 42 | #define TGPIO_BFLR 0x24 | ||
| 40 | 43 | ||
| 41 | struct timbgpio { | 44 | struct timbgpio { |
| 42 | void __iomem *membase; | 45 | void __iomem *membase; |
| @@ -125,17 +128,23 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger) | |||
| 125 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 128 | struct timbgpio *tgpio = get_irq_chip_data(irq); |
| 126 | int offset = irq - tgpio->irq_base; | 129 | int offset = irq - tgpio->irq_base; |
| 127 | unsigned long flags; | 130 | unsigned long flags; |
| 128 | u32 lvr, flr; | 131 | u32 lvr, flr, bflr = 0; |
| 132 | u32 ver; | ||
| 129 | 133 | ||
| 130 | if (offset < 0 || offset > tgpio->gpio.ngpio) | 134 | if (offset < 0 || offset > tgpio->gpio.ngpio) |
| 131 | return -EINVAL; | 135 | return -EINVAL; |
| 132 | 136 | ||
| 137 | ver = ioread32(tgpio->membase + TGPIO_VER); | ||
| 138 | |||
| 133 | spin_lock_irqsave(&tgpio->lock, flags); | 139 | spin_lock_irqsave(&tgpio->lock, flags); |
| 134 | 140 | ||
| 135 | lvr = ioread32(tgpio->membase + TGPIO_LVR); | 141 | lvr = ioread32(tgpio->membase + TGPIO_LVR); |
| 136 | flr = ioread32(tgpio->membase + TGPIO_FLR); | 142 | flr = ioread32(tgpio->membase + TGPIO_FLR); |
| 143 | if (ver > 2) | ||
| 144 | bflr = ioread32(tgpio->membase + TGPIO_BFLR); | ||
| 137 | 145 | ||
| 138 | if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { | 146 | if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { |
| 147 | bflr &= ~(1 << offset); | ||
| 139 | flr &= ~(1 << offset); | 148 | flr &= ~(1 << offset); |
| 140 | if (trigger & IRQ_TYPE_LEVEL_HIGH) | 149 | if (trigger & IRQ_TYPE_LEVEL_HIGH) |
| 141 | lvr |= 1 << offset; | 150 | lvr |= 1 << offset; |
| @@ -143,21 +152,27 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger) | |||
| 143 | lvr &= ~(1 << offset); | 152 | lvr &= ~(1 << offset); |
| 144 | } | 153 | } |
| 145 | 154 | ||
| 146 | if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) | 155 | if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) { |
| 147 | return -EINVAL; | 156 | if (ver < 3) |
| 148 | else { | 157 | return -EINVAL; |
| 158 | else { | ||
| 159 | flr |= 1 << offset; | ||
| 160 | bflr |= 1 << offset; | ||
| 161 | } | ||
| 162 | } else { | ||
| 163 | bflr &= ~(1 << offset); | ||
| 149 | flr |= 1 << offset; | 164 | flr |= 1 << offset; |
| 150 | /* opposite compared to the datasheet, but it mirrors the | ||
| 151 | * reality | ||
| 152 | */ | ||
| 153 | if (trigger & IRQ_TYPE_EDGE_FALLING) | 165 | if (trigger & IRQ_TYPE_EDGE_FALLING) |
| 154 | lvr |= 1 << offset; | ||
| 155 | else | ||
| 156 | lvr &= ~(1 << offset); | 166 | lvr &= ~(1 << offset); |
| 167 | else | ||
| 168 | lvr |= 1 << offset; | ||
| 157 | } | 169 | } |
| 158 | 170 | ||
| 159 | iowrite32(lvr, tgpio->membase + TGPIO_LVR); | 171 | iowrite32(lvr, tgpio->membase + TGPIO_LVR); |
| 160 | iowrite32(flr, tgpio->membase + TGPIO_FLR); | 172 | iowrite32(flr, tgpio->membase + TGPIO_FLR); |
| 173 | if (ver > 2) | ||
| 174 | iowrite32(bflr, tgpio->membase + TGPIO_BFLR); | ||
| 175 | |||
| 161 | iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); | 176 | iowrite32(1 << offset, tgpio->membase + TGPIO_ICR); |
| 162 | spin_unlock_irqrestore(&tgpio->lock, flags); | 177 | spin_unlock_irqrestore(&tgpio->lock, flags); |
| 163 | 178 | ||
| @@ -174,7 +189,7 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) | |||
| 174 | ipr = ioread32(tgpio->membase + TGPIO_IPR); | 189 | ipr = ioread32(tgpio->membase + TGPIO_IPR); |
| 175 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); | 190 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); |
| 176 | 191 | ||
| 177 | for_each_bit(offset, &ipr, tgpio->gpio.ngpio) | 192 | for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) |
| 178 | generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); | 193 | generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); |
| 179 | } | 194 | } |
| 180 | 195 | ||
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 305c59003963..3d2ab03f1296 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -9,6 +9,7 @@ menuconfig DRM | |||
| 9 | depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU | 9 | depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU |
| 10 | select I2C | 10 | select I2C |
| 11 | select I2C_ALGOBIT | 11 | select I2C_ALGOBIT |
| 12 | select LIST_SORT | ||
| 12 | help | 13 | help |
| 13 | Kernel-level support for the Direct Rendering Infrastructure (DRI) | 14 | Kernel-level support for the Direct Rendering Infrastructure (DRI) |
| 14 | introduced in XFree86 4.0. If you say Y here, you need to select | 15 | introduced in XFree86 4.0. If you say Y here, you need to select |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 68cf87749a42..e4595e6147b4 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -170,6 +170,16 @@ config SENSORS_ADM9240 | |||
| 170 | This driver can also be built as a module. If so, the module | 170 | This driver can also be built as a module. If so, the module |
| 171 | will be called adm9240. | 171 | will be called adm9240. |
| 172 | 172 | ||
| 173 | config SENSORS_ADT7411 | ||
| 174 | tristate "Analog Devices ADT7411" | ||
| 175 | depends on I2C && EXPERIMENTAL | ||
| 176 | help | ||
| 177 | If you say yes here you get support for the Analog Devices | ||
| 178 | ADT7411 voltage and temperature monitoring chip. | ||
| 179 | |||
| 180 | This driver can also be built as a module. If so, the module | ||
| 181 | will be called adt7411. | ||
| 182 | |||
| 173 | config SENSORS_ADT7462 | 183 | config SENSORS_ADT7462 |
| 174 | tristate "Analog Devices ADT7462" | 184 | tristate "Analog Devices ADT7462" |
| 175 | depends on I2C && EXPERIMENTAL | 185 | depends on I2C && EXPERIMENTAL |
| @@ -190,20 +200,6 @@ config SENSORS_ADT7470 | |||
| 190 | This driver can also be built as a module. If so, the module | 200 | This driver can also be built as a module. If so, the module |
| 191 | will be called adt7470. | 201 | will be called adt7470. |
| 192 | 202 | ||
| 193 | config SENSORS_ADT7473 | ||
| 194 | tristate "Analog Devices ADT7473 (DEPRECATED)" | ||
| 195 | depends on I2C && EXPERIMENTAL | ||
| 196 | select SENSORS_ADT7475 | ||
| 197 | help | ||
| 198 | If you say yes here you get support for the Analog Devices | ||
| 199 | ADT7473 temperature monitoring chips. | ||
| 200 | |||
| 201 | This driver is deprecated, you should use the adt7475 driver | ||
| 202 | instead. | ||
| 203 | |||
| 204 | This driver can also be built as a module. If so, the module | ||
| 205 | will be called adt7473. | ||
| 206 | |||
| 207 | config SENSORS_ADT7475 | 203 | config SENSORS_ADT7475 |
| 208 | tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490" | 204 | tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490" |
| 209 | depends on I2C && EXPERIMENTAL | 205 | depends on I2C && EXPERIMENTAL |
| @@ -216,6 +212,19 @@ config SENSORS_ADT7475 | |||
| 216 | This driver can also be build as a module. If so, the module | 212 | This driver can also be build as a module. If so, the module |
| 217 | will be called adt7475. | 213 | will be called adt7475. |
| 218 | 214 | ||
| 215 | config SENSORS_ASC7621 | ||
| 216 | tristate "Andigilog aSC7621" | ||
| 217 | depends on HWMON && I2C | ||
| 218 | help | ||
| 219 | If you say yes here you get support for the aSC7621 | ||
| 220 | family of SMBus sensors chip found on most Intel X48, X38, 975, | ||
| 221 | 965 and 945 desktop boards. Currently supported chips: | ||
| 222 | aSC7621 | ||
| 223 | aSC7621a | ||
| 224 | |||
| 225 | This driver can also be built as a module. If so, the module | ||
| 226 | will be called asc7621. | ||
| 227 | |||
| 219 | config SENSORS_K8TEMP | 228 | config SENSORS_K8TEMP |
| 220 | tristate "AMD Athlon64/FX or Opteron temperature sensor" | 229 | tristate "AMD Athlon64/FX or Opteron temperature sensor" |
| 221 | depends on X86 && PCI && EXPERIMENTAL | 230 | depends on X86 && PCI && EXPERIMENTAL |
| @@ -563,9 +572,10 @@ config SENSORS_LM90 | |||
| 563 | depends on I2C | 572 | depends on I2C |
| 564 | help | 573 | help |
| 565 | If you say yes here you get support for National Semiconductor LM90, | 574 | If you say yes here you get support for National Semiconductor LM90, |
| 566 | LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim | 575 | LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, Maxim |
| 567 | MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, | 576 | MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, |
| 568 | MAX6680, MAX6681 and MAX6692 sensor chips. | 577 | MAX6680, MAX6681 and MAX6692, and Winbond/Nuvoton W83L771AWG/ASG |
| 578 | sensor chips. | ||
| 569 | 579 | ||
| 570 | This driver can also be built as a module. If so, the module | 580 | This driver can also be built as a module. If so, the module |
| 571 | will be called lm90. | 581 | will be called lm90. |
| @@ -909,7 +919,8 @@ config SENSORS_W83793 | |||
| 909 | select HWMON_VID | 919 | select HWMON_VID |
| 910 | help | 920 | help |
| 911 | If you say yes here you get support for the Winbond W83793 | 921 | If you say yes here you get support for the Winbond W83793 |
| 912 | hardware monitoring chip. | 922 | hardware monitoring chip, including support for the integrated |
| 923 | watchdog. | ||
| 913 | 924 | ||
| 914 | This driver can also be built as a module. If so, the module | 925 | This driver can also be built as a module. If so, the module |
| 915 | will be called w83793. | 926 | will be called w83793. |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 4bc215c0953f..4aa1a3d112ad 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
| @@ -29,12 +29,13 @@ obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o | |||
| 29 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o | 29 | obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o |
| 30 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o | 30 | obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o |
| 31 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o | 31 | obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o |
| 32 | obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o | ||
| 32 | obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o | 33 | obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o |
| 33 | obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o | 34 | obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o |
| 34 | obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o | ||
| 35 | obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o | 35 | obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o |
| 36 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o | 36 | obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o |
| 37 | obj-$(CONFIG_SENSORS_AMS) += ams/ | 37 | obj-$(CONFIG_SENSORS_AMS) += ams/ |
| 38 | obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o | ||
| 38 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o | 39 | obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o |
| 39 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o | 40 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o |
| 40 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o | 41 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o |
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c index 5e9e095f1136..74d9c5195e44 100644 --- a/drivers/hwmon/adcxx.c +++ b/drivers/hwmon/adcxx.c | |||
| @@ -62,18 +62,23 @@ static ssize_t adcxx_read(struct device *dev, | |||
| 62 | struct spi_device *spi = to_spi_device(dev); | 62 | struct spi_device *spi = to_spi_device(dev); |
| 63 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 63 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
| 64 | struct adcxx *adc = dev_get_drvdata(&spi->dev); | 64 | struct adcxx *adc = dev_get_drvdata(&spi->dev); |
| 65 | u8 tx_buf[2] = { attr->index << 3 }; /* other bits are don't care */ | 65 | u8 tx_buf[2]; |
| 66 | u8 rx_buf[2]; | 66 | u8 rx_buf[2]; |
| 67 | int status; | 67 | int status; |
| 68 | int value; | 68 | u32 value; |
| 69 | 69 | ||
| 70 | if (mutex_lock_interruptible(&adc->lock)) | 70 | if (mutex_lock_interruptible(&adc->lock)) |
| 71 | return -ERESTARTSYS; | 71 | return -ERESTARTSYS; |
| 72 | 72 | ||
| 73 | status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), | 73 | if (adc->channels == 1) { |
| 74 | rx_buf, sizeof(rx_buf)); | 74 | status = spi_read(spi, rx_buf, sizeof(rx_buf)); |
| 75 | } else { | ||
| 76 | tx_buf[0] = attr->index << 3; /* other bits are don't care */ | ||
| 77 | status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), | ||
| 78 | rx_buf, sizeof(rx_buf)); | ||
| 79 | } | ||
| 75 | if (status < 0) { | 80 | if (status < 0) { |
| 76 | dev_warn(dev, "spi_write_then_read failed with status %d\n", | 81 | dev_warn(dev, "SPI synch. transfer failed with status %d\n", |
| 77 | status); | 82 | status); |
| 78 | goto out; | 83 | goto out; |
| 79 | } | 84 | } |
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c new file mode 100644 index 000000000000..3471884e42d2 --- /dev/null +++ b/drivers/hwmon/adt7411.c | |||
| @@ -0,0 +1,366 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the ADT7411 (I2C/SPI 8 channel 10 bit ADC & temperature-sensor) | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008, 2010 Pengutronix | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * TODO: SPI, support for external temperature sensor | ||
| 11 | * use power-down mode for suspend?, interrupt handling? | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/delay.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/jiffies.h> | ||
| 21 | #include <linux/i2c.h> | ||
| 22 | #include <linux/hwmon.h> | ||
| 23 | #include <linux/hwmon-sysfs.h> | ||
| 24 | |||
| 25 | #define ADT7411_REG_INT_TEMP_VDD_LSB 0x03 | ||
| 26 | #define ADT7411_REG_EXT_TEMP_AIN14_LSB 0x04 | ||
| 27 | #define ADT7411_REG_VDD_MSB 0x06 | ||
| 28 | #define ADT7411_REG_INT_TEMP_MSB 0x07 | ||
| 29 | #define ADT7411_REG_EXT_TEMP_AIN1_MSB 0x08 | ||
| 30 | |||
| 31 | #define ADT7411_REG_CFG1 0x18 | ||
| 32 | #define ADT7411_CFG1_START_MONITOR (1 << 0) | ||
| 33 | |||
| 34 | #define ADT7411_REG_CFG2 0x19 | ||
| 35 | #define ADT7411_CFG2_DISABLE_AVG (1 << 5) | ||
| 36 | |||
| 37 | #define ADT7411_REG_CFG3 0x1a | ||
| 38 | #define ADT7411_CFG3_ADC_CLK_225 (1 << 0) | ||
| 39 | #define ADT7411_CFG3_REF_VDD (1 << 4) | ||
| 40 | |||
| 41 | #define ADT7411_REG_DEVICE_ID 0x4d | ||
| 42 | #define ADT7411_REG_MANUFACTURER_ID 0x4e | ||
| 43 | |||
| 44 | #define ADT7411_DEVICE_ID 0x2 | ||
| 45 | #define ADT7411_MANUFACTURER_ID 0x41 | ||
| 46 | |||
| 47 | static const unsigned short normal_i2c[] = { 0x48, 0x4a, 0x4b, I2C_CLIENT_END }; | ||
| 48 | |||
| 49 | struct adt7411_data { | ||
| 50 | struct mutex device_lock; /* for "atomic" device accesses */ | ||
| 51 | struct mutex update_lock; | ||
| 52 | unsigned long next_update; | ||
| 53 | int vref_cached; | ||
| 54 | struct device *hwmon_dev; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /* | ||
| 58 | * When reading a register containing (up to 4) lsb, all associated | ||
| 59 | * msb-registers get locked by the hardware. After _one_ of those msb is read, | ||
| 60 | * _all_ are unlocked. In order to use this locking correctly, reading lsb/msb | ||
| 61 | * is protected here with a mutex, too. | ||
| 62 | */ | ||
| 63 | static int adt7411_read_10_bit(struct i2c_client *client, u8 lsb_reg, | ||
| 64 | u8 msb_reg, u8 lsb_shift) | ||
| 65 | { | ||
| 66 | struct adt7411_data *data = i2c_get_clientdata(client); | ||
| 67 | int val, tmp; | ||
| 68 | |||
| 69 | mutex_lock(&data->device_lock); | ||
| 70 | |||
| 71 | val = i2c_smbus_read_byte_data(client, lsb_reg); | ||
| 72 | if (val < 0) | ||
| 73 | goto exit_unlock; | ||
| 74 | |||
| 75 | tmp = (val >> lsb_shift) & 3; | ||
| 76 | val = i2c_smbus_read_byte_data(client, msb_reg); | ||
| 77 | |||
| 78 | if (val >= 0) | ||
| 79 | val = (val << 2) | tmp; | ||
| 80 | |||
| 81 | exit_unlock: | ||
| 82 | mutex_unlock(&data->device_lock); | ||
| 83 | |||
| 84 | return val; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int adt7411_modify_bit(struct i2c_client *client, u8 reg, u8 bit, | ||
| 88 | bool flag) | ||
| 89 | { | ||
| 90 | struct adt7411_data *data = i2c_get_clientdata(client); | ||
| 91 | int ret, val; | ||
| 92 | |||
| 93 | mutex_lock(&data->device_lock); | ||
| 94 | |||
| 95 | ret = i2c_smbus_read_byte_data(client, reg); | ||
| 96 | if (ret < 0) | ||
| 97 | goto exit_unlock; | ||
| 98 | |||
| 99 | if (flag) | ||
| 100 | val = ret | bit; | ||
| 101 | else | ||
| 102 | val = ret & ~bit; | ||
| 103 | |||
| 104 | ret = i2c_smbus_write_byte_data(client, reg, val); | ||
| 105 | |||
| 106 | exit_unlock: | ||
| 107 | mutex_unlock(&data->device_lock); | ||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | |||
| 111 | static ssize_t adt7411_show_vdd(struct device *dev, | ||
| 112 | struct device_attribute *attr, char *buf) | ||
| 113 | { | ||
| 114 | struct i2c_client *client = to_i2c_client(dev); | ||
| 115 | int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, | ||
| 116 | ADT7411_REG_VDD_MSB, 2); | ||
| 117 | |||
| 118 | return ret < 0 ? ret : sprintf(buf, "%u\n", ret * 7000 / 1024); | ||
| 119 | } | ||
| 120 | |||
| 121 | static ssize_t adt7411_show_temp(struct device *dev, | ||
| 122 | struct device_attribute *attr, char *buf) | ||
| 123 | { | ||
| 124 | struct i2c_client *client = to_i2c_client(dev); | ||
| 125 | int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, | ||
| 126 | ADT7411_REG_INT_TEMP_MSB, 0); | ||
| 127 | |||
| 128 | if (val < 0) | ||
| 129 | return val; | ||
| 130 | |||
| 131 | val = val & 0x200 ? val - 0x400 : val; /* 10 bit signed */ | ||
| 132 | |||
| 133 | return sprintf(buf, "%d\n", val * 250); | ||
| 134 | } | ||
| 135 | |||
| 136 | static ssize_t adt7411_show_input(struct device *dev, | ||
| 137 | struct device_attribute *attr, char *buf) | ||
| 138 | { | ||
| 139 | int nr = to_sensor_dev_attr(attr)->index; | ||
| 140 | struct i2c_client *client = to_i2c_client(dev); | ||
| 141 | struct adt7411_data *data = i2c_get_clientdata(client); | ||
| 142 | int val; | ||
| 143 | u8 lsb_reg, lsb_shift; | ||
| 144 | |||
| 145 | mutex_lock(&data->update_lock); | ||
| 146 | if (time_after_eq(jiffies, data->next_update)) { | ||
| 147 | val = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3); | ||
| 148 | if (val < 0) | ||
| 149 | goto exit_unlock; | ||
| 150 | |||
| 151 | if (val & ADT7411_CFG3_REF_VDD) { | ||
| 152 | val = adt7411_read_10_bit(client, | ||
| 153 | ADT7411_REG_INT_TEMP_VDD_LSB, | ||
| 154 | ADT7411_REG_VDD_MSB, 2); | ||
| 155 | if (val < 0) | ||
| 156 | goto exit_unlock; | ||
| 157 | |||
| 158 | data->vref_cached = val * 7000 / 1024; | ||
| 159 | } else { | ||
| 160 | data->vref_cached = 2250; | ||
| 161 | } | ||
| 162 | |||
| 163 | data->next_update = jiffies + HZ; | ||
| 164 | } | ||
| 165 | |||
| 166 | lsb_reg = ADT7411_REG_EXT_TEMP_AIN14_LSB + (nr >> 2); | ||
| 167 | lsb_shift = 2 * (nr & 0x03); | ||
| 168 | val = adt7411_read_10_bit(client, lsb_reg, | ||
| 169 | ADT7411_REG_EXT_TEMP_AIN1_MSB + nr, lsb_shift); | ||
| 170 | if (val < 0) | ||
| 171 | goto exit_unlock; | ||
| 172 | |||
| 173 | val = sprintf(buf, "%u\n", val * data->vref_cached / 1024); | ||
| 174 | exit_unlock: | ||
| 175 | mutex_unlock(&data->update_lock); | ||
| 176 | return val; | ||
| 177 | } | ||
| 178 | |||
| 179 | static ssize_t adt7411_show_bit(struct device *dev, | ||
| 180 | struct device_attribute *attr, char *buf) | ||
| 181 | { | ||
| 182 | struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); | ||
| 183 | struct i2c_client *client = to_i2c_client(dev); | ||
| 184 | int ret = i2c_smbus_read_byte_data(client, attr2->index); | ||
| 185 | |||
| 186 | return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr)); | ||
| 187 | } | ||
| 188 | |||
| 189 | static ssize_t adt7411_set_bit(struct device *dev, | ||
| 190 | struct device_attribute *attr, const char *buf, | ||
| 191 | size_t count) | ||
| 192 | { | ||
| 193 | struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr); | ||
| 194 | struct i2c_client *client = to_i2c_client(dev); | ||
| 195 | struct adt7411_data *data = i2c_get_clientdata(client); | ||
| 196 | int ret; | ||
| 197 | unsigned long flag; | ||
| 198 | |||
| 199 | ret = strict_strtoul(buf, 0, &flag); | ||
| 200 | if (ret || flag > 1) | ||
| 201 | return -EINVAL; | ||
| 202 | |||
| 203 | ret = adt7411_modify_bit(client, s_attr2->index, s_attr2->nr, flag); | ||
| 204 | |||
| 205 | /* force update */ | ||
| 206 | mutex_lock(&data->update_lock); | ||
| 207 | data->next_update = jiffies; | ||
| 208 | mutex_unlock(&data->update_lock); | ||
| 209 | |||
| 210 | return ret < 0 ? ret : count; | ||
| 211 | } | ||
| 212 | |||
| 213 | #define ADT7411_BIT_ATTR(__name, __reg, __bit) \ | ||
| 214 | SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \ | ||
| 215 | adt7411_set_bit, __bit, __reg) | ||
| 216 | |||
| 217 | static DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL); | ||
| 218 | static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL); | ||
| 219 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0); | ||
| 220 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1); | ||
| 221 | static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, adt7411_show_input, NULL, 2); | ||
| 222 | static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, adt7411_show_input, NULL, 3); | ||
| 223 | static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, adt7411_show_input, NULL, 4); | ||
| 224 | static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, adt7411_show_input, NULL, 5); | ||
| 225 | static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, adt7411_show_input, NULL, 6); | ||
| 226 | static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, adt7411_show_input, NULL, 7); | ||
| 227 | static ADT7411_BIT_ATTR(no_average, ADT7411_REG_CFG2, ADT7411_CFG2_DISABLE_AVG); | ||
| 228 | static ADT7411_BIT_ATTR(fast_sampling, ADT7411_REG_CFG3, ADT7411_CFG3_ADC_CLK_225); | ||
| 229 | static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD); | ||
| 230 | |||
| 231 | static struct attribute *adt7411_attrs[] = { | ||
| 232 | &dev_attr_temp1_input.attr, | ||
| 233 | &dev_attr_in0_input.attr, | ||
| 234 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
| 235 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
| 236 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
| 237 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
| 238 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
| 239 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
| 240 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
| 241 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
| 242 | &sensor_dev_attr_no_average.dev_attr.attr, | ||
| 243 | &sensor_dev_attr_fast_sampling.dev_attr.attr, | ||
| 244 | &sensor_dev_attr_adc_ref_vdd.dev_attr.attr, | ||
| 245 | NULL | ||
| 246 | }; | ||
| 247 | |||
| 248 | static const struct attribute_group adt7411_attr_grp = { | ||
| 249 | .attrs = adt7411_attrs, | ||
| 250 | }; | ||
| 251 | |||
| 252 | static int adt7411_detect(struct i2c_client *client, | ||
| 253 | struct i2c_board_info *info) | ||
| 254 | { | ||
| 255 | int val; | ||
| 256 | |||
| 257 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 258 | return -ENODEV; | ||
| 259 | |||
| 260 | val = i2c_smbus_read_byte_data(client, ADT7411_REG_MANUFACTURER_ID); | ||
| 261 | if (val < 0 || val != ADT7411_MANUFACTURER_ID) { | ||
| 262 | dev_dbg(&client->dev, "Wrong manufacturer ID. Got %d, " | ||
| 263 | "expected %d\n", val, ADT7411_MANUFACTURER_ID); | ||
| 264 | return -ENODEV; | ||
| 265 | } | ||
| 266 | |||
| 267 | val = i2c_smbus_read_byte_data(client, ADT7411_REG_DEVICE_ID); | ||
| 268 | if (val < 0 || val != ADT7411_DEVICE_ID) { | ||
| 269 | dev_dbg(&client->dev, "Wrong device ID. Got %d, " | ||
| 270 | "expected %d\n", val, ADT7411_DEVICE_ID); | ||
| 271 | return -ENODEV; | ||
| 272 | } | ||
| 273 | |||
| 274 | strlcpy(info->type, "adt7411", I2C_NAME_SIZE); | ||
| 275 | |||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int __devinit adt7411_probe(struct i2c_client *client, | ||
| 280 | const struct i2c_device_id *id) | ||
| 281 | { | ||
| 282 | struct adt7411_data *data; | ||
| 283 | int ret; | ||
| 284 | |||
| 285 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 286 | if (!data) | ||
| 287 | return -ENOMEM; | ||
| 288 | |||
| 289 | i2c_set_clientdata(client, data); | ||
| 290 | mutex_init(&data->device_lock); | ||
| 291 | mutex_init(&data->update_lock); | ||
| 292 | |||
| 293 | ret = adt7411_modify_bit(client, ADT7411_REG_CFG1, | ||
| 294 | ADT7411_CFG1_START_MONITOR, 1); | ||
| 295 | if (ret < 0) | ||
| 296 | goto exit_free; | ||
| 297 | |||
| 298 | /* force update on first occasion */ | ||
| 299 | data->next_update = jiffies; | ||
| 300 | |||
| 301 | ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp); | ||
| 302 | if (ret) | ||
| 303 | goto exit_free; | ||
| 304 | |||
| 305 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
| 306 | if (IS_ERR(data->hwmon_dev)) { | ||
| 307 | ret = PTR_ERR(data->hwmon_dev); | ||
| 308 | goto exit_remove; | ||
| 309 | } | ||
| 310 | |||
| 311 | dev_info(&client->dev, "successfully registered\n"); | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | |||
| 315 | exit_remove: | ||
| 316 | sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); | ||
| 317 | exit_free: | ||
| 318 | i2c_set_clientdata(client, NULL); | ||
| 319 | kfree(data); | ||
| 320 | return ret; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int __devexit adt7411_remove(struct i2c_client *client) | ||
| 324 | { | ||
| 325 | struct adt7411_data *data = i2c_get_clientdata(client); | ||
| 326 | |||
| 327 | hwmon_device_unregister(data->hwmon_dev); | ||
| 328 | sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); | ||
| 329 | i2c_set_clientdata(client, NULL); | ||
| 330 | kfree(data); | ||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | static const struct i2c_device_id adt7411_id[] = { | ||
| 335 | { "adt7411", 0 }, | ||
| 336 | { } | ||
| 337 | }; | ||
| 338 | |||
| 339 | static struct i2c_driver adt7411_driver = { | ||
| 340 | .driver = { | ||
| 341 | .name = "adt7411", | ||
| 342 | }, | ||
| 343 | .probe = adt7411_probe, | ||
| 344 | .remove = __devexit_p(adt7411_remove), | ||
| 345 | .id_table = adt7411_id, | ||
| 346 | .detect = adt7411_detect, | ||
| 347 | .address_list = normal_i2c, | ||
| 348 | .class = I2C_CLASS_HWMON, | ||
| 349 | }; | ||
| 350 | |||
| 351 | static int __init sensors_adt7411_init(void) | ||
| 352 | { | ||
| 353 | return i2c_add_driver(&adt7411_driver); | ||
| 354 | } | ||
| 355 | module_init(sensors_adt7411_init) | ||
| 356 | |||
| 357 | static void __exit sensors_adt7411_exit(void) | ||
| 358 | { | ||
| 359 | i2c_del_driver(&adt7411_driver); | ||
| 360 | } | ||
| 361 | module_exit(sensors_adt7411_exit) | ||
| 362 | |||
| 363 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de> and " | ||
| 364 | "Wolfram Sang <w.sang@pengutronix.de>"); | ||
| 365 | MODULE_DESCRIPTION("ADT7411 driver"); | ||
| 366 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c deleted file mode 100644 index 434576f61c84..000000000000 --- a/drivers/hwmon/adt7473.c +++ /dev/null | |||
| @@ -1,1180 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * A hwmon driver for the Analog Devices ADT7473 | ||
| 3 | * Copyright (C) 2007 IBM | ||
| 4 | * | ||
| 5 | * Author: Darrick J. Wong <djwong@us.ibm.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/jiffies.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/hwmon.h> | ||
| 26 | #include <linux/hwmon-sysfs.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/mutex.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/log2.h> | ||
| 31 | |||
| 32 | /* Addresses to scan */ | ||
| 33 | static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, I2C_CLIENT_END }; | ||
| 34 | |||
| 35 | /* ADT7473 registers */ | ||
| 36 | #define ADT7473_REG_BASE_ADDR 0x20 | ||
| 37 | |||
| 38 | #define ADT7473_REG_VOLT_BASE_ADDR 0x21 | ||
| 39 | #define ADT7473_REG_VOLT_MIN_BASE_ADDR 0x46 | ||
| 40 | |||
| 41 | #define ADT7473_REG_TEMP_BASE_ADDR 0x25 | ||
| 42 | #define ADT7473_REG_TEMP_LIMITS_BASE_ADDR 0x4E | ||
| 43 | #define ADT7473_REG_TEMP_TMIN_BASE_ADDR 0x67 | ||
| 44 | #define ADT7473_REG_TEMP_TMAX_BASE_ADDR 0x6A | ||
| 45 | |||
| 46 | #define ADT7473_REG_FAN_BASE_ADDR 0x28 | ||
| 47 | #define ADT7473_REG_FAN_MIN_BASE_ADDR 0x54 | ||
| 48 | |||
| 49 | #define ADT7473_REG_PWM_BASE_ADDR 0x30 | ||
| 50 | #define ADT7473_REG_PWM_MIN_BASE_ADDR 0x64 | ||
| 51 | #define ADT7473_REG_PWM_MAX_BASE_ADDR 0x38 | ||
| 52 | #define ADT7473_REG_PWM_BHVR_BASE_ADDR 0x5C | ||
| 53 | #define ADT7473_PWM_BHVR_MASK 0xE0 | ||
| 54 | #define ADT7473_PWM_BHVR_SHIFT 5 | ||
| 55 | |||
| 56 | #define ADT7473_REG_CFG1 0x40 | ||
| 57 | #define ADT7473_CFG1_START 0x01 | ||
| 58 | #define ADT7473_CFG1_READY 0x04 | ||
| 59 | #define ADT7473_REG_CFG2 0x73 | ||
| 60 | #define ADT7473_REG_CFG3 0x78 | ||
| 61 | #define ADT7473_REG_CFG4 0x7D | ||
| 62 | #define ADT7473_CFG4_MAX_DUTY_AT_OVT 0x08 | ||
| 63 | #define ADT7473_REG_CFG5 0x7C | ||
| 64 | #define ADT7473_CFG5_TEMP_TWOS 0x01 | ||
| 65 | #define ADT7473_CFG5_TEMP_OFFSET 0x02 | ||
| 66 | |||
| 67 | #define ADT7473_REG_DEVICE 0x3D | ||
| 68 | #define ADT7473_VENDOR 0x41 | ||
| 69 | #define ADT7473_REG_VENDOR 0x3E | ||
| 70 | #define ADT7473_DEVICE 0x73 | ||
| 71 | #define ADT7473_REG_REVISION 0x3F | ||
| 72 | #define ADT7473_REV_68 0x68 | ||
| 73 | #define ADT7473_REV_69 0x69 | ||
| 74 | |||
| 75 | #define ADT7473_REG_ALARM1 0x41 | ||
| 76 | #define ADT7473_VCCP_ALARM 0x02 | ||
| 77 | #define ADT7473_VCC_ALARM 0x04 | ||
| 78 | #define ADT7473_R1T_ALARM 0x10 | ||
| 79 | #define ADT7473_LT_ALARM 0x20 | ||
| 80 | #define ADT7473_R2T_ALARM 0x40 | ||
| 81 | #define ADT7473_OOL 0x80 | ||
| 82 | #define ADT7473_REG_ALARM2 0x42 | ||
| 83 | #define ADT7473_OVT_ALARM 0x02 | ||
| 84 | #define ADT7473_FAN1_ALARM 0x04 | ||
| 85 | #define ADT7473_FAN2_ALARM 0x08 | ||
| 86 | #define ADT7473_FAN3_ALARM 0x10 | ||
| 87 | #define ADT7473_FAN4_ALARM 0x20 | ||
| 88 | #define ADT7473_R1T_SHORT 0x40 | ||
| 89 | #define ADT7473_R2T_SHORT 0x80 | ||
| 90 | |||
| 91 | #define ALARM2(x) ((x) << 8) | ||
| 92 | |||
| 93 | #define ADT7473_VOLT_COUNT 2 | ||
| 94 | #define ADT7473_REG_VOLT(x) (ADT7473_REG_VOLT_BASE_ADDR + (x)) | ||
| 95 | #define ADT7473_REG_VOLT_MIN(x) (ADT7473_REG_VOLT_MIN_BASE_ADDR + ((x) * 2)) | ||
| 96 | #define ADT7473_REG_VOLT_MAX(x) (ADT7473_REG_VOLT_MIN_BASE_ADDR + \ | ||
| 97 | ((x) * 2) + 1) | ||
| 98 | |||
| 99 | #define ADT7473_TEMP_COUNT 3 | ||
| 100 | #define ADT7473_REG_TEMP(x) (ADT7473_REG_TEMP_BASE_ADDR + (x)) | ||
| 101 | #define ADT7473_REG_TEMP_MIN(x) (ADT7473_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2)) | ||
| 102 | #define ADT7473_REG_TEMP_MAX(x) (ADT7473_REG_TEMP_LIMITS_BASE_ADDR + \ | ||
| 103 | ((x) * 2) + 1) | ||
| 104 | #define ADT7473_REG_TEMP_TMIN(x) (ADT7473_REG_TEMP_TMIN_BASE_ADDR + (x)) | ||
| 105 | #define ADT7473_REG_TEMP_TMAX(x) (ADT7473_REG_TEMP_TMAX_BASE_ADDR + (x)) | ||
| 106 | |||
| 107 | #define ADT7473_FAN_COUNT 4 | ||
| 108 | #define ADT7473_REG_FAN(x) (ADT7473_REG_FAN_BASE_ADDR + ((x) * 2)) | ||
| 109 | #define ADT7473_REG_FAN_MIN(x) (ADT7473_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) | ||
| 110 | |||
| 111 | #define ADT7473_PWM_COUNT 3 | ||
| 112 | #define ADT7473_REG_PWM(x) (ADT7473_REG_PWM_BASE_ADDR + (x)) | ||
| 113 | #define ADT7473_REG_PWM_MAX(x) (ADT7473_REG_PWM_MAX_BASE_ADDR + (x)) | ||
| 114 | #define ADT7473_REG_PWM_MIN(x) (ADT7473_REG_PWM_MIN_BASE_ADDR + (x)) | ||
| 115 | #define ADT7473_REG_PWM_BHVR(x) (ADT7473_REG_PWM_BHVR_BASE_ADDR + (x)) | ||
| 116 | |||
| 117 | /* How often do we reread sensors values? (In jiffies) */ | ||
| 118 | #define SENSOR_REFRESH_INTERVAL (2 * HZ) | ||
| 119 | |||
| 120 | /* How often do we reread sensor limit values? (In jiffies) */ | ||
| 121 | #define LIMIT_REFRESH_INTERVAL (60 * HZ) | ||
| 122 | |||
| 123 | /* datasheet says to divide this number by the fan reading to get fan rpm */ | ||
| 124 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | ||
| 125 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | ||
| 126 | #define FAN_PERIOD_INVALID 65535 | ||
| 127 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | ||
| 128 | |||
| 129 | struct adt7473_data { | ||
| 130 | struct device *hwmon_dev; | ||
| 131 | struct attribute_group attrs; | ||
| 132 | struct mutex lock; | ||
| 133 | char sensors_valid; | ||
| 134 | char limits_valid; | ||
| 135 | unsigned long sensors_last_updated; /* In jiffies */ | ||
| 136 | unsigned long limits_last_updated; /* In jiffies */ | ||
| 137 | |||
| 138 | u8 volt[ADT7473_VOLT_COUNT]; | ||
| 139 | s8 volt_min[ADT7473_VOLT_COUNT]; | ||
| 140 | s8 volt_max[ADT7473_VOLT_COUNT]; | ||
| 141 | |||
| 142 | s8 temp[ADT7473_TEMP_COUNT]; | ||
| 143 | s8 temp_min[ADT7473_TEMP_COUNT]; | ||
| 144 | s8 temp_max[ADT7473_TEMP_COUNT]; | ||
| 145 | s8 temp_tmin[ADT7473_TEMP_COUNT]; | ||
| 146 | /* This is called the !THERM limit in the datasheet */ | ||
| 147 | s8 temp_tmax[ADT7473_TEMP_COUNT]; | ||
| 148 | |||
| 149 | u16 fan[ADT7473_FAN_COUNT]; | ||
| 150 | u16 fan_min[ADT7473_FAN_COUNT]; | ||
| 151 | |||
| 152 | u8 pwm[ADT7473_PWM_COUNT]; | ||
| 153 | u8 pwm_max[ADT7473_PWM_COUNT]; | ||
| 154 | u8 pwm_min[ADT7473_PWM_COUNT]; | ||
| 155 | u8 pwm_behavior[ADT7473_PWM_COUNT]; | ||
| 156 | |||
| 157 | u8 temp_twos_complement; | ||
| 158 | u8 temp_offset; | ||
| 159 | |||
| 160 | u16 alarm; | ||
| 161 | u8 max_duty_at_overheat; | ||
| 162 | }; | ||
| 163 | |||
| 164 | static int adt7473_probe(struct i2c_client *client, | ||
| 165 | const struct i2c_device_id *id); | ||
| 166 | static int adt7473_detect(struct i2c_client *client, | ||
| 167 | struct i2c_board_info *info); | ||
| 168 | static int adt7473_remove(struct i2c_client *client); | ||
| 169 | |||
| 170 | static const struct i2c_device_id adt7473_id[] = { | ||
| 171 | { "adt7473", 0 }, | ||
| 172 | { } | ||
| 173 | }; | ||
| 174 | |||
| 175 | static struct i2c_driver adt7473_driver = { | ||
| 176 | .class = I2C_CLASS_HWMON, | ||
| 177 | .driver = { | ||
| 178 | .name = "adt7473", | ||
| 179 | }, | ||
| 180 | .probe = adt7473_probe, | ||
| 181 | .remove = adt7473_remove, | ||
| 182 | .id_table = adt7473_id, | ||
| 183 | .detect = adt7473_detect, | ||
| 184 | .address_list = normal_i2c, | ||
| 185 | }; | ||
| 186 | |||
| 187 | /* | ||
| 188 | * 16-bit registers on the ADT7473 are low-byte first. The data sheet says | ||
| 189 | * that the low byte must be read before the high byte. | ||
| 190 | */ | ||
| 191 | static inline int adt7473_read_word_data(struct i2c_client *client, u8 reg) | ||
| 192 | { | ||
| 193 | u16 foo; | ||
| 194 | foo = i2c_smbus_read_byte_data(client, reg); | ||
| 195 | foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); | ||
| 196 | return foo; | ||
| 197 | } | ||
| 198 | |||
| 199 | static inline int adt7473_write_word_data(struct i2c_client *client, u8 reg, | ||
| 200 | u16 value) | ||
| 201 | { | ||
| 202 | return i2c_smbus_write_byte_data(client, reg, value & 0xFF) | ||
| 203 | && i2c_smbus_write_byte_data(client, reg + 1, value >> 8); | ||
| 204 | } | ||
| 205 | |||
| 206 | static void adt7473_init_client(struct i2c_client *client) | ||
| 207 | { | ||
| 208 | int reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG1); | ||
| 209 | |||
| 210 | if (!(reg & ADT7473_CFG1_READY)) { | ||
| 211 | dev_err(&client->dev, "Chip not ready.\n"); | ||
| 212 | } else { | ||
| 213 | /* start monitoring */ | ||
| 214 | i2c_smbus_write_byte_data(client, ADT7473_REG_CFG1, | ||
| 215 | reg | ADT7473_CFG1_START); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | static struct adt7473_data *adt7473_update_device(struct device *dev) | ||
| 220 | { | ||
| 221 | struct i2c_client *client = to_i2c_client(dev); | ||
| 222 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 223 | unsigned long local_jiffies = jiffies; | ||
| 224 | u8 cfg; | ||
| 225 | int i; | ||
| 226 | |||
| 227 | mutex_lock(&data->lock); | ||
| 228 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
| 229 | SENSOR_REFRESH_INTERVAL) | ||
| 230 | && data->sensors_valid) | ||
| 231 | goto no_sensor_update; | ||
| 232 | |||
| 233 | for (i = 0; i < ADT7473_VOLT_COUNT; i++) | ||
| 234 | data->volt[i] = i2c_smbus_read_byte_data(client, | ||
| 235 | ADT7473_REG_VOLT(i)); | ||
| 236 | |||
| 237 | /* Determine temperature encoding */ | ||
| 238 | cfg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG5); | ||
| 239 | data->temp_twos_complement = (cfg & ADT7473_CFG5_TEMP_TWOS); | ||
| 240 | |||
| 241 | /* | ||
| 242 | * What does this do? it implies a variable temperature sensor | ||
| 243 | * offset, but the datasheet doesn't say anything about this bit | ||
| 244 | * and other parts of the datasheet imply that "offset64" mode | ||
| 245 | * means that you shift temp values by -64 if the above bit was set. | ||
| 246 | */ | ||
| 247 | data->temp_offset = (cfg & ADT7473_CFG5_TEMP_OFFSET); | ||
| 248 | |||
| 249 | for (i = 0; i < ADT7473_TEMP_COUNT; i++) | ||
| 250 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
| 251 | ADT7473_REG_TEMP(i)); | ||
| 252 | |||
| 253 | for (i = 0; i < ADT7473_FAN_COUNT; i++) | ||
| 254 | data->fan[i] = adt7473_read_word_data(client, | ||
| 255 | ADT7473_REG_FAN(i)); | ||
| 256 | |||
| 257 | for (i = 0; i < ADT7473_PWM_COUNT; i++) | ||
| 258 | data->pwm[i] = i2c_smbus_read_byte_data(client, | ||
| 259 | ADT7473_REG_PWM(i)); | ||
| 260 | |||
| 261 | data->alarm = i2c_smbus_read_byte_data(client, ADT7473_REG_ALARM1); | ||
| 262 | if (data->alarm & ADT7473_OOL) | ||
| 263 | data->alarm |= ALARM2(i2c_smbus_read_byte_data(client, | ||
| 264 | ADT7473_REG_ALARM2)); | ||
| 265 | |||
| 266 | data->sensors_last_updated = local_jiffies; | ||
| 267 | data->sensors_valid = 1; | ||
| 268 | |||
| 269 | no_sensor_update: | ||
| 270 | if (time_before(local_jiffies, data->limits_last_updated + | ||
| 271 | LIMIT_REFRESH_INTERVAL) | ||
| 272 | && data->limits_valid) | ||
| 273 | goto out; | ||
| 274 | |||
| 275 | for (i = 0; i < ADT7473_VOLT_COUNT; i++) { | ||
| 276 | data->volt_min[i] = i2c_smbus_read_byte_data(client, | ||
| 277 | ADT7473_REG_VOLT_MIN(i)); | ||
| 278 | data->volt_max[i] = i2c_smbus_read_byte_data(client, | ||
| 279 | ADT7473_REG_VOLT_MAX(i)); | ||
| 280 | } | ||
| 281 | |||
| 282 | for (i = 0; i < ADT7473_TEMP_COUNT; i++) { | ||
| 283 | data->temp_min[i] = i2c_smbus_read_byte_data(client, | ||
| 284 | ADT7473_REG_TEMP_MIN(i)); | ||
| 285 | data->temp_max[i] = i2c_smbus_read_byte_data(client, | ||
| 286 | ADT7473_REG_TEMP_MAX(i)); | ||
| 287 | data->temp_tmin[i] = i2c_smbus_read_byte_data(client, | ||
| 288 | ADT7473_REG_TEMP_TMIN(i)); | ||
| 289 | data->temp_tmax[i] = i2c_smbus_read_byte_data(client, | ||
| 290 | ADT7473_REG_TEMP_TMAX(i)); | ||
| 291 | } | ||
| 292 | |||
| 293 | for (i = 0; i < ADT7473_FAN_COUNT; i++) | ||
| 294 | data->fan_min[i] = adt7473_read_word_data(client, | ||
| 295 | ADT7473_REG_FAN_MIN(i)); | ||
| 296 | |||
| 297 | for (i = 0; i < ADT7473_PWM_COUNT; i++) { | ||
| 298 | data->pwm_max[i] = i2c_smbus_read_byte_data(client, | ||
| 299 | ADT7473_REG_PWM_MAX(i)); | ||
| 300 | data->pwm_min[i] = i2c_smbus_read_byte_data(client, | ||
| 301 | ADT7473_REG_PWM_MIN(i)); | ||
| 302 | data->pwm_behavior[i] = i2c_smbus_read_byte_data(client, | ||
| 303 | ADT7473_REG_PWM_BHVR(i)); | ||
| 304 | } | ||
| 305 | |||
| 306 | i = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG4); | ||
| 307 | data->max_duty_at_overheat = !!(i & ADT7473_CFG4_MAX_DUTY_AT_OVT); | ||
| 308 | |||
| 309 | data->limits_last_updated = local_jiffies; | ||
| 310 | data->limits_valid = 1; | ||
| 311 | |||
| 312 | out: | ||
| 313 | mutex_unlock(&data->lock); | ||
| 314 | return data; | ||
| 315 | } | ||
| 316 | |||
| 317 | /* | ||
| 318 | * Conversions | ||
| 319 | */ | ||
| 320 | |||
| 321 | /* IN are scaled acording to built-in resistors */ | ||
| 322 | static const int adt7473_scaling[] = { /* .001 Volts */ | ||
| 323 | 2250, 3300 | ||
| 324 | }; | ||
| 325 | #define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from)) | ||
| 326 | |||
| 327 | static int decode_volt(int volt_index, u8 raw) | ||
| 328 | { | ||
| 329 | return SCALE(raw, 192, adt7473_scaling[volt_index]); | ||
| 330 | } | ||
| 331 | |||
| 332 | static u8 encode_volt(int volt_index, int cooked) | ||
| 333 | { | ||
| 334 | int raw = SCALE(cooked, adt7473_scaling[volt_index], 192); | ||
| 335 | return SENSORS_LIMIT(raw, 0, 255); | ||
| 336 | } | ||
| 337 | |||
| 338 | static ssize_t show_volt_min(struct device *dev, | ||
| 339 | struct device_attribute *devattr, | ||
| 340 | char *buf) | ||
| 341 | { | ||
| 342 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 343 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 344 | return sprintf(buf, "%d\n", | ||
| 345 | decode_volt(attr->index, data->volt_min[attr->index])); | ||
| 346 | } | ||
| 347 | |||
| 348 | static ssize_t set_volt_min(struct device *dev, | ||
| 349 | struct device_attribute *devattr, | ||
| 350 | const char *buf, | ||
| 351 | size_t count) | ||
| 352 | { | ||
| 353 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 354 | struct i2c_client *client = to_i2c_client(dev); | ||
| 355 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 356 | long volt; | ||
| 357 | |||
| 358 | if (strict_strtol(buf, 10, &volt)) | ||
| 359 | return -EINVAL; | ||
| 360 | |||
| 361 | volt = encode_volt(attr->index, volt); | ||
| 362 | |||
| 363 | mutex_lock(&data->lock); | ||
| 364 | data->volt_min[attr->index] = volt; | ||
| 365 | i2c_smbus_write_byte_data(client, ADT7473_REG_VOLT_MIN(attr->index), | ||
| 366 | volt); | ||
| 367 | mutex_unlock(&data->lock); | ||
| 368 | |||
| 369 | return count; | ||
| 370 | } | ||
| 371 | |||
| 372 | static ssize_t show_volt_max(struct device *dev, | ||
| 373 | struct device_attribute *devattr, | ||
| 374 | char *buf) | ||
| 375 | { | ||
| 376 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 377 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 378 | return sprintf(buf, "%d\n", | ||
| 379 | decode_volt(attr->index, data->volt_max[attr->index])); | ||
| 380 | } | ||
| 381 | |||
| 382 | static ssize_t set_volt_max(struct device *dev, | ||
| 383 | struct device_attribute *devattr, | ||
| 384 | const char *buf, | ||
| 385 | size_t count) | ||
| 386 | { | ||
| 387 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 388 | struct i2c_client *client = to_i2c_client(dev); | ||
| 389 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 390 | long volt; | ||
| 391 | |||
| 392 | if (strict_strtol(buf, 10, &volt)) | ||
| 393 | return -EINVAL; | ||
| 394 | |||
| 395 | volt = encode_volt(attr->index, volt); | ||
| 396 | |||
| 397 | mutex_lock(&data->lock); | ||
| 398 | data->volt_max[attr->index] = volt; | ||
| 399 | i2c_smbus_write_byte_data(client, ADT7473_REG_VOLT_MAX(attr->index), | ||
| 400 | volt); | ||
| 401 | mutex_unlock(&data->lock); | ||
| 402 | |||
| 403 | return count; | ||
| 404 | } | ||
| 405 | |||
| 406 | static ssize_t show_volt(struct device *dev, struct device_attribute *devattr, | ||
| 407 | char *buf) | ||
| 408 | { | ||
| 409 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 410 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 411 | |||
| 412 | return sprintf(buf, "%d\n", | ||
| 413 | decode_volt(attr->index, data->volt[attr->index])); | ||
| 414 | } | ||
| 415 | |||
| 416 | /* | ||
| 417 | * This chip can report temperature data either as a two's complement | ||
| 418 | * number in the range -128 to 127, or as an unsigned number that must | ||
| 419 | * be offset by 64. | ||
| 420 | */ | ||
| 421 | static int decode_temp(u8 twos_complement, u8 raw) | ||
| 422 | { | ||
| 423 | return twos_complement ? (s8)raw : raw - 64; | ||
| 424 | } | ||
| 425 | |||
| 426 | static u8 encode_temp(u8 twos_complement, int cooked) | ||
| 427 | { | ||
| 428 | u8 ret = twos_complement ? cooked & 0xFF : cooked + 64; | ||
| 429 | return SENSORS_LIMIT(ret, 0, 255); | ||
| 430 | } | ||
| 431 | |||
| 432 | static ssize_t show_temp_min(struct device *dev, | ||
| 433 | struct device_attribute *devattr, | ||
| 434 | char *buf) | ||
| 435 | { | ||
| 436 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 437 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 438 | return sprintf(buf, "%d\n", 1000 * decode_temp( | ||
| 439 | data->temp_twos_complement, | ||
| 440 | data->temp_min[attr->index])); | ||
| 441 | } | ||
| 442 | |||
| 443 | static ssize_t set_temp_min(struct device *dev, | ||
| 444 | struct device_attribute *devattr, | ||
| 445 | const char *buf, | ||
| 446 | size_t count) | ||
| 447 | { | ||
| 448 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 449 | struct i2c_client *client = to_i2c_client(dev); | ||
| 450 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 451 | long temp; | ||
| 452 | |||
| 453 | if (strict_strtol(buf, 10, &temp)) | ||
| 454 | return -EINVAL; | ||
| 455 | |||
| 456 | temp = DIV_ROUND_CLOSEST(temp, 1000); | ||
| 457 | temp = encode_temp(data->temp_twos_complement, temp); | ||
| 458 | |||
| 459 | mutex_lock(&data->lock); | ||
| 460 | data->temp_min[attr->index] = temp; | ||
| 461 | i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_MIN(attr->index), | ||
| 462 | temp); | ||
| 463 | mutex_unlock(&data->lock); | ||
| 464 | |||
| 465 | return count; | ||
| 466 | } | ||
| 467 | |||
| 468 | static ssize_t show_temp_max(struct device *dev, | ||
| 469 | struct device_attribute *devattr, | ||
| 470 | char *buf) | ||
| 471 | { | ||
| 472 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 473 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 474 | return sprintf(buf, "%d\n", 1000 * decode_temp( | ||
| 475 | data->temp_twos_complement, | ||
| 476 | data->temp_max[attr->index])); | ||
| 477 | } | ||
| 478 | |||
| 479 | static ssize_t set_temp_max(struct device *dev, | ||
| 480 | struct device_attribute *devattr, | ||
| 481 | const char *buf, | ||
| 482 | size_t count) | ||
| 483 | { | ||
| 484 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 485 | struct i2c_client *client = to_i2c_client(dev); | ||
| 486 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 487 | long temp; | ||
| 488 | |||
| 489 | if (strict_strtol(buf, 10, &temp)) | ||
| 490 | return -EINVAL; | ||
| 491 | |||
| 492 | temp = DIV_ROUND_CLOSEST(temp, 1000); | ||
| 493 | temp = encode_temp(data->temp_twos_complement, temp); | ||
| 494 | |||
| 495 | mutex_lock(&data->lock); | ||
| 496 | data->temp_max[attr->index] = temp; | ||
| 497 | i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_MAX(attr->index), | ||
| 498 | temp); | ||
| 499 | mutex_unlock(&data->lock); | ||
| 500 | |||
| 501 | return count; | ||
| 502 | } | ||
| 503 | |||
| 504 | static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | ||
| 505 | char *buf) | ||
| 506 | { | ||
| 507 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 508 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 509 | return sprintf(buf, "%d\n", 1000 * decode_temp( | ||
| 510 | data->temp_twos_complement, | ||
| 511 | data->temp[attr->index])); | ||
| 512 | } | ||
| 513 | |||
| 514 | static ssize_t show_fan_min(struct device *dev, | ||
| 515 | struct device_attribute *devattr, | ||
| 516 | char *buf) | ||
| 517 | { | ||
| 518 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 519 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 520 | |||
| 521 | if (FAN_DATA_VALID(data->fan_min[attr->index])) | ||
| 522 | return sprintf(buf, "%d\n", | ||
| 523 | FAN_PERIOD_TO_RPM(data->fan_min[attr->index])); | ||
| 524 | else | ||
| 525 | return sprintf(buf, "0\n"); | ||
| 526 | } | ||
| 527 | |||
| 528 | static ssize_t set_fan_min(struct device *dev, | ||
| 529 | struct device_attribute *devattr, | ||
| 530 | const char *buf, size_t count) | ||
| 531 | { | ||
| 532 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 533 | struct i2c_client *client = to_i2c_client(dev); | ||
| 534 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 535 | long temp; | ||
| 536 | |||
| 537 | if (strict_strtol(buf, 10, &temp) || !temp) | ||
| 538 | return -EINVAL; | ||
| 539 | |||
| 540 | temp = FAN_RPM_TO_PERIOD(temp); | ||
| 541 | temp = SENSORS_LIMIT(temp, 1, 65534); | ||
| 542 | |||
| 543 | mutex_lock(&data->lock); | ||
| 544 | data->fan_min[attr->index] = temp; | ||
| 545 | adt7473_write_word_data(client, ADT7473_REG_FAN_MIN(attr->index), temp); | ||
| 546 | mutex_unlock(&data->lock); | ||
| 547 | |||
| 548 | return count; | ||
| 549 | } | ||
| 550 | |||
| 551 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | ||
| 552 | char *buf) | ||
| 553 | { | ||
| 554 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 555 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 556 | |||
| 557 | if (FAN_DATA_VALID(data->fan[attr->index])) | ||
| 558 | return sprintf(buf, "%d\n", | ||
| 559 | FAN_PERIOD_TO_RPM(data->fan[attr->index])); | ||
| 560 | else | ||
| 561 | return sprintf(buf, "0\n"); | ||
| 562 | } | ||
| 563 | |||
| 564 | static ssize_t show_max_duty_at_crit(struct device *dev, | ||
| 565 | struct device_attribute *devattr, | ||
| 566 | char *buf) | ||
| 567 | { | ||
| 568 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 569 | return sprintf(buf, "%d\n", data->max_duty_at_overheat); | ||
| 570 | } | ||
| 571 | |||
| 572 | static ssize_t set_max_duty_at_crit(struct device *dev, | ||
| 573 | struct device_attribute *devattr, | ||
| 574 | const char *buf, | ||
| 575 | size_t count) | ||
| 576 | { | ||
| 577 | u8 reg; | ||
| 578 | struct i2c_client *client = to_i2c_client(dev); | ||
| 579 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 580 | long temp; | ||
| 581 | |||
| 582 | if (strict_strtol(buf, 10, &temp)) | ||
| 583 | return -EINVAL; | ||
| 584 | |||
| 585 | mutex_lock(&data->lock); | ||
| 586 | data->max_duty_at_overheat = !!temp; | ||
| 587 | reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG4); | ||
| 588 | if (temp) | ||
| 589 | reg |= ADT7473_CFG4_MAX_DUTY_AT_OVT; | ||
| 590 | else | ||
| 591 | reg &= ~ADT7473_CFG4_MAX_DUTY_AT_OVT; | ||
| 592 | i2c_smbus_write_byte_data(client, ADT7473_REG_CFG4, reg); | ||
| 593 | mutex_unlock(&data->lock); | ||
| 594 | |||
| 595 | return count; | ||
| 596 | } | ||
| 597 | |||
| 598 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | ||
| 599 | char *buf) | ||
| 600 | { | ||
| 601 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 602 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 603 | return sprintf(buf, "%d\n", data->pwm[attr->index]); | ||
| 604 | } | ||
| 605 | |||
| 606 | static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, | ||
| 607 | const char *buf, size_t count) | ||
| 608 | { | ||
| 609 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 610 | struct i2c_client *client = to_i2c_client(dev); | ||
| 611 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 612 | long temp; | ||
| 613 | |||
| 614 | if (strict_strtol(buf, 10, &temp)) | ||
| 615 | return -EINVAL; | ||
| 616 | |||
| 617 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 618 | |||
| 619 | mutex_lock(&data->lock); | ||
| 620 | data->pwm[attr->index] = temp; | ||
| 621 | i2c_smbus_write_byte_data(client, ADT7473_REG_PWM(attr->index), temp); | ||
| 622 | mutex_unlock(&data->lock); | ||
| 623 | |||
| 624 | return count; | ||
| 625 | } | ||
| 626 | |||
| 627 | static ssize_t show_pwm_max(struct device *dev, | ||
| 628 | struct device_attribute *devattr, | ||
| 629 | char *buf) | ||
| 630 | { | ||
| 631 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 632 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 633 | return sprintf(buf, "%d\n", data->pwm_max[attr->index]); | ||
| 634 | } | ||
| 635 | |||
| 636 | static ssize_t set_pwm_max(struct device *dev, | ||
| 637 | struct device_attribute *devattr, | ||
| 638 | const char *buf, | ||
| 639 | size_t count) | ||
| 640 | { | ||
| 641 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 642 | struct i2c_client *client = to_i2c_client(dev); | ||
| 643 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 644 | long temp; | ||
| 645 | |||
| 646 | if (strict_strtol(buf, 10, &temp)) | ||
| 647 | return -EINVAL; | ||
| 648 | |||
| 649 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 650 | |||
| 651 | mutex_lock(&data->lock); | ||
| 652 | data->pwm_max[attr->index] = temp; | ||
| 653 | i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_MAX(attr->index), | ||
| 654 | temp); | ||
| 655 | mutex_unlock(&data->lock); | ||
| 656 | |||
| 657 | return count; | ||
| 658 | } | ||
| 659 | |||
| 660 | static ssize_t show_pwm_min(struct device *dev, | ||
| 661 | struct device_attribute *devattr, | ||
| 662 | char *buf) | ||
| 663 | { | ||
| 664 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 665 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 666 | return sprintf(buf, "%d\n", data->pwm_min[attr->index]); | ||
| 667 | } | ||
| 668 | |||
| 669 | static ssize_t set_pwm_min(struct device *dev, | ||
| 670 | struct device_attribute *devattr, | ||
| 671 | const char *buf, | ||
| 672 | size_t count) | ||
| 673 | { | ||
| 674 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 675 | struct i2c_client *client = to_i2c_client(dev); | ||
| 676 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 677 | long temp; | ||
| 678 | |||
| 679 | if (strict_strtol(buf, 10, &temp)) | ||
| 680 | return -EINVAL; | ||
| 681 | |||
| 682 | temp = SENSORS_LIMIT(temp, 0, 255); | ||
| 683 | |||
| 684 | mutex_lock(&data->lock); | ||
| 685 | data->pwm_min[attr->index] = temp; | ||
| 686 | i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_MIN(attr->index), | ||
| 687 | temp); | ||
| 688 | mutex_unlock(&data->lock); | ||
| 689 | |||
| 690 | return count; | ||
| 691 | } | ||
| 692 | |||
| 693 | static ssize_t show_temp_tmax(struct device *dev, | ||
| 694 | struct device_attribute *devattr, | ||
| 695 | char *buf) | ||
| 696 | { | ||
| 697 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 698 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 699 | return sprintf(buf, "%d\n", 1000 * decode_temp( | ||
| 700 | data->temp_twos_complement, | ||
| 701 | data->temp_tmax[attr->index])); | ||
| 702 | } | ||
| 703 | |||
| 704 | static ssize_t set_temp_tmax(struct device *dev, | ||
| 705 | struct device_attribute *devattr, | ||
| 706 | const char *buf, | ||
| 707 | size_t count) | ||
| 708 | { | ||
| 709 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 710 | struct i2c_client *client = to_i2c_client(dev); | ||
| 711 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 712 | long temp; | ||
| 713 | |||
| 714 | if (strict_strtol(buf, 10, &temp)) | ||
| 715 | return -EINVAL; | ||
| 716 | |||
| 717 | temp = DIV_ROUND_CLOSEST(temp, 1000); | ||
| 718 | temp = encode_temp(data->temp_twos_complement, temp); | ||
| 719 | |||
| 720 | mutex_lock(&data->lock); | ||
| 721 | data->temp_tmax[attr->index] = temp; | ||
| 722 | i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_TMAX(attr->index), | ||
| 723 | temp); | ||
| 724 | mutex_unlock(&data->lock); | ||
| 725 | |||
| 726 | return count; | ||
| 727 | } | ||
| 728 | |||
| 729 | static ssize_t show_temp_tmin(struct device *dev, | ||
| 730 | struct device_attribute *devattr, | ||
| 731 | char *buf) | ||
| 732 | { | ||
| 733 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 734 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 735 | return sprintf(buf, "%d\n", 1000 * decode_temp( | ||
| 736 | data->temp_twos_complement, | ||
| 737 | data->temp_tmin[attr->index])); | ||
| 738 | } | ||
| 739 | |||
| 740 | static ssize_t set_temp_tmin(struct device *dev, | ||
| 741 | struct device_attribute *devattr, | ||
| 742 | const char *buf, | ||
| 743 | size_t count) | ||
| 744 | { | ||
| 745 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 746 | struct i2c_client *client = to_i2c_client(dev); | ||
| 747 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 748 | long temp; | ||
| 749 | |||
| 750 | if (strict_strtol(buf, 10, &temp)) | ||
| 751 | return -EINVAL; | ||
| 752 | |||
| 753 | temp = DIV_ROUND_CLOSEST(temp, 1000); | ||
| 754 | temp = encode_temp(data->temp_twos_complement, temp); | ||
| 755 | |||
| 756 | mutex_lock(&data->lock); | ||
| 757 | data->temp_tmin[attr->index] = temp; | ||
| 758 | i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_TMIN(attr->index), | ||
| 759 | temp); | ||
| 760 | mutex_unlock(&data->lock); | ||
| 761 | |||
| 762 | return count; | ||
| 763 | } | ||
| 764 | |||
| 765 | static ssize_t show_pwm_enable(struct device *dev, | ||
| 766 | struct device_attribute *devattr, | ||
| 767 | char *buf) | ||
| 768 | { | ||
| 769 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 770 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 771 | |||
| 772 | switch (data->pwm_behavior[attr->index] >> ADT7473_PWM_BHVR_SHIFT) { | ||
| 773 | case 3: | ||
| 774 | return sprintf(buf, "0\n"); | ||
| 775 | case 7: | ||
| 776 | return sprintf(buf, "1\n"); | ||
| 777 | default: | ||
| 778 | return sprintf(buf, "2\n"); | ||
| 779 | } | ||
| 780 | } | ||
| 781 | |||
| 782 | static ssize_t set_pwm_enable(struct device *dev, | ||
| 783 | struct device_attribute *devattr, | ||
| 784 | const char *buf, | ||
| 785 | size_t count) | ||
| 786 | { | ||
| 787 | u8 reg; | ||
| 788 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 789 | struct i2c_client *client = to_i2c_client(dev); | ||
| 790 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 791 | long temp; | ||
| 792 | |||
| 793 | if (strict_strtol(buf, 10, &temp)) | ||
| 794 | return -EINVAL; | ||
| 795 | |||
| 796 | switch (temp) { | ||
| 797 | case 0: | ||
| 798 | temp = 3; | ||
| 799 | break; | ||
| 800 | case 1: | ||
| 801 | temp = 7; | ||
| 802 | break; | ||
| 803 | case 2: | ||
| 804 | /* Enter automatic mode with fans off */ | ||
| 805 | temp = 4; | ||
| 806 | break; | ||
| 807 | default: | ||
| 808 | return -EINVAL; | ||
| 809 | } | ||
| 810 | |||
| 811 | mutex_lock(&data->lock); | ||
| 812 | reg = i2c_smbus_read_byte_data(client, | ||
| 813 | ADT7473_REG_PWM_BHVR(attr->index)); | ||
| 814 | reg = (temp << ADT7473_PWM_BHVR_SHIFT) | | ||
| 815 | (reg & ~ADT7473_PWM_BHVR_MASK); | ||
| 816 | i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_BHVR(attr->index), | ||
| 817 | reg); | ||
| 818 | data->pwm_behavior[attr->index] = reg; | ||
| 819 | mutex_unlock(&data->lock); | ||
| 820 | |||
| 821 | return count; | ||
| 822 | } | ||
| 823 | |||
| 824 | static ssize_t show_pwm_auto_temp(struct device *dev, | ||
| 825 | struct device_attribute *devattr, | ||
| 826 | char *buf) | ||
| 827 | { | ||
| 828 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 829 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 830 | int bhvr = data->pwm_behavior[attr->index] >> ADT7473_PWM_BHVR_SHIFT; | ||
| 831 | |||
| 832 | switch (bhvr) { | ||
| 833 | case 3: | ||
| 834 | case 4: | ||
| 835 | case 7: | ||
| 836 | return sprintf(buf, "0\n"); | ||
| 837 | case 0: | ||
| 838 | case 1: | ||
| 839 | case 5: | ||
| 840 | case 6: | ||
| 841 | return sprintf(buf, "%d\n", bhvr + 1); | ||
| 842 | case 2: | ||
| 843 | return sprintf(buf, "4\n"); | ||
| 844 | } | ||
| 845 | /* shouldn't ever get here */ | ||
| 846 | BUG(); | ||
| 847 | } | ||
| 848 | |||
| 849 | static ssize_t set_pwm_auto_temp(struct device *dev, | ||
| 850 | struct device_attribute *devattr, | ||
| 851 | const char *buf, | ||
| 852 | size_t count) | ||
| 853 | { | ||
| 854 | u8 reg; | ||
| 855 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 856 | struct i2c_client *client = to_i2c_client(dev); | ||
| 857 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 858 | long temp; | ||
| 859 | |||
| 860 | if (strict_strtol(buf, 10, &temp)) | ||
| 861 | return -EINVAL; | ||
| 862 | |||
| 863 | switch (temp) { | ||
| 864 | case 1: | ||
| 865 | case 2: | ||
| 866 | case 6: | ||
| 867 | case 7: | ||
| 868 | temp--; | ||
| 869 | break; | ||
| 870 | case 0: | ||
| 871 | temp = 4; | ||
| 872 | break; | ||
| 873 | default: | ||
| 874 | return -EINVAL; | ||
| 875 | } | ||
| 876 | |||
| 877 | mutex_lock(&data->lock); | ||
| 878 | reg = i2c_smbus_read_byte_data(client, | ||
| 879 | ADT7473_REG_PWM_BHVR(attr->index)); | ||
| 880 | reg = (temp << ADT7473_PWM_BHVR_SHIFT) | | ||
| 881 | (reg & ~ADT7473_PWM_BHVR_MASK); | ||
| 882 | i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_BHVR(attr->index), | ||
| 883 | reg); | ||
| 884 | data->pwm_behavior[attr->index] = reg; | ||
| 885 | mutex_unlock(&data->lock); | ||
| 886 | |||
| 887 | return count; | ||
| 888 | } | ||
| 889 | |||
| 890 | static ssize_t show_alarm(struct device *dev, | ||
| 891 | struct device_attribute *devattr, | ||
| 892 | char *buf) | ||
| 893 | { | ||
| 894 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
| 895 | struct adt7473_data *data = adt7473_update_device(dev); | ||
| 896 | |||
| 897 | if (data->alarm & attr->index) | ||
| 898 | return sprintf(buf, "1\n"); | ||
| 899 | else | ||
| 900 | return sprintf(buf, "0\n"); | ||
| 901 | } | ||
| 902 | |||
| 903 | |||
| 904 | static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 905 | set_volt_max, 0); | ||
| 906 | static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max, | ||
| 907 | set_volt_max, 1); | ||
| 908 | |||
| 909 | static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 910 | set_volt_min, 0); | ||
| 911 | static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min, | ||
| 912 | set_volt_min, 1); | ||
| 913 | |||
| 914 | static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_volt, NULL, 0); | ||
| 915 | static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_volt, NULL, 1); | ||
| 916 | |||
| 917 | static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, | ||
| 918 | ADT7473_VCCP_ALARM); | ||
| 919 | static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, | ||
| 920 | ADT7473_VCC_ALARM); | ||
| 921 | |||
| 922 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 923 | set_temp_max, 0); | ||
| 924 | static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 925 | set_temp_max, 1); | ||
| 926 | static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, | ||
| 927 | set_temp_max, 2); | ||
| 928 | |||
| 929 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 930 | set_temp_min, 0); | ||
| 931 | static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 932 | set_temp_min, 1); | ||
| 933 | static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, | ||
| 934 | set_temp_min, 2); | ||
| 935 | |||
| 936 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); | ||
| 937 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); | ||
| 938 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); | ||
| 939 | |||
| 940 | static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, | ||
| 941 | ADT7473_R1T_ALARM | ALARM2(ADT7473_R1T_SHORT)); | ||
| 942 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, | ||
| 943 | ADT7473_LT_ALARM); | ||
| 944 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, | ||
| 945 | ADT7473_R2T_ALARM | ALARM2(ADT7473_R2T_SHORT)); | ||
| 946 | |||
| 947 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 948 | set_fan_min, 0); | ||
| 949 | static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 950 | set_fan_min, 1); | ||
| 951 | static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 952 | set_fan_min, 2); | ||
| 953 | static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, | ||
| 954 | set_fan_min, 3); | ||
| 955 | |||
| 956 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | ||
| 957 | static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); | ||
| 958 | static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); | ||
| 959 | static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); | ||
| 960 | |||
| 961 | static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, | ||
| 962 | ALARM2(ADT7473_FAN1_ALARM)); | ||
| 963 | static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, | ||
| 964 | ALARM2(ADT7473_FAN2_ALARM)); | ||
| 965 | static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, | ||
| 966 | ALARM2(ADT7473_FAN3_ALARM)); | ||
| 967 | static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, | ||
| 968 | ALARM2(ADT7473_FAN4_ALARM)); | ||
| 969 | |||
| 970 | static SENSOR_DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO, | ||
| 971 | show_max_duty_at_crit, set_max_duty_at_crit, 0); | ||
| 972 | |||
| 973 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); | ||
| 974 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); | ||
| 975 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); | ||
| 976 | |||
| 977 | static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 978 | show_pwm_min, set_pwm_min, 0); | ||
| 979 | static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 980 | show_pwm_min, set_pwm_min, 1); | ||
| 981 | static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, | ||
| 982 | show_pwm_min, set_pwm_min, 2); | ||
| 983 | |||
| 984 | static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 985 | show_pwm_max, set_pwm_max, 0); | ||
| 986 | static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 987 | show_pwm_max, set_pwm_max, 1); | ||
| 988 | static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, | ||
| 989 | show_pwm_max, set_pwm_max, 2); | ||
| 990 | |||
| 991 | static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 992 | show_temp_tmin, set_temp_tmin, 0); | ||
| 993 | static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 994 | show_temp_tmin, set_temp_tmin, 1); | ||
| 995 | static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO, | ||
| 996 | show_temp_tmin, set_temp_tmin, 2); | ||
| 997 | |||
| 998 | static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 999 | show_temp_tmax, set_temp_tmax, 0); | ||
| 1000 | static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 1001 | show_temp_tmax, set_temp_tmax, 1); | ||
| 1002 | static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO, | ||
| 1003 | show_temp_tmax, set_temp_tmax, 2); | ||
| 1004 | |||
| 1005 | static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
| 1006 | set_pwm_enable, 0); | ||
| 1007 | static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
| 1008 | set_pwm_enable, 1); | ||
| 1009 | static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable, | ||
| 1010 | set_pwm_enable, 2); | ||
| 1011 | |||
| 1012 | static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1013 | show_pwm_auto_temp, set_pwm_auto_temp, 0); | ||
| 1014 | static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1015 | show_pwm_auto_temp, set_pwm_auto_temp, 1); | ||
| 1016 | static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, | ||
| 1017 | show_pwm_auto_temp, set_pwm_auto_temp, 2); | ||
| 1018 | |||
| 1019 | static struct attribute *adt7473_attr[] = | ||
| 1020 | { | ||
| 1021 | &sensor_dev_attr_in1_max.dev_attr.attr, | ||
| 1022 | &sensor_dev_attr_in2_max.dev_attr.attr, | ||
| 1023 | &sensor_dev_attr_in1_min.dev_attr.attr, | ||
| 1024 | &sensor_dev_attr_in2_min.dev_attr.attr, | ||
| 1025 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
| 1026 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
| 1027 | &sensor_dev_attr_in1_alarm.dev_attr.attr, | ||
| 1028 | &sensor_dev_attr_in2_alarm.dev_attr.attr, | ||
| 1029 | |||
| 1030 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
| 1031 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
| 1032 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
| 1033 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
| 1034 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
| 1035 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
| 1036 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
| 1037 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
| 1038 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
| 1039 | &sensor_dev_attr_temp1_alarm.dev_attr.attr, | ||
| 1040 | &sensor_dev_attr_temp2_alarm.dev_attr.attr, | ||
| 1041 | &sensor_dev_attr_temp3_alarm.dev_attr.attr, | ||
| 1042 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | ||
| 1043 | &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, | ||
| 1044 | &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, | ||
| 1045 | &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, | ||
| 1046 | &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, | ||
| 1047 | &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, | ||
| 1048 | |||
| 1049 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
| 1050 | &sensor_dev_attr_fan2_min.dev_attr.attr, | ||
| 1051 | &sensor_dev_attr_fan3_min.dev_attr.attr, | ||
| 1052 | &sensor_dev_attr_fan4_min.dev_attr.attr, | ||
| 1053 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
| 1054 | &sensor_dev_attr_fan2_input.dev_attr.attr, | ||
| 1055 | &sensor_dev_attr_fan3_input.dev_attr.attr, | ||
| 1056 | &sensor_dev_attr_fan4_input.dev_attr.attr, | ||
| 1057 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
| 1058 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
| 1059 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
| 1060 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
| 1061 | |||
| 1062 | &sensor_dev_attr_pwm_use_point2_pwm_at_crit.dev_attr.attr, | ||
| 1063 | |||
| 1064 | &sensor_dev_attr_pwm1.dev_attr.attr, | ||
| 1065 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
| 1066 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 1067 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | ||
| 1068 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | ||
| 1069 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | ||
| 1070 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | ||
| 1071 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | ||
| 1072 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | ||
| 1073 | |||
| 1074 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
| 1075 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
| 1076 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
| 1077 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | ||
| 1078 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | ||
| 1079 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | ||
| 1080 | |||
| 1081 | NULL | ||
| 1082 | }; | ||
| 1083 | |||
| 1084 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
| 1085 | static int adt7473_detect(struct i2c_client *client, | ||
| 1086 | struct i2c_board_info *info) | ||
| 1087 | { | ||
| 1088 | struct i2c_adapter *adapter = client->adapter; | ||
| 1089 | int vendor, device, revision; | ||
| 1090 | |||
| 1091 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 1092 | return -ENODEV; | ||
| 1093 | |||
| 1094 | vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR); | ||
| 1095 | if (vendor != ADT7473_VENDOR) | ||
| 1096 | return -ENODEV; | ||
| 1097 | |||
| 1098 | device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE); | ||
| 1099 | if (device != ADT7473_DEVICE) | ||
| 1100 | return -ENODEV; | ||
| 1101 | |||
| 1102 | revision = i2c_smbus_read_byte_data(client, ADT7473_REG_REVISION); | ||
| 1103 | if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) | ||
| 1104 | return -ENODEV; | ||
| 1105 | |||
| 1106 | strlcpy(info->type, "adt7473", I2C_NAME_SIZE); | ||
| 1107 | |||
| 1108 | return 0; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static int adt7473_probe(struct i2c_client *client, | ||
| 1112 | const struct i2c_device_id *id) | ||
| 1113 | { | ||
| 1114 | struct adt7473_data *data; | ||
| 1115 | int err; | ||
| 1116 | |||
| 1117 | data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL); | ||
| 1118 | if (!data) { | ||
| 1119 | err = -ENOMEM; | ||
| 1120 | goto exit; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | i2c_set_clientdata(client, data); | ||
| 1124 | mutex_init(&data->lock); | ||
| 1125 | |||
| 1126 | dev_info(&client->dev, "%s chip found\n", client->name); | ||
| 1127 | |||
| 1128 | /* Initialize the ADT7473 chip */ | ||
| 1129 | adt7473_init_client(client); | ||
| 1130 | |||
| 1131 | /* Register sysfs hooks */ | ||
| 1132 | data->attrs.attrs = adt7473_attr; | ||
| 1133 | err = sysfs_create_group(&client->dev.kobj, &data->attrs); | ||
| 1134 | if (err) | ||
| 1135 | goto exit_free; | ||
| 1136 | |||
| 1137 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
| 1138 | if (IS_ERR(data->hwmon_dev)) { | ||
| 1139 | err = PTR_ERR(data->hwmon_dev); | ||
| 1140 | goto exit_remove; | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | return 0; | ||
| 1144 | |||
| 1145 | exit_remove: | ||
| 1146 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 1147 | exit_free: | ||
| 1148 | kfree(data); | ||
| 1149 | exit: | ||
| 1150 | return err; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | static int adt7473_remove(struct i2c_client *client) | ||
| 1154 | { | ||
| 1155 | struct adt7473_data *data = i2c_get_clientdata(client); | ||
| 1156 | |||
| 1157 | hwmon_device_unregister(data->hwmon_dev); | ||
| 1158 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | ||
| 1159 | kfree(data); | ||
| 1160 | return 0; | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | static int __init adt7473_init(void) | ||
| 1164 | { | ||
| 1165 | pr_notice("The adt7473 driver is deprecated, please use the adt7475 " | ||
| 1166 | "driver instead\n"); | ||
| 1167 | return i2c_add_driver(&adt7473_driver); | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | static void __exit adt7473_exit(void) | ||
| 1171 | { | ||
| 1172 | i2c_del_driver(&adt7473_driver); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); | ||
| 1176 | MODULE_DESCRIPTION("ADT7473 driver"); | ||
| 1177 | MODULE_LICENSE("GPL"); | ||
| 1178 | |||
| 1179 | module_init(adt7473_init); | ||
| 1180 | module_exit(adt7473_exit); | ||
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c new file mode 100644 index 000000000000..7f948105d8ad --- /dev/null +++ b/drivers/hwmon/asc7621.c | |||
| @@ -0,0 +1,1255 @@ | |||
| 1 | /* | ||
| 2 | * asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring | ||
| 3 | * Copyright (c) 2007, 2010 George Joseph <george.joseph@fairview5.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/jiffies.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/hwmon.h> | ||
| 26 | #include <linux/hwmon-sysfs.h> | ||
| 27 | #include <linux/err.h> | ||
| 28 | #include <linux/mutex.h> | ||
| 29 | |||
| 30 | /* Addresses to scan */ | ||
| 31 | static unsigned short normal_i2c[] = { | ||
| 32 | 0x2c, 0x2d, 0x2e, I2C_CLIENT_END | ||
| 33 | }; | ||
| 34 | |||
| 35 | enum asc7621_type { | ||
| 36 | asc7621, | ||
| 37 | asc7621a | ||
| 38 | }; | ||
| 39 | |||
| 40 | #define INTERVAL_HIGH (HZ + HZ / 2) | ||
| 41 | #define INTERVAL_LOW (1 * 60 * HZ) | ||
| 42 | #define PRI_NONE 0 | ||
| 43 | #define PRI_LOW 1 | ||
| 44 | #define PRI_HIGH 2 | ||
| 45 | #define FIRST_CHIP asc7621 | ||
| 46 | #define LAST_CHIP asc7621a | ||
| 47 | |||
| 48 | struct asc7621_chip { | ||
| 49 | char *name; | ||
| 50 | enum asc7621_type chip_type; | ||
| 51 | u8 company_reg; | ||
| 52 | u8 company_id; | ||
| 53 | u8 verstep_reg; | ||
| 54 | u8 verstep_id; | ||
| 55 | unsigned short *addresses; | ||
| 56 | }; | ||
| 57 | |||
| 58 | static struct asc7621_chip asc7621_chips[] = { | ||
| 59 | { | ||
| 60 | .name = "asc7621", | ||
| 61 | .chip_type = asc7621, | ||
| 62 | .company_reg = 0x3e, | ||
| 63 | .company_id = 0x61, | ||
| 64 | .verstep_reg = 0x3f, | ||
| 65 | .verstep_id = 0x6c, | ||
| 66 | .addresses = normal_i2c, | ||
| 67 | }, | ||
| 68 | { | ||
| 69 | .name = "asc7621a", | ||
| 70 | .chip_type = asc7621a, | ||
| 71 | .company_reg = 0x3e, | ||
| 72 | .company_id = 0x61, | ||
| 73 | .verstep_reg = 0x3f, | ||
| 74 | .verstep_id = 0x6d, | ||
| 75 | .addresses = normal_i2c, | ||
| 76 | }, | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* | ||
| 80 | * Defines the highest register to be used, not the count. | ||
| 81 | * The actual count will probably be smaller because of gaps | ||
| 82 | * in the implementation (unused register locations). | ||
| 83 | * This define will safely set the array size of both the parameter | ||
| 84 | * and data arrays. | ||
| 85 | * This comes from the data sheet register description table. | ||
| 86 | */ | ||
| 87 | #define LAST_REGISTER 0xff | ||
| 88 | |||
| 89 | struct asc7621_data { | ||
| 90 | struct i2c_client client; | ||
| 91 | struct device *class_dev; | ||
| 92 | struct mutex update_lock; | ||
| 93 | int valid; /* !=0 if following fields are valid */ | ||
| 94 | unsigned long last_high_reading; /* In jiffies */ | ||
| 95 | unsigned long last_low_reading; /* In jiffies */ | ||
| 96 | /* | ||
| 97 | * Registers we care about occupy the corresponding index | ||
| 98 | * in the array. Registers we don't care about are left | ||
| 99 | * at 0. | ||
| 100 | */ | ||
| 101 | u8 reg[LAST_REGISTER + 1]; | ||
| 102 | }; | ||
| 103 | |||
| 104 | /* | ||
| 105 | * Macro to get the parent asc7621_param structure | ||
| 106 | * from a sensor_device_attribute passed into the | ||
| 107 | * show/store functions. | ||
| 108 | */ | ||
| 109 | #define to_asc7621_param(_sda) \ | ||
| 110 | container_of(_sda, struct asc7621_param, sda) | ||
| 111 | |||
| 112 | /* | ||
| 113 | * Each parameter to be retrieved needs an asc7621_param structure | ||
| 114 | * allocated. It contains the sensor_device_attribute structure | ||
| 115 | * and the control info needed to retrieve the value from the register map. | ||
| 116 | */ | ||
| 117 | struct asc7621_param { | ||
| 118 | struct sensor_device_attribute sda; | ||
| 119 | u8 priority; | ||
| 120 | u8 msb[3]; | ||
| 121 | u8 lsb[3]; | ||
| 122 | u8 mask[3]; | ||
| 123 | u8 shift[3]; | ||
| 124 | }; | ||
| 125 | |||
| 126 | /* | ||
| 127 | * This is the map that ultimately indicates whether we'll be | ||
| 128 | * retrieving a register value or not, and at what frequency. | ||
| 129 | */ | ||
| 130 | static u8 asc7621_register_priorities[255]; | ||
| 131 | |||
| 132 | static struct asc7621_data *asc7621_update_device(struct device *dev); | ||
| 133 | |||
| 134 | static inline u8 read_byte(struct i2c_client *client, u8 reg) | ||
| 135 | { | ||
| 136 | int res = i2c_smbus_read_byte_data(client, reg); | ||
| 137 | if (res < 0) { | ||
| 138 | dev_err(&client->dev, | ||
| 139 | "Unable to read from register 0x%02x.\n", reg); | ||
| 140 | return 0; | ||
| 141 | }; | ||
| 142 | return res & 0xff; | ||
| 143 | } | ||
| 144 | |||
| 145 | static inline int write_byte(struct i2c_client *client, u8 reg, u8 data) | ||
| 146 | { | ||
| 147 | int res = i2c_smbus_write_byte_data(client, reg, data); | ||
| 148 | if (res < 0) { | ||
| 149 | dev_err(&client->dev, | ||
| 150 | "Unable to write value 0x%02x to register 0x%02x.\n", | ||
| 151 | data, reg); | ||
| 152 | }; | ||
| 153 | return res; | ||
| 154 | } | ||
| 155 | |||
| 156 | /* | ||
| 157 | * Data Handlers | ||
| 158 | * Each function handles the formatting, storage | ||
| 159 | * and retrieval of like parameters. | ||
| 160 | */ | ||
| 161 | |||
| 162 | #define SETUP_SHOW_data_param(d, a) \ | ||
| 163 | struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ | ||
| 164 | struct asc7621_data *data = asc7621_update_device(d); \ | ||
| 165 | struct asc7621_param *param = to_asc7621_param(sda) | ||
| 166 | |||
| 167 | #define SETUP_STORE_data_param(d, a) \ | ||
| 168 | struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ | ||
| 169 | struct i2c_client *client = to_i2c_client(d); \ | ||
| 170 | struct asc7621_data *data = i2c_get_clientdata(client); \ | ||
| 171 | struct asc7621_param *param = to_asc7621_param(sda) | ||
| 172 | |||
| 173 | /* | ||
| 174 | * u8 is just what it sounds like...an unsigned byte with no | ||
| 175 | * special formatting. | ||
| 176 | */ | ||
| 177 | static ssize_t show_u8(struct device *dev, struct device_attribute *attr, | ||
| 178 | char *buf) | ||
| 179 | { | ||
| 180 | SETUP_SHOW_data_param(dev, attr); | ||
| 181 | |||
| 182 | return sprintf(buf, "%u\n", data->reg[param->msb[0]]); | ||
| 183 | } | ||
| 184 | |||
| 185 | static ssize_t store_u8(struct device *dev, struct device_attribute *attr, | ||
| 186 | const char *buf, size_t count) | ||
| 187 | { | ||
| 188 | SETUP_STORE_data_param(dev, attr); | ||
| 189 | long reqval; | ||
| 190 | |||
| 191 | if (strict_strtol(buf, 10, &reqval)) | ||
| 192 | return -EINVAL; | ||
| 193 | |||
| 194 | reqval = SENSORS_LIMIT(reqval, 0, 255); | ||
| 195 | |||
| 196 | mutex_lock(&data->update_lock); | ||
| 197 | data->reg[param->msb[0]] = reqval; | ||
| 198 | write_byte(client, param->msb[0], reqval); | ||
| 199 | mutex_unlock(&data->update_lock); | ||
| 200 | return count; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * Many of the config values occupy only a few bits of a register. | ||
| 205 | */ | ||
| 206 | static ssize_t show_bitmask(struct device *dev, | ||
| 207 | struct device_attribute *attr, char *buf) | ||
| 208 | { | ||
| 209 | SETUP_SHOW_data_param(dev, attr); | ||
| 210 | |||
| 211 | return sprintf(buf, "%u\n", | ||
| 212 | (data->reg[param->msb[0]] >> param-> | ||
| 213 | shift[0]) & param->mask[0]); | ||
| 214 | } | ||
| 215 | |||
| 216 | static ssize_t store_bitmask(struct device *dev, | ||
| 217 | struct device_attribute *attr, | ||
| 218 | const char *buf, size_t count) | ||
| 219 | { | ||
| 220 | SETUP_STORE_data_param(dev, attr); | ||
| 221 | long reqval; | ||
| 222 | u8 currval; | ||
| 223 | |||
| 224 | if (strict_strtol(buf, 10, &reqval)) | ||
| 225 | return -EINVAL; | ||
| 226 | |||
| 227 | reqval = SENSORS_LIMIT(reqval, 0, param->mask[0]); | ||
| 228 | |||
| 229 | reqval = (reqval & param->mask[0]) << param->shift[0]; | ||
| 230 | |||
| 231 | mutex_lock(&data->update_lock); | ||
| 232 | currval = read_byte(client, param->msb[0]); | ||
| 233 | reqval |= (currval & ~(param->mask[0] << param->shift[0])); | ||
| 234 | data->reg[param->msb[0]] = reqval; | ||
| 235 | write_byte(client, param->msb[0], reqval); | ||
| 236 | mutex_unlock(&data->update_lock); | ||
| 237 | return count; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* | ||
| 241 | * 16 bit fan rpm values | ||
| 242 | * reported by the device as the number of 11.111us periods (90khz) | ||
| 243 | * between full fan rotations. Therefore... | ||
| 244 | * RPM = (90000 * 60) / register value | ||
| 245 | */ | ||
| 246 | static ssize_t show_fan16(struct device *dev, | ||
| 247 | struct device_attribute *attr, char *buf) | ||
| 248 | { | ||
| 249 | SETUP_SHOW_data_param(dev, attr); | ||
| 250 | u16 regval; | ||
| 251 | |||
| 252 | mutex_lock(&data->update_lock); | ||
| 253 | regval = (data->reg[param->msb[0]] << 8) | data->reg[param->lsb[0]]; | ||
| 254 | mutex_unlock(&data->update_lock); | ||
| 255 | |||
| 256 | return sprintf(buf, "%u\n", | ||
| 257 | (regval == 0 ? -1 : (regval) == | ||
| 258 | 0xffff ? 0 : 5400000 / regval)); | ||
| 259 | } | ||
| 260 | |||
| 261 | static ssize_t store_fan16(struct device *dev, | ||
| 262 | struct device_attribute *attr, const char *buf, | ||
| 263 | size_t count) | ||
| 264 | { | ||
| 265 | SETUP_STORE_data_param(dev, attr); | ||
| 266 | long reqval; | ||
| 267 | |||
| 268 | if (strict_strtol(buf, 10, &reqval)) | ||
| 269 | return -EINVAL; | ||
| 270 | |||
| 271 | reqval = | ||
| 272 | (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534)); | ||
| 273 | |||
| 274 | mutex_lock(&data->update_lock); | ||
| 275 | data->reg[param->msb[0]] = (reqval >> 8) & 0xff; | ||
| 276 | data->reg[param->lsb[0]] = reqval & 0xff; | ||
| 277 | write_byte(client, param->msb[0], data->reg[param->msb[0]]); | ||
| 278 | write_byte(client, param->lsb[0], data->reg[param->lsb[0]]); | ||
| 279 | mutex_unlock(&data->update_lock); | ||
| 280 | |||
| 281 | return count; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* | ||
| 285 | * Voltages are scaled in the device so that the nominal voltage | ||
| 286 | * is 3/4ths of the 0-255 range (i.e. 192). | ||
| 287 | * If all voltages are 'normal' then all voltage registers will | ||
| 288 | * read 0xC0. This doesn't help us if we don't have a point of refernce. | ||
| 289 | * The data sheet however provides us with the full scale value for each | ||
| 290 | * which is stored in in_scaling. The sda->index parameter value provides | ||
| 291 | * the index into in_scaling. | ||
| 292 | * | ||
| 293 | * NOTE: The chip expects the first 2 inputs be 2.5 and 2.25 volts | ||
| 294 | * respectively. That doesn't mean that's what the motherboard provides. :) | ||
| 295 | */ | ||
| 296 | |||
| 297 | static int asc7621_in_scaling[] = { | ||
| 298 | 3320, 3000, 4380, 6640, 16000 | ||
| 299 | }; | ||
| 300 | |||
| 301 | static ssize_t show_in10(struct device *dev, struct device_attribute *attr, | ||
| 302 | char *buf) | ||
| 303 | { | ||
| 304 | SETUP_SHOW_data_param(dev, attr); | ||
| 305 | u16 regval; | ||
| 306 | u8 nr = sda->index; | ||
| 307 | |||
| 308 | mutex_lock(&data->update_lock); | ||
| 309 | regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256; | ||
| 310 | |||
| 311 | /* The LSB value is a 2-bit scaling of the MSB's LSbit value. | ||
| 312 | * I.E. If the maximim voltage for this input is 6640 millivolts then | ||
| 313 | * a MSB register value of 0 = 0mv and 255 = 6640mv. | ||
| 314 | * A 1 step change therefore represents 25.9mv (6640 / 256). | ||
| 315 | * The extra 2-bits therefore represent increments of 6.48mv. | ||
| 316 | */ | ||
| 317 | regval += ((asc7621_in_scaling[nr] / 256) / 4) * | ||
| 318 | (data->reg[param->lsb[0]] >> 6); | ||
| 319 | |||
| 320 | mutex_unlock(&data->update_lock); | ||
| 321 | |||
| 322 | return sprintf(buf, "%u\n", regval); | ||
| 323 | } | ||
| 324 | |||
| 325 | /* 8 bit voltage values (the mins and maxs) */ | ||
| 326 | static ssize_t show_in8(struct device *dev, struct device_attribute *attr, | ||
| 327 | char *buf) | ||
| 328 | { | ||
| 329 | SETUP_SHOW_data_param(dev, attr); | ||
| 330 | u8 nr = sda->index; | ||
| 331 | |||
| 332 | return sprintf(buf, "%u\n", | ||
| 333 | ((data->reg[param->msb[0]] * | ||
| 334 | asc7621_in_scaling[nr]) / 256)); | ||
| 335 | } | ||
| 336 | |||
| 337 | static ssize_t store_in8(struct device *dev, struct device_attribute *attr, | ||
| 338 | const char *buf, size_t count) | ||
| 339 | { | ||
| 340 | SETUP_STORE_data_param(dev, attr); | ||
| 341 | long reqval; | ||
| 342 | u8 nr = sda->index; | ||
| 343 | |||
| 344 | if (strict_strtol(buf, 10, &reqval)) | ||
| 345 | return -EINVAL; | ||
| 346 | |||
| 347 | reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]); | ||
| 348 | |||
| 349 | reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr]; | ||
| 350 | |||
| 351 | mutex_lock(&data->update_lock); | ||
| 352 | data->reg[param->msb[0]] = reqval; | ||
| 353 | write_byte(client, param->msb[0], reqval); | ||
| 354 | mutex_unlock(&data->update_lock); | ||
| 355 | |||
| 356 | return count; | ||
| 357 | } | ||
| 358 | |||
| 359 | static ssize_t show_temp8(struct device *dev, | ||
| 360 | struct device_attribute *attr, char *buf) | ||
| 361 | { | ||
| 362 | SETUP_SHOW_data_param(dev, attr); | ||
| 363 | |||
| 364 | return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000); | ||
| 365 | } | ||
| 366 | |||
| 367 | static ssize_t store_temp8(struct device *dev, | ||
| 368 | struct device_attribute *attr, const char *buf, | ||
| 369 | size_t count) | ||
| 370 | { | ||
| 371 | SETUP_STORE_data_param(dev, attr); | ||
| 372 | long reqval; | ||
| 373 | s8 temp; | ||
| 374 | |||
| 375 | if (strict_strtol(buf, 10, &reqval)) | ||
| 376 | return -EINVAL; | ||
| 377 | |||
| 378 | reqval = SENSORS_LIMIT(reqval, -127000, 127000); | ||
| 379 | |||
| 380 | temp = reqval / 1000; | ||
| 381 | |||
| 382 | mutex_lock(&data->update_lock); | ||
| 383 | data->reg[param->msb[0]] = temp; | ||
| 384 | write_byte(client, param->msb[0], temp); | ||
| 385 | mutex_unlock(&data->update_lock); | ||
| 386 | return count; | ||
| 387 | } | ||
| 388 | |||
| 389 | /* | ||
| 390 | * Temperatures that occupy 2 bytes always have the whole | ||
| 391 | * number of degrees in the MSB with some part of the LSB | ||
| 392 | * indicating fractional degrees. | ||
| 393 | */ | ||
| 394 | |||
| 395 | /* mmmmmmmm.llxxxxxx */ | ||
| 396 | static ssize_t show_temp10(struct device *dev, | ||
| 397 | struct device_attribute *attr, char *buf) | ||
| 398 | { | ||
| 399 | SETUP_SHOW_data_param(dev, attr); | ||
| 400 | u8 msb, lsb; | ||
| 401 | int temp; | ||
| 402 | |||
| 403 | mutex_lock(&data->update_lock); | ||
| 404 | msb = data->reg[param->msb[0]]; | ||
| 405 | lsb = (data->reg[param->lsb[0]] >> 6) & 0x03; | ||
| 406 | temp = (((s8) msb) * 1000) + (lsb * 250); | ||
| 407 | mutex_unlock(&data->update_lock); | ||
| 408 | |||
| 409 | return sprintf(buf, "%d\n", temp); | ||
| 410 | } | ||
| 411 | |||
| 412 | /* mmmmmm.ll */ | ||
| 413 | static ssize_t show_temp62(struct device *dev, | ||
| 414 | struct device_attribute *attr, char *buf) | ||
| 415 | { | ||
| 416 | SETUP_SHOW_data_param(dev, attr); | ||
| 417 | u8 regval = data->reg[param->msb[0]]; | ||
| 418 | int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250); | ||
| 419 | |||
| 420 | return sprintf(buf, "%d\n", temp); | ||
| 421 | } | ||
| 422 | |||
| 423 | static ssize_t store_temp62(struct device *dev, | ||
| 424 | struct device_attribute *attr, const char *buf, | ||
| 425 | size_t count) | ||
| 426 | { | ||
| 427 | SETUP_STORE_data_param(dev, attr); | ||
| 428 | long reqval, i, f; | ||
| 429 | s8 temp; | ||
| 430 | |||
| 431 | if (strict_strtol(buf, 10, &reqval)) | ||
| 432 | return -EINVAL; | ||
| 433 | |||
| 434 | reqval = SENSORS_LIMIT(reqval, -32000, 31750); | ||
| 435 | i = reqval / 1000; | ||
| 436 | f = reqval - (i * 1000); | ||
| 437 | temp = i << 2; | ||
| 438 | temp |= f / 250; | ||
| 439 | |||
| 440 | mutex_lock(&data->update_lock); | ||
| 441 | data->reg[param->msb[0]] = temp; | ||
| 442 | write_byte(client, param->msb[0], temp); | ||
| 443 | mutex_unlock(&data->update_lock); | ||
| 444 | return count; | ||
| 445 | } | ||
| 446 | |||
| 447 | /* | ||
| 448 | * The aSC7621 doesn't provide an "auto_point2". Instead, you | ||
| 449 | * specify the auto_point1 and a range. To keep with the sysfs | ||
| 450 | * hwmon specs, we synthesize the auto_point_2 from them. | ||
| 451 | */ | ||
| 452 | |||
| 453 | static u32 asc7621_range_map[] = { | ||
| 454 | 2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000, | ||
| 455 | 13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000, | ||
| 456 | }; | ||
| 457 | |||
| 458 | static ssize_t show_ap2_temp(struct device *dev, | ||
| 459 | struct device_attribute *attr, char *buf) | ||
| 460 | { | ||
| 461 | SETUP_SHOW_data_param(dev, attr); | ||
| 462 | long auto_point1; | ||
| 463 | u8 regval; | ||
| 464 | int temp; | ||
| 465 | |||
| 466 | mutex_lock(&data->update_lock); | ||
| 467 | auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000; | ||
| 468 | regval = | ||
| 469 | ((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]); | ||
| 470 | temp = auto_point1 + asc7621_range_map[SENSORS_LIMIT(regval, 0, 15)]; | ||
| 471 | mutex_unlock(&data->update_lock); | ||
| 472 | |||
| 473 | return sprintf(buf, "%d\n", temp); | ||
| 474 | |||
| 475 | } | ||
| 476 | |||
| 477 | static ssize_t store_ap2_temp(struct device *dev, | ||
| 478 | struct device_attribute *attr, | ||
| 479 | const char *buf, size_t count) | ||
| 480 | { | ||
| 481 | SETUP_STORE_data_param(dev, attr); | ||
| 482 | long reqval, auto_point1; | ||
| 483 | int i; | ||
| 484 | u8 currval, newval = 0; | ||
| 485 | |||
| 486 | if (strict_strtol(buf, 10, &reqval)) | ||
| 487 | return -EINVAL; | ||
| 488 | |||
| 489 | mutex_lock(&data->update_lock); | ||
| 490 | auto_point1 = data->reg[param->msb[1]] * 1000; | ||
| 491 | reqval = SENSORS_LIMIT(reqval, auto_point1 + 2000, auto_point1 + 80000); | ||
| 492 | |||
| 493 | for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) { | ||
| 494 | if (reqval >= auto_point1 + asc7621_range_map[i]) { | ||
| 495 | newval = i; | ||
| 496 | break; | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | newval = (newval & param->mask[0]) << param->shift[0]; | ||
| 501 | currval = read_byte(client, param->msb[0]); | ||
| 502 | newval |= (currval & ~(param->mask[0] << param->shift[0])); | ||
| 503 | data->reg[param->msb[0]] = newval; | ||
| 504 | write_byte(client, param->msb[0], newval); | ||
| 505 | mutex_unlock(&data->update_lock); | ||
| 506 | return count; | ||
| 507 | } | ||
| 508 | |||
| 509 | static ssize_t show_pwm_ac(struct device *dev, | ||
| 510 | struct device_attribute *attr, char *buf) | ||
| 511 | { | ||
| 512 | SETUP_SHOW_data_param(dev, attr); | ||
| 513 | u8 config, altbit, regval; | ||
| 514 | u8 map[] = { | ||
| 515 | 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10, | ||
| 516 | 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f | ||
| 517 | }; | ||
| 518 | |||
| 519 | mutex_lock(&data->update_lock); | ||
| 520 | config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; | ||
| 521 | altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; | ||
| 522 | regval = config | (altbit << 3); | ||
| 523 | mutex_unlock(&data->update_lock); | ||
| 524 | |||
| 525 | return sprintf(buf, "%u\n", map[SENSORS_LIMIT(regval, 0, 15)]); | ||
| 526 | } | ||
| 527 | |||
| 528 | static ssize_t store_pwm_ac(struct device *dev, | ||
| 529 | struct device_attribute *attr, | ||
| 530 | const char *buf, size_t count) | ||
| 531 | { | ||
| 532 | SETUP_STORE_data_param(dev, attr); | ||
| 533 | unsigned long reqval; | ||
| 534 | u8 currval, config, altbit, newval; | ||
| 535 | u16 map[] = { | ||
| 536 | 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06, | ||
| 537 | 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, | ||
| 538 | 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 539 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, | ||
| 540 | }; | ||
| 541 | |||
| 542 | if (strict_strtoul(buf, 10, &reqval)) | ||
| 543 | return -EINVAL; | ||
| 544 | |||
| 545 | if (reqval > 31) | ||
| 546 | return -EINVAL; | ||
| 547 | |||
| 548 | reqval = map[reqval]; | ||
| 549 | if (reqval == 0xff) | ||
| 550 | return -EINVAL; | ||
| 551 | |||
| 552 | config = reqval & 0x07; | ||
| 553 | altbit = (reqval >> 3) & 0x01; | ||
| 554 | |||
| 555 | config = (config & param->mask[0]) << param->shift[0]; | ||
| 556 | altbit = (altbit & param->mask[1]) << param->shift[1]; | ||
| 557 | |||
| 558 | mutex_lock(&data->update_lock); | ||
| 559 | currval = read_byte(client, param->msb[0]); | ||
| 560 | newval = config | (currval & ~(param->mask[0] << param->shift[0])); | ||
| 561 | newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); | ||
| 562 | data->reg[param->msb[0]] = newval; | ||
| 563 | write_byte(client, param->msb[0], newval); | ||
| 564 | mutex_unlock(&data->update_lock); | ||
| 565 | return count; | ||
| 566 | } | ||
| 567 | |||
| 568 | static ssize_t show_pwm_enable(struct device *dev, | ||
| 569 | struct device_attribute *attr, char *buf) | ||
| 570 | { | ||
| 571 | SETUP_SHOW_data_param(dev, attr); | ||
| 572 | u8 config, altbit, minoff, val, newval; | ||
| 573 | |||
| 574 | mutex_lock(&data->update_lock); | ||
| 575 | config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; | ||
| 576 | altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; | ||
| 577 | minoff = (data->reg[param->msb[2]] >> param->shift[2]) & param->mask[2]; | ||
| 578 | mutex_unlock(&data->update_lock); | ||
| 579 | |||
| 580 | val = config | (altbit << 3); | ||
| 581 | newval = 0; | ||
| 582 | |||
| 583 | if (val == 3 || val >= 10) | ||
| 584 | newval = 255; | ||
| 585 | else if (val == 4) | ||
| 586 | newval = 0; | ||
| 587 | else if (val == 7) | ||
| 588 | newval = 1; | ||
| 589 | else if (minoff == 1) | ||
| 590 | newval = 2; | ||
| 591 | else | ||
| 592 | newval = 3; | ||
| 593 | |||
| 594 | return sprintf(buf, "%u\n", newval); | ||
| 595 | } | ||
| 596 | |||
| 597 | static ssize_t store_pwm_enable(struct device *dev, | ||
| 598 | struct device_attribute *attr, | ||
| 599 | const char *buf, size_t count) | ||
| 600 | { | ||
| 601 | SETUP_STORE_data_param(dev, attr); | ||
| 602 | long reqval; | ||
| 603 | u8 currval, config, altbit, newval, minoff = 255; | ||
| 604 | |||
| 605 | if (strict_strtol(buf, 10, &reqval)) | ||
| 606 | return -EINVAL; | ||
| 607 | |||
| 608 | switch (reqval) { | ||
| 609 | case 0: | ||
| 610 | newval = 0x04; | ||
| 611 | break; | ||
| 612 | case 1: | ||
| 613 | newval = 0x07; | ||
| 614 | break; | ||
| 615 | case 2: | ||
| 616 | newval = 0x00; | ||
| 617 | minoff = 1; | ||
| 618 | break; | ||
| 619 | case 3: | ||
| 620 | newval = 0x00; | ||
| 621 | minoff = 0; | ||
| 622 | break; | ||
| 623 | case 255: | ||
| 624 | newval = 0x03; | ||
| 625 | break; | ||
| 626 | default: | ||
| 627 | return -EINVAL; | ||
| 628 | } | ||
| 629 | |||
| 630 | config = newval & 0x07; | ||
| 631 | altbit = (newval >> 3) & 0x01; | ||
| 632 | |||
| 633 | mutex_lock(&data->update_lock); | ||
| 634 | config = (config & param->mask[0]) << param->shift[0]; | ||
| 635 | altbit = (altbit & param->mask[1]) << param->shift[1]; | ||
| 636 | currval = read_byte(client, param->msb[0]); | ||
| 637 | newval = config | (currval & ~(param->mask[0] << param->shift[0])); | ||
| 638 | newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); | ||
| 639 | data->reg[param->msb[0]] = newval; | ||
| 640 | write_byte(client, param->msb[0], newval); | ||
| 641 | if (minoff < 255) { | ||
| 642 | minoff = (minoff & param->mask[2]) << param->shift[2]; | ||
| 643 | currval = read_byte(client, param->msb[2]); | ||
| 644 | newval = | ||
| 645 | minoff | (currval & ~(param->mask[2] << param->shift[2])); | ||
| 646 | data->reg[param->msb[2]] = newval; | ||
| 647 | write_byte(client, param->msb[2], newval); | ||
| 648 | } | ||
| 649 | mutex_unlock(&data->update_lock); | ||
| 650 | return count; | ||
| 651 | } | ||
| 652 | |||
| 653 | static u32 asc7621_pwm_freq_map[] = { | ||
| 654 | 10, 15, 23, 30, 38, 47, 62, 94, | ||
| 655 | 23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000 | ||
| 656 | }; | ||
| 657 | |||
| 658 | static ssize_t show_pwm_freq(struct device *dev, | ||
| 659 | struct device_attribute *attr, char *buf) | ||
| 660 | { | ||
| 661 | SETUP_SHOW_data_param(dev, attr); | ||
| 662 | u8 regval = | ||
| 663 | (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; | ||
| 664 | |||
| 665 | regval = SENSORS_LIMIT(regval, 0, 15); | ||
| 666 | |||
| 667 | return sprintf(buf, "%u\n", asc7621_pwm_freq_map[regval]); | ||
| 668 | } | ||
| 669 | |||
| 670 | static ssize_t store_pwm_freq(struct device *dev, | ||
| 671 | struct device_attribute *attr, | ||
| 672 | const char *buf, size_t count) | ||
| 673 | { | ||
| 674 | SETUP_STORE_data_param(dev, attr); | ||
| 675 | unsigned long reqval; | ||
| 676 | u8 currval, newval = 255; | ||
| 677 | int i; | ||
| 678 | |||
| 679 | if (strict_strtoul(buf, 10, &reqval)) | ||
| 680 | return -EINVAL; | ||
| 681 | |||
| 682 | for (i = 0; i < ARRAY_SIZE(asc7621_pwm_freq_map); i++) { | ||
| 683 | if (reqval == asc7621_pwm_freq_map[i]) { | ||
| 684 | newval = i; | ||
| 685 | break; | ||
| 686 | } | ||
| 687 | } | ||
| 688 | if (newval == 255) | ||
| 689 | return -EINVAL; | ||
| 690 | |||
| 691 | newval = (newval & param->mask[0]) << param->shift[0]; | ||
| 692 | |||
| 693 | mutex_lock(&data->update_lock); | ||
| 694 | currval = read_byte(client, param->msb[0]); | ||
| 695 | newval |= (currval & ~(param->mask[0] << param->shift[0])); | ||
| 696 | data->reg[param->msb[0]] = newval; | ||
| 697 | write_byte(client, param->msb[0], newval); | ||
| 698 | mutex_unlock(&data->update_lock); | ||
| 699 | return count; | ||
| 700 | } | ||
| 701 | |||
| 702 | static u32 asc7621_pwm_auto_spinup_map[] = { | ||
| 703 | 0, 100, 250, 400, 700, 1000, 2000, 4000 | ||
| 704 | }; | ||
| 705 | |||
| 706 | static ssize_t show_pwm_ast(struct device *dev, | ||
| 707 | struct device_attribute *attr, char *buf) | ||
| 708 | { | ||
| 709 | SETUP_SHOW_data_param(dev, attr); | ||
| 710 | u8 regval = | ||
| 711 | (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; | ||
| 712 | |||
| 713 | regval = SENSORS_LIMIT(regval, 0, 7); | ||
| 714 | |||
| 715 | return sprintf(buf, "%u\n", asc7621_pwm_auto_spinup_map[regval]); | ||
| 716 | |||
| 717 | } | ||
| 718 | |||
| 719 | static ssize_t store_pwm_ast(struct device *dev, | ||
| 720 | struct device_attribute *attr, | ||
| 721 | const char *buf, size_t count) | ||
| 722 | { | ||
| 723 | SETUP_STORE_data_param(dev, attr); | ||
| 724 | long reqval; | ||
| 725 | u8 currval, newval = 255; | ||
| 726 | u32 i; | ||
| 727 | |||
| 728 | if (strict_strtol(buf, 10, &reqval)) | ||
| 729 | return -EINVAL; | ||
| 730 | |||
| 731 | for (i = 0; i < ARRAY_SIZE(asc7621_pwm_auto_spinup_map); i++) { | ||
| 732 | if (reqval == asc7621_pwm_auto_spinup_map[i]) { | ||
| 733 | newval = i; | ||
| 734 | break; | ||
| 735 | } | ||
| 736 | } | ||
| 737 | if (newval == 255) | ||
| 738 | return -EINVAL; | ||
| 739 | |||
| 740 | newval = (newval & param->mask[0]) << param->shift[0]; | ||
| 741 | |||
| 742 | mutex_lock(&data->update_lock); | ||
| 743 | currval = read_byte(client, param->msb[0]); | ||
| 744 | newval |= (currval & ~(param->mask[0] << param->shift[0])); | ||
| 745 | data->reg[param->msb[0]] = newval; | ||
| 746 | write_byte(client, param->msb[0], newval); | ||
| 747 | mutex_unlock(&data->update_lock); | ||
| 748 | return count; | ||
| 749 | } | ||
| 750 | |||
| 751 | static u32 asc7621_temp_smoothing_time_map[] = { | ||
| 752 | 35000, 17600, 11800, 7000, 4400, 3000, 1600, 800 | ||
| 753 | }; | ||
| 754 | |||
| 755 | static ssize_t show_temp_st(struct device *dev, | ||
| 756 | struct device_attribute *attr, char *buf) | ||
| 757 | { | ||
| 758 | SETUP_SHOW_data_param(dev, attr); | ||
| 759 | u8 regval = | ||
| 760 | (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; | ||
| 761 | regval = SENSORS_LIMIT(regval, 0, 7); | ||
| 762 | |||
| 763 | return sprintf(buf, "%u\n", asc7621_temp_smoothing_time_map[regval]); | ||
| 764 | } | ||
| 765 | |||
| 766 | static ssize_t store_temp_st(struct device *dev, | ||
| 767 | struct device_attribute *attr, | ||
| 768 | const char *buf, size_t count) | ||
| 769 | { | ||
| 770 | SETUP_STORE_data_param(dev, attr); | ||
| 771 | long reqval; | ||
| 772 | u8 currval, newval = 255; | ||
| 773 | u32 i; | ||
| 774 | |||
| 775 | if (strict_strtol(buf, 10, &reqval)) | ||
| 776 | return -EINVAL; | ||
| 777 | |||
| 778 | for (i = 0; i < ARRAY_SIZE(asc7621_temp_smoothing_time_map); i++) { | ||
| 779 | if (reqval == asc7621_temp_smoothing_time_map[i]) { | ||
| 780 | newval = i; | ||
| 781 | break; | ||
| 782 | } | ||
| 783 | } | ||
| 784 | |||
| 785 | if (newval == 255) | ||
| 786 | return -EINVAL; | ||
| 787 | |||
| 788 | newval = (newval & param->mask[0]) << param->shift[0]; | ||
| 789 | |||
| 790 | mutex_lock(&data->update_lock); | ||
| 791 | currval = read_byte(client, param->msb[0]); | ||
| 792 | newval |= (currval & ~(param->mask[0] << param->shift[0])); | ||
| 793 | data->reg[param->msb[0]] = newval; | ||
| 794 | write_byte(client, param->msb[0], newval); | ||
| 795 | mutex_unlock(&data->update_lock); | ||
| 796 | return count; | ||
| 797 | } | ||
| 798 | |||
| 799 | /* | ||
| 800 | * End of data handlers | ||
| 801 | * | ||
| 802 | * These defines do nothing more than make the table easier | ||
| 803 | * to read when wrapped at column 80. | ||
| 804 | */ | ||
| 805 | |||
| 806 | /* | ||
| 807 | * Creates a variable length array inititalizer. | ||
| 808 | * VAA(1,3,5,7) would produce {1,3,5,7} | ||
| 809 | */ | ||
| 810 | #define VAA(args...) {args} | ||
| 811 | |||
| 812 | #define PREAD(name, n, pri, rm, rl, m, s, r) \ | ||
| 813 | {.sda = SENSOR_ATTR(name, S_IRUGO, show_##r, NULL, n), \ | ||
| 814 | .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ | ||
| 815 | .shift[0] = s,} | ||
| 816 | |||
| 817 | #define PWRITE(name, n, pri, rm, rl, m, s, r) \ | ||
| 818 | {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ | ||
| 819 | .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ | ||
| 820 | .shift[0] = s,} | ||
| 821 | |||
| 822 | /* | ||
| 823 | * PWRITEM assumes that the initializers for the .msb, .lsb, .mask and .shift | ||
| 824 | * were created using the VAA macro. | ||
| 825 | */ | ||
| 826 | #define PWRITEM(name, n, pri, rm, rl, m, s, r) \ | ||
| 827 | {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ | ||
| 828 | .priority = pri, .msb = rm, .lsb = rl, .mask = m, .shift = s,} | ||
| 829 | |||
| 830 | static struct asc7621_param asc7621_params[] = { | ||
| 831 | PREAD(in0_input, 0, PRI_HIGH, 0x20, 0x13, 0, 0, in10), | ||
| 832 | PREAD(in1_input, 1, PRI_HIGH, 0x21, 0x18, 0, 0, in10), | ||
| 833 | PREAD(in2_input, 2, PRI_HIGH, 0x22, 0x11, 0, 0, in10), | ||
| 834 | PREAD(in3_input, 3, PRI_HIGH, 0x23, 0x12, 0, 0, in10), | ||
| 835 | PREAD(in4_input, 4, PRI_HIGH, 0x24, 0x14, 0, 0, in10), | ||
| 836 | |||
| 837 | PWRITE(in0_min, 0, PRI_LOW, 0x44, 0, 0, 0, in8), | ||
| 838 | PWRITE(in1_min, 1, PRI_LOW, 0x46, 0, 0, 0, in8), | ||
| 839 | PWRITE(in2_min, 2, PRI_LOW, 0x48, 0, 0, 0, in8), | ||
| 840 | PWRITE(in3_min, 3, PRI_LOW, 0x4a, 0, 0, 0, in8), | ||
| 841 | PWRITE(in4_min, 4, PRI_LOW, 0x4c, 0, 0, 0, in8), | ||
| 842 | |||
| 843 | PWRITE(in0_max, 0, PRI_LOW, 0x45, 0, 0, 0, in8), | ||
| 844 | PWRITE(in1_max, 1, PRI_LOW, 0x47, 0, 0, 0, in8), | ||
| 845 | PWRITE(in2_max, 2, PRI_LOW, 0x49, 0, 0, 0, in8), | ||
| 846 | PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), | ||
| 847 | PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), | ||
| 848 | |||
| 849 | PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask), | ||
| 850 | PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask), | ||
| 851 | PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask), | ||
| 852 | PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask), | ||
| 853 | PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), | ||
| 854 | |||
| 855 | PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), | ||
| 856 | PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), | ||
| 857 | PREAD(fan3_input, 2, PRI_HIGH, 0x2d, 0x2c, 0, 0, fan16), | ||
| 858 | PREAD(fan4_input, 3, PRI_HIGH, 0x2f, 0x2e, 0, 0, fan16), | ||
| 859 | |||
| 860 | PWRITE(fan1_min, 0, PRI_LOW, 0x55, 0x54, 0, 0, fan16), | ||
| 861 | PWRITE(fan2_min, 1, PRI_LOW, 0x57, 0x56, 0, 0, fan16), | ||
| 862 | PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), | ||
| 863 | PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), | ||
| 864 | |||
| 865 | PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), | ||
| 866 | PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask), | ||
| 867 | PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask), | ||
| 868 | PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask), | ||
| 869 | |||
| 870 | PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), | ||
| 871 | PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), | ||
| 872 | PREAD(temp3_input, 2, PRI_HIGH, 0x27, 0x16, 0, 0, temp10), | ||
| 873 | PREAD(temp4_input, 3, PRI_HIGH, 0x33, 0x17, 0, 0, temp10), | ||
| 874 | PREAD(temp5_input, 4, PRI_HIGH, 0xf7, 0xf6, 0, 0, temp10), | ||
| 875 | PREAD(temp6_input, 5, PRI_HIGH, 0xf9, 0xf8, 0, 0, temp10), | ||
| 876 | PREAD(temp7_input, 6, PRI_HIGH, 0xfb, 0xfa, 0, 0, temp10), | ||
| 877 | PREAD(temp8_input, 7, PRI_HIGH, 0xfd, 0xfc, 0, 0, temp10), | ||
| 878 | |||
| 879 | PWRITE(temp1_min, 0, PRI_LOW, 0x4e, 0, 0, 0, temp8), | ||
| 880 | PWRITE(temp2_min, 1, PRI_LOW, 0x50, 0, 0, 0, temp8), | ||
| 881 | PWRITE(temp3_min, 2, PRI_LOW, 0x52, 0, 0, 0, temp8), | ||
| 882 | PWRITE(temp4_min, 3, PRI_LOW, 0x34, 0, 0, 0, temp8), | ||
| 883 | |||
| 884 | PWRITE(temp1_max, 0, PRI_LOW, 0x4f, 0, 0, 0, temp8), | ||
| 885 | PWRITE(temp2_max, 1, PRI_LOW, 0x51, 0, 0, 0, temp8), | ||
| 886 | PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), | ||
| 887 | PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), | ||
| 888 | |||
| 889 | PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask), | ||
| 890 | PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask), | ||
| 891 | PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask), | ||
| 892 | PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask), | ||
| 893 | |||
| 894 | PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), | ||
| 895 | PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), | ||
| 896 | PWRITE(temp3_source, 2, PRI_LOW, 0x03, 0, 0x07, 4, bitmask), | ||
| 897 | PWRITE(temp4_source, 3, PRI_LOW, 0x03, 0, 0x07, 0, bitmask), | ||
| 898 | |||
| 899 | PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), | ||
| 900 | PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), | ||
| 901 | PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask), | ||
| 902 | PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), | ||
| 903 | |||
| 904 | PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), | ||
| 905 | PWRITE(temp2_smoothing_time, 1, PRI_LOW, 0x63, 0, 0x07, 4, temp_st), | ||
| 906 | PWRITE(temp3_smoothing_time, 2, PRI_LOW, 0x63, 0, 0x07, 0, temp_st), | ||
| 907 | PWRITE(temp4_smoothing_time, 3, PRI_LOW, 0x3c, 0, 0x07, 0, temp_st), | ||
| 908 | |||
| 909 | PWRITE(temp1_auto_point1_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, | ||
| 910 | bitmask), | ||
| 911 | PWRITE(temp2_auto_point1_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, | ||
| 912 | bitmask), | ||
| 913 | PWRITE(temp3_auto_point1_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, | ||
| 914 | bitmask), | ||
| 915 | PWRITE(temp4_auto_point1_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, | ||
| 916 | bitmask), | ||
| 917 | |||
| 918 | PREAD(temp1_auto_point2_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, | ||
| 919 | bitmask), | ||
| 920 | PREAD(temp2_auto_point2_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, | ||
| 921 | bitmask), | ||
| 922 | PREAD(temp3_auto_point2_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, | ||
| 923 | bitmask), | ||
| 924 | PREAD(temp4_auto_point2_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, | ||
| 925 | bitmask), | ||
| 926 | |||
| 927 | PWRITE(temp1_auto_point1_temp, 0, PRI_LOW, 0x67, 0, 0, 0, temp8), | ||
| 928 | PWRITE(temp2_auto_point1_temp, 1, PRI_LOW, 0x68, 0, 0, 0, temp8), | ||
| 929 | PWRITE(temp3_auto_point1_temp, 2, PRI_LOW, 0x69, 0, 0, 0, temp8), | ||
| 930 | PWRITE(temp4_auto_point1_temp, 3, PRI_LOW, 0x3b, 0, 0, 0, temp8), | ||
| 931 | |||
| 932 | PWRITEM(temp1_auto_point2_temp, 0, PRI_LOW, VAA(0x5f, 0x67), VAA(0), | ||
| 933 | VAA(0x0f), VAA(4), ap2_temp), | ||
| 934 | PWRITEM(temp2_auto_point2_temp, 1, PRI_LOW, VAA(0x60, 0x68), VAA(0), | ||
| 935 | VAA(0x0f), VAA(4), ap2_temp), | ||
| 936 | PWRITEM(temp3_auto_point2_temp, 2, PRI_LOW, VAA(0x61, 0x69), VAA(0), | ||
| 937 | VAA(0x0f), VAA(4), ap2_temp), | ||
| 938 | PWRITEM(temp4_auto_point2_temp, 3, PRI_LOW, VAA(0x3c, 0x3b), VAA(0), | ||
| 939 | VAA(0x0f), VAA(4), ap2_temp), | ||
| 940 | |||
| 941 | PWRITE(temp1_crit, 0, PRI_LOW, 0x6a, 0, 0, 0, temp8), | ||
| 942 | PWRITE(temp2_crit, 1, PRI_LOW, 0x6b, 0, 0, 0, temp8), | ||
| 943 | PWRITE(temp3_crit, 2, PRI_LOW, 0x6c, 0, 0, 0, temp8), | ||
| 944 | PWRITE(temp4_crit, 3, PRI_LOW, 0x3d, 0, 0, 0, temp8), | ||
| 945 | |||
| 946 | PWRITE(temp5_enable, 4, PRI_LOW, 0x0e, 0, 0x01, 0, bitmask), | ||
| 947 | PWRITE(temp6_enable, 5, PRI_LOW, 0x0e, 0, 0x01, 1, bitmask), | ||
| 948 | PWRITE(temp7_enable, 6, PRI_LOW, 0x0e, 0, 0x01, 2, bitmask), | ||
| 949 | PWRITE(temp8_enable, 7, PRI_LOW, 0x0e, 0, 0x01, 3, bitmask), | ||
| 950 | |||
| 951 | PWRITE(remote1_offset, 0, PRI_LOW, 0x1c, 0, 0, 0, temp62), | ||
| 952 | PWRITE(remote2_offset, 1, PRI_LOW, 0x1d, 0, 0, 0, temp62), | ||
| 953 | |||
| 954 | PWRITE(pwm1, 0, PRI_HIGH, 0x30, 0, 0, 0, u8), | ||
| 955 | PWRITE(pwm2, 1, PRI_HIGH, 0x31, 0, 0, 0, u8), | ||
| 956 | PWRITE(pwm3, 2, PRI_HIGH, 0x32, 0, 0, 0, u8), | ||
| 957 | |||
| 958 | PWRITE(pwm1_invert, 0, PRI_LOW, 0x5c, 0, 0x01, 4, bitmask), | ||
| 959 | PWRITE(pwm2_invert, 1, PRI_LOW, 0x5d, 0, 0x01, 4, bitmask), | ||
| 960 | PWRITE(pwm3_invert, 2, PRI_LOW, 0x5e, 0, 0x01, 4, bitmask), | ||
| 961 | |||
| 962 | PWRITEM(pwm1_enable, 0, PRI_LOW, VAA(0x5c, 0x5c, 0x62), VAA(0, 0, 0), | ||
| 963 | VAA(0x07, 0x01, 0x01), VAA(5, 3, 5), pwm_enable), | ||
| 964 | PWRITEM(pwm2_enable, 1, PRI_LOW, VAA(0x5d, 0x5d, 0x62), VAA(0, 0, 0), | ||
| 965 | VAA(0x07, 0x01, 0x01), VAA(5, 3, 6), pwm_enable), | ||
| 966 | PWRITEM(pwm3_enable, 2, PRI_LOW, VAA(0x5e, 0x5e, 0x62), VAA(0, 0, 0), | ||
| 967 | VAA(0x07, 0x01, 0x01), VAA(5, 3, 7), pwm_enable), | ||
| 968 | |||
| 969 | PWRITEM(pwm1_auto_channels, 0, PRI_LOW, VAA(0x5c, 0x5c), VAA(0, 0), | ||
| 970 | VAA(0x07, 0x01), VAA(5, 3), pwm_ac), | ||
| 971 | PWRITEM(pwm2_auto_channels, 1, PRI_LOW, VAA(0x5d, 0x5d), VAA(0, 0), | ||
| 972 | VAA(0x07, 0x01), VAA(5, 3), pwm_ac), | ||
| 973 | PWRITEM(pwm3_auto_channels, 2, PRI_LOW, VAA(0x5e, 0x5e), VAA(0, 0), | ||
| 974 | VAA(0x07, 0x01), VAA(5, 3), pwm_ac), | ||
| 975 | |||
| 976 | PWRITE(pwm1_auto_point1_pwm, 0, PRI_LOW, 0x64, 0, 0, 0, u8), | ||
| 977 | PWRITE(pwm2_auto_point1_pwm, 1, PRI_LOW, 0x65, 0, 0, 0, u8), | ||
| 978 | PWRITE(pwm3_auto_point1_pwm, 2, PRI_LOW, 0x66, 0, 0, 0, u8), | ||
| 979 | |||
| 980 | PWRITE(pwm1_auto_point2_pwm, 0, PRI_LOW, 0x38, 0, 0, 0, u8), | ||
| 981 | PWRITE(pwm2_auto_point2_pwm, 1, PRI_LOW, 0x39, 0, 0, 0, u8), | ||
| 982 | PWRITE(pwm3_auto_point2_pwm, 2, PRI_LOW, 0x3a, 0, 0, 0, u8), | ||
| 983 | |||
| 984 | PWRITE(pwm1_freq, 0, PRI_LOW, 0x5f, 0, 0x0f, 0, pwm_freq), | ||
| 985 | PWRITE(pwm2_freq, 1, PRI_LOW, 0x60, 0, 0x0f, 0, pwm_freq), | ||
| 986 | PWRITE(pwm3_freq, 2, PRI_LOW, 0x61, 0, 0x0f, 0, pwm_freq), | ||
| 987 | |||
| 988 | PREAD(pwm1_auto_zone_assigned, 0, PRI_LOW, 0, 0, 0x03, 2, bitmask), | ||
| 989 | PREAD(pwm2_auto_zone_assigned, 1, PRI_LOW, 0, 0, 0x03, 4, bitmask), | ||
| 990 | PREAD(pwm3_auto_zone_assigned, 2, PRI_LOW, 0, 0, 0x03, 6, bitmask), | ||
| 991 | |||
| 992 | PWRITE(pwm1_auto_spinup_time, 0, PRI_LOW, 0x5c, 0, 0x07, 0, pwm_ast), | ||
| 993 | PWRITE(pwm2_auto_spinup_time, 1, PRI_LOW, 0x5d, 0, 0x07, 0, pwm_ast), | ||
| 994 | PWRITE(pwm3_auto_spinup_time, 2, PRI_LOW, 0x5e, 0, 0x07, 0, pwm_ast), | ||
| 995 | |||
| 996 | PWRITE(peci_enable, 0, PRI_LOW, 0x40, 0, 0x01, 4, bitmask), | ||
| 997 | PWRITE(peci_avg, 0, PRI_LOW, 0x36, 0, 0x07, 0, bitmask), | ||
| 998 | PWRITE(peci_domain, 0, PRI_LOW, 0x36, 0, 0x01, 3, bitmask), | ||
| 999 | PWRITE(peci_legacy, 0, PRI_LOW, 0x36, 0, 0x01, 4, bitmask), | ||
| 1000 | PWRITE(peci_diode, 0, PRI_LOW, 0x0e, 0, 0x07, 4, bitmask), | ||
| 1001 | PWRITE(peci_4domain, 0, PRI_LOW, 0x0e, 0, 0x01, 4, bitmask), | ||
| 1002 | |||
| 1003 | }; | ||
| 1004 | |||
| 1005 | static struct asc7621_data *asc7621_update_device(struct device *dev) | ||
| 1006 | { | ||
| 1007 | struct i2c_client *client = to_i2c_client(dev); | ||
| 1008 | struct asc7621_data *data = i2c_get_clientdata(client); | ||
| 1009 | int i; | ||
| 1010 | |||
| 1011 | /* | ||
| 1012 | * The asc7621 chips guarantee consistent reads of multi-byte values | ||
| 1013 | * regardless of the order of the reads. No special logic is needed | ||
| 1014 | * so we can just read the registers in whatever order they appear | ||
| 1015 | * in the asc7621_params array. | ||
| 1016 | */ | ||
| 1017 | |||
| 1018 | mutex_lock(&data->update_lock); | ||
| 1019 | |||
| 1020 | /* Read all the high priority registers */ | ||
| 1021 | |||
| 1022 | if (!data->valid || | ||
| 1023 | time_after(jiffies, data->last_high_reading + INTERVAL_HIGH)) { | ||
| 1024 | |||
| 1025 | for (i = 0; i < ARRAY_SIZE(asc7621_register_priorities); i++) { | ||
| 1026 | if (asc7621_register_priorities[i] == PRI_HIGH) { | ||
| 1027 | data->reg[i] = | ||
| 1028 | i2c_smbus_read_byte_data(client, i) & 0xff; | ||
| 1029 | } | ||
| 1030 | } | ||
| 1031 | data->last_high_reading = jiffies; | ||
| 1032 | }; /* last_reading */ | ||
| 1033 | |||
| 1034 | /* Read all the low priority registers. */ | ||
| 1035 | |||
| 1036 | if (!data->valid || | ||
| 1037 | time_after(jiffies, data->last_low_reading + INTERVAL_LOW)) { | ||
| 1038 | |||
| 1039 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { | ||
| 1040 | if (asc7621_register_priorities[i] == PRI_LOW) { | ||
| 1041 | data->reg[i] = | ||
| 1042 | i2c_smbus_read_byte_data(client, i) & 0xff; | ||
| 1043 | } | ||
| 1044 | } | ||
| 1045 | data->last_low_reading = jiffies; | ||
| 1046 | }; /* last_reading */ | ||
| 1047 | |||
| 1048 | data->valid = 1; | ||
| 1049 | |||
| 1050 | mutex_unlock(&data->update_lock); | ||
| 1051 | |||
| 1052 | return data; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | /* | ||
| 1056 | * Standard detection and initialization below | ||
| 1057 | * | ||
| 1058 | * Helper function that checks if an address is valid | ||
| 1059 | * for a particular chip. | ||
| 1060 | */ | ||
| 1061 | |||
| 1062 | static inline int valid_address_for_chip(int chip_type, int address) | ||
| 1063 | { | ||
| 1064 | int i; | ||
| 1065 | |||
| 1066 | for (i = 0; asc7621_chips[chip_type].addresses[i] != I2C_CLIENT_END; | ||
| 1067 | i++) { | ||
| 1068 | if (asc7621_chips[chip_type].addresses[i] == address) | ||
| 1069 | return 1; | ||
| 1070 | } | ||
| 1071 | return 0; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static void asc7621_init_client(struct i2c_client *client) | ||
| 1075 | { | ||
| 1076 | int value; | ||
| 1077 | |||
| 1078 | /* Warn if part was not "READY" */ | ||
| 1079 | |||
| 1080 | value = read_byte(client, 0x40); | ||
| 1081 | |||
| 1082 | if (value & 0x02) { | ||
| 1083 | dev_err(&client->dev, | ||
| 1084 | "Client (%d,0x%02x) config is locked.\n", | ||
| 1085 | i2c_adapter_id(client->adapter), client->addr); | ||
| 1086 | }; | ||
| 1087 | if (!(value & 0x04)) { | ||
| 1088 | dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n", | ||
| 1089 | i2c_adapter_id(client->adapter), client->addr); | ||
| 1090 | }; | ||
| 1091 | |||
| 1092 | /* | ||
| 1093 | * Start monitoring | ||
| 1094 | * | ||
| 1095 | * Try to clear LOCK, Set START, save everything else | ||
| 1096 | */ | ||
| 1097 | value = (value & ~0x02) | 0x01; | ||
| 1098 | write_byte(client, 0x40, value & 0xff); | ||
| 1099 | |||
| 1100 | } | ||
| 1101 | |||
| 1102 | static int | ||
| 1103 | asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
| 1104 | { | ||
| 1105 | struct asc7621_data *data; | ||
| 1106 | int i, err; | ||
| 1107 | |||
| 1108 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 1109 | return -EIO; | ||
| 1110 | |||
| 1111 | data = kzalloc(sizeof(struct asc7621_data), GFP_KERNEL); | ||
| 1112 | if (data == NULL) | ||
| 1113 | return -ENOMEM; | ||
| 1114 | |||
| 1115 | i2c_set_clientdata(client, data); | ||
| 1116 | data->valid = 0; | ||
| 1117 | mutex_init(&data->update_lock); | ||
| 1118 | |||
| 1119 | /* Initialize the asc7621 chip */ | ||
| 1120 | asc7621_init_client(client); | ||
| 1121 | |||
| 1122 | /* Create the sysfs entries */ | ||
| 1123 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { | ||
| 1124 | err = | ||
| 1125 | device_create_file(&client->dev, | ||
| 1126 | &(asc7621_params[i].sda.dev_attr)); | ||
| 1127 | if (err) | ||
| 1128 | goto exit_remove; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | data->class_dev = hwmon_device_register(&client->dev); | ||
| 1132 | if (IS_ERR(data->class_dev)) { | ||
| 1133 | err = PTR_ERR(data->class_dev); | ||
| 1134 | goto exit_remove; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | return 0; | ||
| 1138 | |||
| 1139 | exit_remove: | ||
| 1140 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { | ||
| 1141 | device_remove_file(&client->dev, | ||
| 1142 | &(asc7621_params[i].sda.dev_attr)); | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | i2c_set_clientdata(client, NULL); | ||
| 1146 | kfree(data); | ||
| 1147 | return err; | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | static int asc7621_detect(struct i2c_client *client, | ||
| 1151 | struct i2c_board_info *info) | ||
| 1152 | { | ||
| 1153 | struct i2c_adapter *adapter = client->adapter; | ||
| 1154 | int company, verstep, chip_index; | ||
| 1155 | struct device *dev; | ||
| 1156 | |||
| 1157 | dev = &client->dev; | ||
| 1158 | |||
| 1159 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 1160 | return -ENODEV; | ||
| 1161 | |||
| 1162 | for (chip_index = FIRST_CHIP; chip_index <= LAST_CHIP; chip_index++) { | ||
| 1163 | |||
| 1164 | if (!valid_address_for_chip(chip_index, client->addr)) | ||
| 1165 | continue; | ||
| 1166 | |||
| 1167 | company = read_byte(client, | ||
| 1168 | asc7621_chips[chip_index].company_reg); | ||
| 1169 | verstep = read_byte(client, | ||
| 1170 | asc7621_chips[chip_index].verstep_reg); | ||
| 1171 | |||
| 1172 | if (company == asc7621_chips[chip_index].company_id && | ||
| 1173 | verstep == asc7621_chips[chip_index].verstep_id) { | ||
| 1174 | strlcpy(client->name, asc7621_chips[chip_index].name, | ||
| 1175 | I2C_NAME_SIZE); | ||
| 1176 | strlcpy(info->type, asc7621_chips[chip_index].name, | ||
| 1177 | I2C_NAME_SIZE); | ||
| 1178 | |||
| 1179 | dev_info(&adapter->dev, "Matched %s\n", | ||
| 1180 | asc7621_chips[chip_index].name); | ||
| 1181 | return 0; | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | return -ENODEV; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | static int asc7621_remove(struct i2c_client *client) | ||
| 1189 | { | ||
| 1190 | struct asc7621_data *data = i2c_get_clientdata(client); | ||
| 1191 | int i; | ||
| 1192 | |||
| 1193 | hwmon_device_unregister(data->class_dev); | ||
| 1194 | |||
| 1195 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { | ||
| 1196 | device_remove_file(&client->dev, | ||
| 1197 | &(asc7621_params[i].sda.dev_attr)); | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | i2c_set_clientdata(client, NULL); | ||
| 1201 | kfree(data); | ||
| 1202 | return 0; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | static const struct i2c_device_id asc7621_id[] = { | ||
| 1206 | {"asc7621", asc7621}, | ||
| 1207 | {"asc7621a", asc7621a}, | ||
| 1208 | {}, | ||
| 1209 | }; | ||
| 1210 | |||
| 1211 | MODULE_DEVICE_TABLE(i2c, asc7621_id); | ||
| 1212 | |||
| 1213 | static struct i2c_driver asc7621_driver = { | ||
| 1214 | .class = I2C_CLASS_HWMON, | ||
| 1215 | .driver = { | ||
| 1216 | .name = "asc7621", | ||
| 1217 | }, | ||
| 1218 | .probe = asc7621_probe, | ||
| 1219 | .remove = asc7621_remove, | ||
| 1220 | .id_table = asc7621_id, | ||
| 1221 | .detect = asc7621_detect, | ||
| 1222 | .address_list = normal_i2c, | ||
| 1223 | }; | ||
| 1224 | |||
| 1225 | static int __init sm_asc7621_init(void) | ||
| 1226 | { | ||
| 1227 | int i, j; | ||
| 1228 | /* | ||
| 1229 | * Collect all the registers needed into a single array. | ||
| 1230 | * This way, if a register isn't actually used for anything, | ||
| 1231 | * we don't retrieve it. | ||
| 1232 | */ | ||
| 1233 | |||
| 1234 | for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { | ||
| 1235 | for (j = 0; j < ARRAY_SIZE(asc7621_params[i].msb); j++) | ||
| 1236 | asc7621_register_priorities[asc7621_params[i].msb[j]] = | ||
| 1237 | asc7621_params[i].priority; | ||
| 1238 | for (j = 0; j < ARRAY_SIZE(asc7621_params[i].lsb); j++) | ||
| 1239 | asc7621_register_priorities[asc7621_params[i].lsb[j]] = | ||
| 1240 | asc7621_params[i].priority; | ||
| 1241 | } | ||
| 1242 | return i2c_add_driver(&asc7621_driver); | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | static void __exit sm_asc7621_exit(void) | ||
| 1246 | { | ||
| 1247 | i2c_del_driver(&asc7621_driver); | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | MODULE_LICENSE("GPL"); | ||
| 1251 | MODULE_AUTHOR("George Joseph"); | ||
| 1252 | MODULE_DESCRIPTION("Andigilog aSC7621 and aSC7621a driver"); | ||
| 1253 | |||
| 1254 | module_init(sm_asc7621_init); | ||
| 1255 | module_exit(sm_asc7621_exit); | ||
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index fa0728232e71..0627f7a5b9b8 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c | |||
| @@ -267,7 +267,7 @@ struct fschmd_data { | |||
| 267 | struct list_head list; /* member of the watchdog_data_list */ | 267 | struct list_head list; /* member of the watchdog_data_list */ |
| 268 | struct kref kref; | 268 | struct kref kref; |
| 269 | struct miscdevice watchdog_miscdev; | 269 | struct miscdevice watchdog_miscdev; |
| 270 | int kind; | 270 | enum chips kind; |
| 271 | unsigned long watchdog_is_open; | 271 | unsigned long watchdog_is_open; |
| 272 | char watchdog_expect_close; | 272 | char watchdog_expect_close; |
| 273 | char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ | 273 | char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ |
| @@ -325,8 +325,7 @@ static ssize_t show_in_value(struct device *dev, | |||
| 325 | int index = to_sensor_dev_attr(devattr)->index; | 325 | int index = to_sensor_dev_attr(devattr)->index; |
| 326 | struct fschmd_data *data = fschmd_update_device(dev); | 326 | struct fschmd_data *data = fschmd_update_device(dev); |
| 327 | 327 | ||
| 328 | /* fscher / fschrc - 1 as data->kind is an array index, not a chips */ | 328 | if (data->kind == fscher || data->kind >= fschrc) |
| 329 | if (data->kind == (fscher - 1) || data->kind >= (fschrc - 1)) | ||
| 330 | return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref * | 329 | return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref * |
| 331 | dmi_mult[index]) / 255 + dmi_offset[index]); | 330 | dmi_mult[index]) / 255 + dmi_offset[index]); |
| 332 | else | 331 | else |
| @@ -492,7 +491,7 @@ static ssize_t show_pwm_auto_point1_pwm(struct device *dev, | |||
| 492 | int val = data->fan_min[index]; | 491 | int val = data->fan_min[index]; |
| 493 | 492 | ||
| 494 | /* 0 = allow turning off (except on the syl), 1-255 = 50-100% */ | 493 | /* 0 = allow turning off (except on the syl), 1-255 = 50-100% */ |
| 495 | if (val || data->kind == fscsyl - 1) | 494 | if (val || data->kind == fscsyl) |
| 496 | val = val / 2 + 128; | 495 | val = val / 2 + 128; |
| 497 | 496 | ||
| 498 | return sprintf(buf, "%d\n", val); | 497 | return sprintf(buf, "%d\n", val); |
| @@ -506,7 +505,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev, | |||
| 506 | unsigned long v = simple_strtoul(buf, NULL, 10); | 505 | unsigned long v = simple_strtoul(buf, NULL, 10); |
| 507 | 506 | ||
| 508 | /* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */ | 507 | /* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */ |
| 509 | if (v || data->kind == fscsyl - 1) { | 508 | if (v || data->kind == fscsyl) { |
| 510 | v = SENSORS_LIMIT(v, 128, 255); | 509 | v = SENSORS_LIMIT(v, 128, 255); |
| 511 | v = (v - 128) * 2 + 1; | 510 | v = (v - 128) * 2 + 1; |
| 512 | } | 511 | } |
| @@ -1037,7 +1036,7 @@ static int fschmd_detect(struct i2c_client *client, | |||
| 1037 | else | 1036 | else |
| 1038 | return -ENODEV; | 1037 | return -ENODEV; |
| 1039 | 1038 | ||
| 1040 | strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE); | 1039 | strlcpy(info->type, fschmd_id[kind].name, I2C_NAME_SIZE); |
| 1041 | 1040 | ||
| 1042 | return 0; | 1041 | return 0; |
| 1043 | } | 1042 | } |
| @@ -1065,6 +1064,7 @@ static int fschmd_probe(struct i2c_client *client, | |||
| 1065 | (where the client is found through a data ptr instead of the | 1064 | (where the client is found through a data ptr instead of the |
| 1066 | otherway around) */ | 1065 | otherway around) */ |
| 1067 | data->client = client; | 1066 | data->client = client; |
| 1067 | data->kind = kind; | ||
| 1068 | 1068 | ||
| 1069 | if (kind == fscpos) { | 1069 | if (kind == fscpos) { |
| 1070 | /* The Poseidon has hardwired temp limits, fill these | 1070 | /* The Poseidon has hardwired temp limits, fill these |
| @@ -1085,9 +1085,6 @@ static int fschmd_probe(struct i2c_client *client, | |||
| 1085 | } | 1085 | } |
| 1086 | } | 1086 | } |
| 1087 | 1087 | ||
| 1088 | /* i2c kind goes from 1-6, we want from 0-5 to address arrays */ | ||
| 1089 | data->kind = kind - 1; | ||
| 1090 | |||
| 1091 | /* Read in some never changing registers */ | 1088 | /* Read in some never changing registers */ |
| 1092 | data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); | 1089 | data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); |
| 1093 | data->global_control = i2c_smbus_read_byte_data(client, | 1090 | data->global_control = i2c_smbus_read_byte_data(client, |
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index 19c01a49f6be..09ea12e0a551 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c | |||
| @@ -68,7 +68,7 @@ struct g760a_data { | |||
| 68 | #define PWM_FROM_CNT(cnt) (0xff-(cnt)) | 68 | #define PWM_FROM_CNT(cnt) (0xff-(cnt)) |
| 69 | #define PWM_TO_CNT(pwm) (0xff-(pwm)) | 69 | #define PWM_TO_CNT(pwm) (0xff-(pwm)) |
| 70 | 70 | ||
| 71 | unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div) | 71 | static inline unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div) |
| 72 | { | 72 | { |
| 73 | return ((val == 0x00) ? 0 : ((clk*30)/(val*div))); | 73 | return ((val == 0x00) ? 0 : ((clk*30)/(val*div))); |
| 74 | } | 74 | } |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0ffe84d190bb..1002befd87d5 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
| @@ -1,40 +1,40 @@ | |||
| 1 | /* | 1 | /* |
| 2 | it87.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * it87.c - Part of lm_sensors, Linux kernel modules for hardware |
| 3 | monitoring. | 3 | * monitoring. |
| 4 | 4 | * | |
| 5 | The IT8705F is an LPC-based Super I/O part that contains UARTs, a | 5 | * The IT8705F is an LPC-based Super I/O part that contains UARTs, a |
| 6 | parallel port, an IR port, a MIDI port, a floppy controller, etc., in | 6 | * parallel port, an IR port, a MIDI port, a floppy controller, etc., in |
| 7 | addition to an Environment Controller (Enhanced Hardware Monitor and | 7 | * addition to an Environment Controller (Enhanced Hardware Monitor and |
| 8 | Fan Controller) | 8 | * Fan Controller) |
| 9 | 9 | * | |
| 10 | This driver supports only the Environment Controller in the IT8705F and | 10 | * This driver supports only the Environment Controller in the IT8705F and |
| 11 | similar parts. The other devices are supported by different drivers. | 11 | * similar parts. The other devices are supported by different drivers. |
| 12 | 12 | * | |
| 13 | Supports: IT8705F Super I/O chip w/LPC interface | 13 | * Supports: IT8705F Super I/O chip w/LPC interface |
| 14 | IT8712F Super I/O chip w/LPC interface | 14 | * IT8712F Super I/O chip w/LPC interface |
| 15 | IT8716F Super I/O chip w/LPC interface | 15 | * IT8716F Super I/O chip w/LPC interface |
| 16 | IT8718F Super I/O chip w/LPC interface | 16 | * IT8718F Super I/O chip w/LPC interface |
| 17 | IT8720F Super I/O chip w/LPC interface | 17 | * IT8720F Super I/O chip w/LPC interface |
| 18 | IT8726F Super I/O chip w/LPC interface | 18 | * IT8726F Super I/O chip w/LPC interface |
| 19 | Sis950 A clone of the IT8705F | 19 | * Sis950 A clone of the IT8705F |
| 20 | 20 | * | |
| 21 | Copyright (C) 2001 Chris Gauthron | 21 | * Copyright (C) 2001 Chris Gauthron |
| 22 | Copyright (C) 2005-2007 Jean Delvare <khali@linux-fr.org> | 22 | * Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org> |
| 23 | 23 | * | |
| 24 | This program is free software; you can redistribute it and/or modify | 24 | * This program is free software; you can redistribute it and/or modify |
| 25 | it under the terms of the GNU General Public License as published by | 25 | * it under the terms of the GNU General Public License as published by |
| 26 | the Free Software Foundation; either version 2 of the License, or | 26 | * the Free Software Foundation; either version 2 of the License, or |
| 27 | (at your option) any later version. | 27 | * (at your option) any later version. |
| 28 | 28 | * | |
| 29 | This program is distributed in the hope that it will be useful, | 29 | * This program is distributed in the hope that it will be useful, |
| 30 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 32 | GNU General Public License for more details. | 32 | * GNU General Public License for more details. |
| 33 | 33 | * | |
| 34 | You should have received a copy of the GNU General Public License | 34 | * You should have received a copy of the GNU General Public License |
| 35 | along with this program; if not, write to the Free Software | 35 | * along with this program; if not, write to the Free Software |
| 36 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 36 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
| @@ -128,6 +128,7 @@ superio_exit(void) | |||
| 128 | #define IT87_SIO_GPIO5_REG 0x29 | 128 | #define IT87_SIO_GPIO5_REG 0x29 |
| 129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ | 129 | #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ |
| 130 | #define IT87_SIO_VID_REG 0xfc /* VID value */ | 130 | #define IT87_SIO_VID_REG 0xfc /* VID value */ |
| 131 | #define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */ | ||
| 131 | 132 | ||
| 132 | /* Update battery voltage after every reading if true */ | 133 | /* Update battery voltage after every reading if true */ |
| 133 | static int update_vbat; | 134 | static int update_vbat; |
| @@ -187,9 +188,13 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; | |||
| 187 | 188 | ||
| 188 | #define IT87_REG_VIN_ENABLE 0x50 | 189 | #define IT87_REG_VIN_ENABLE 0x50 |
| 189 | #define IT87_REG_TEMP_ENABLE 0x51 | 190 | #define IT87_REG_TEMP_ENABLE 0x51 |
| 191 | #define IT87_REG_BEEP_ENABLE 0x5c | ||
| 190 | 192 | ||
| 191 | #define IT87_REG_CHIPID 0x58 | 193 | #define IT87_REG_CHIPID 0x58 |
| 192 | 194 | ||
| 195 | #define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) | ||
| 196 | #define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) | ||
| 197 | |||
| 193 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) | 198 | #define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) |
| 194 | #define IN_FROM_REG(val) ((val) * 16) | 199 | #define IN_FROM_REG(val) ((val) * 16) |
| 195 | 200 | ||
| @@ -246,6 +251,7 @@ struct it87_sio_data { | |||
| 246 | /* Values read from Super-I/O config space */ | 251 | /* Values read from Super-I/O config space */ |
| 247 | u8 revision; | 252 | u8 revision; |
| 248 | u8 vid_value; | 253 | u8 vid_value; |
| 254 | u8 beep_pin; | ||
| 249 | /* Features skipped based on config or DMI */ | 255 | /* Features skipped based on config or DMI */ |
| 250 | u8 skip_vid; | 256 | u8 skip_vid; |
| 251 | u8 skip_fan; | 257 | u8 skip_fan; |
| @@ -279,9 +285,21 @@ struct it87_data { | |||
| 279 | u8 vid; /* Register encoding, combined */ | 285 | u8 vid; /* Register encoding, combined */ |
| 280 | u8 vrm; | 286 | u8 vrm; |
| 281 | u32 alarms; /* Register encoding, combined */ | 287 | u32 alarms; /* Register encoding, combined */ |
| 288 | u8 beeps; /* Register encoding */ | ||
| 282 | u8 fan_main_ctrl; /* Register value */ | 289 | u8 fan_main_ctrl; /* Register value */ |
| 283 | u8 fan_ctl; /* Register value */ | 290 | u8 fan_ctl; /* Register value */ |
| 284 | u8 manual_pwm_ctl[3]; /* manual PWM value set by user */ | 291 | |
| 292 | /* The following 3 arrays correspond to the same registers. The | ||
| 293 | * meaning of bits 6-0 depends on the value of bit 7, and we want | ||
| 294 | * to preserve settings on mode changes, so we have to track all | ||
| 295 | * values separately. */ | ||
| 296 | u8 pwm_ctrl[3]; /* Register value */ | ||
| 297 | u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */ | ||
| 298 | u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ | ||
| 299 | |||
| 300 | /* Automatic fan speed control registers */ | ||
| 301 | u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */ | ||
| 302 | s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ | ||
| 285 | }; | 303 | }; |
| 286 | 304 | ||
| 287 | static inline int has_16bit_fans(const struct it87_data *data) | 305 | static inline int has_16bit_fans(const struct it87_data *data) |
| @@ -296,6 +314,15 @@ static inline int has_16bit_fans(const struct it87_data *data) | |||
| 296 | || data->type == it8720; | 314 | || data->type == it8720; |
| 297 | } | 315 | } |
| 298 | 316 | ||
| 317 | static inline int has_old_autopwm(const struct it87_data *data) | ||
| 318 | { | ||
| 319 | /* The old automatic fan speed control interface is implemented | ||
| 320 | by IT8705F chips up to revision F and IT8712F chips up to | ||
| 321 | revision G. */ | ||
| 322 | return (data->type == it87 && data->revision < 0x03) | ||
| 323 | || (data->type == it8712 && data->revision < 0x08); | ||
| 324 | } | ||
| 325 | |||
| 299 | static int it87_probe(struct platform_device *pdev); | 326 | static int it87_probe(struct platform_device *pdev); |
| 300 | static int __devexit it87_remove(struct platform_device *pdev); | 327 | static int __devexit it87_remove(struct platform_device *pdev); |
| 301 | 328 | ||
| @@ -352,7 +379,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | |||
| 352 | int nr = sensor_attr->index; | 379 | int nr = sensor_attr->index; |
| 353 | 380 | ||
| 354 | struct it87_data *data = dev_get_drvdata(dev); | 381 | struct it87_data *data = dev_get_drvdata(dev); |
| 355 | unsigned long val = simple_strtoul(buf, NULL, 10); | 382 | unsigned long val; |
| 383 | |||
| 384 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 385 | return -EINVAL; | ||
| 356 | 386 | ||
| 357 | mutex_lock(&data->update_lock); | 387 | mutex_lock(&data->update_lock); |
| 358 | data->in_min[nr] = IN_TO_REG(val); | 388 | data->in_min[nr] = IN_TO_REG(val); |
| @@ -368,7 +398,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | |||
| 368 | int nr = sensor_attr->index; | 398 | int nr = sensor_attr->index; |
| 369 | 399 | ||
| 370 | struct it87_data *data = dev_get_drvdata(dev); | 400 | struct it87_data *data = dev_get_drvdata(dev); |
| 371 | unsigned long val = simple_strtoul(buf, NULL, 10); | 401 | unsigned long val; |
| 402 | |||
| 403 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 404 | return -EINVAL; | ||
| 372 | 405 | ||
| 373 | mutex_lock(&data->update_lock); | 406 | mutex_lock(&data->update_lock); |
| 374 | data->in_max[nr] = IN_TO_REG(val); | 407 | data->in_max[nr] = IN_TO_REG(val); |
| @@ -441,7 +474,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | |||
| 441 | int nr = sensor_attr->index; | 474 | int nr = sensor_attr->index; |
| 442 | 475 | ||
| 443 | struct it87_data *data = dev_get_drvdata(dev); | 476 | struct it87_data *data = dev_get_drvdata(dev); |
| 444 | int val = simple_strtol(buf, NULL, 10); | 477 | long val; |
| 478 | |||
| 479 | if (strict_strtol(buf, 10, &val) < 0) | ||
| 480 | return -EINVAL; | ||
| 445 | 481 | ||
| 446 | mutex_lock(&data->update_lock); | 482 | mutex_lock(&data->update_lock); |
| 447 | data->temp_high[nr] = TEMP_TO_REG(val); | 483 | data->temp_high[nr] = TEMP_TO_REG(val); |
| @@ -456,7 +492,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | |||
| 456 | int nr = sensor_attr->index; | 492 | int nr = sensor_attr->index; |
| 457 | 493 | ||
| 458 | struct it87_data *data = dev_get_drvdata(dev); | 494 | struct it87_data *data = dev_get_drvdata(dev); |
| 459 | int val = simple_strtol(buf, NULL, 10); | 495 | long val; |
| 496 | |||
| 497 | if (strict_strtol(buf, 10, &val) < 0) | ||
| 498 | return -EINVAL; | ||
| 460 | 499 | ||
| 461 | mutex_lock(&data->update_lock); | 500 | mutex_lock(&data->update_lock); |
| 462 | data->temp_low[nr] = TEMP_TO_REG(val); | 501 | data->temp_low[nr] = TEMP_TO_REG(val); |
| @@ -483,8 +522,9 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, | |||
| 483 | int nr = sensor_attr->index; | 522 | int nr = sensor_attr->index; |
| 484 | 523 | ||
| 485 | struct it87_data *data = it87_update_device(dev); | 524 | struct it87_data *data = it87_update_device(dev); |
| 486 | u8 reg = data->sensor; /* In case the value is updated while we use it */ | 525 | u8 reg = data->sensor; /* In case the value is updated while |
| 487 | 526 | we use it */ | |
| 527 | |||
| 488 | if (reg & (1 << nr)) | 528 | if (reg & (1 << nr)) |
| 489 | return sprintf(buf, "3\n"); /* thermal diode */ | 529 | return sprintf(buf, "3\n"); /* thermal diode */ |
| 490 | if (reg & (8 << nr)) | 530 | if (reg & (8 << nr)) |
| @@ -498,7 +538,10 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
| 498 | int nr = sensor_attr->index; | 538 | int nr = sensor_attr->index; |
| 499 | 539 | ||
| 500 | struct it87_data *data = dev_get_drvdata(dev); | 540 | struct it87_data *data = dev_get_drvdata(dev); |
| 501 | int val = simple_strtol(buf, NULL, 10); | 541 | long val; |
| 542 | |||
| 543 | if (strict_strtol(buf, 10, &val) < 0) | ||
| 544 | return -EINVAL; | ||
| 502 | 545 | ||
| 503 | mutex_lock(&data->update_lock); | 546 | mutex_lock(&data->update_lock); |
| 504 | 547 | ||
| @@ -511,9 +554,9 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, | |||
| 511 | } | 554 | } |
| 512 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ | 555 | /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ |
| 513 | if (val == 3) | 556 | if (val == 3) |
| 514 | data->sensor |= 1 << nr; | 557 | data->sensor |= 1 << nr; |
| 515 | else if (val == 4) | 558 | else if (val == 4) |
| 516 | data->sensor |= 8 << nr; | 559 | data->sensor |= 8 << nr; |
| 517 | else if (val != 0) { | 560 | else if (val != 0) { |
| 518 | mutex_unlock(&data->update_lock); | 561 | mutex_unlock(&data->update_lock); |
| 519 | return -EINVAL; | 562 | return -EINVAL; |
| @@ -531,6 +574,19 @@ show_sensor_offset(2); | |||
| 531 | show_sensor_offset(3); | 574 | show_sensor_offset(3); |
| 532 | 575 | ||
| 533 | /* 3 Fans */ | 576 | /* 3 Fans */ |
| 577 | |||
| 578 | static int pwm_mode(const struct it87_data *data, int nr) | ||
| 579 | { | ||
| 580 | int ctrl = data->fan_main_ctrl & (1 << nr); | ||
| 581 | |||
| 582 | if (ctrl == 0) /* Full speed */ | ||
| 583 | return 0; | ||
| 584 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
| 585 | return 2; | ||
| 586 | else /* Manual mode */ | ||
| 587 | return 1; | ||
| 588 | } | ||
| 589 | |||
| 534 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | 590 | static ssize_t show_fan(struct device *dev, struct device_attribute *attr, |
| 535 | char *buf) | 591 | char *buf) |
| 536 | { | 592 | { |
| @@ -538,7 +594,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, | |||
| 538 | int nr = sensor_attr->index; | 594 | int nr = sensor_attr->index; |
| 539 | 595 | ||
| 540 | struct it87_data *data = it87_update_device(dev); | 596 | struct it87_data *data = it87_update_device(dev); |
| 541 | return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], | 597 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], |
| 542 | DIV_FROM_REG(data->fan_div[nr]))); | 598 | DIV_FROM_REG(data->fan_div[nr]))); |
| 543 | } | 599 | } |
| 544 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | 600 | static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, |
| @@ -548,8 +604,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, | |||
| 548 | int nr = sensor_attr->index; | 604 | int nr = sensor_attr->index; |
| 549 | 605 | ||
| 550 | struct it87_data *data = it87_update_device(dev); | 606 | struct it87_data *data = it87_update_device(dev); |
| 551 | return sprintf(buf,"%d\n", | 607 | return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], |
| 552 | FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]))); | 608 | DIV_FROM_REG(data->fan_div[nr]))); |
| 553 | } | 609 | } |
| 554 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | 610 | static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, |
| 555 | char *buf) | 611 | char *buf) |
| @@ -560,14 +616,14 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, | |||
| 560 | struct it87_data *data = it87_update_device(dev); | 616 | struct it87_data *data = it87_update_device(dev); |
| 561 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); | 617 | return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); |
| 562 | } | 618 | } |
| 563 | static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, | 619 | static ssize_t show_pwm_enable(struct device *dev, |
| 564 | char *buf) | 620 | struct device_attribute *attr, char *buf) |
| 565 | { | 621 | { |
| 566 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 622 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
| 567 | int nr = sensor_attr->index; | 623 | int nr = sensor_attr->index; |
| 568 | 624 | ||
| 569 | struct it87_data *data = it87_update_device(dev); | 625 | struct it87_data *data = it87_update_device(dev); |
| 570 | return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0); | 626 | return sprintf(buf, "%d\n", pwm_mode(data, nr)); |
| 571 | } | 627 | } |
| 572 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | 628 | static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, |
| 573 | char *buf) | 629 | char *buf) |
| @@ -576,7 +632,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, | |||
| 576 | int nr = sensor_attr->index; | 632 | int nr = sensor_attr->index; |
| 577 | 633 | ||
| 578 | struct it87_data *data = it87_update_device(dev); | 634 | struct it87_data *data = it87_update_device(dev); |
| 579 | return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]); | 635 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr])); |
| 580 | } | 636 | } |
| 581 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, | 637 | static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, |
| 582 | char *buf) | 638 | char *buf) |
| @@ -593,15 +649,24 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, | |||
| 593 | int nr = sensor_attr->index; | 649 | int nr = sensor_attr->index; |
| 594 | 650 | ||
| 595 | struct it87_data *data = dev_get_drvdata(dev); | 651 | struct it87_data *data = dev_get_drvdata(dev); |
| 596 | int val = simple_strtol(buf, NULL, 10); | 652 | long val; |
| 597 | u8 reg; | 653 | u8 reg; |
| 598 | 654 | ||
| 655 | if (strict_strtol(buf, 10, &val) < 0) | ||
| 656 | return -EINVAL; | ||
| 657 | |||
| 599 | mutex_lock(&data->update_lock); | 658 | mutex_lock(&data->update_lock); |
| 600 | reg = it87_read_value(data, IT87_REG_FAN_DIV); | 659 | reg = it87_read_value(data, IT87_REG_FAN_DIV); |
| 601 | switch (nr) { | 660 | switch (nr) { |
| 602 | case 0: data->fan_div[nr] = reg & 0x07; break; | 661 | case 0: |
| 603 | case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break; | 662 | data->fan_div[nr] = reg & 0x07; |
| 604 | case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break; | 663 | break; |
| 664 | case 1: | ||
| 665 | data->fan_div[nr] = (reg >> 3) & 0x07; | ||
| 666 | break; | ||
| 667 | case 2: | ||
| 668 | data->fan_div[nr] = (reg & 0x40) ? 3 : 1; | ||
| 669 | break; | ||
| 605 | } | 670 | } |
| 606 | 671 | ||
| 607 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 672 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
| @@ -616,10 +681,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
| 616 | int nr = sensor_attr->index; | 681 | int nr = sensor_attr->index; |
| 617 | 682 | ||
| 618 | struct it87_data *data = dev_get_drvdata(dev); | 683 | struct it87_data *data = dev_get_drvdata(dev); |
| 619 | unsigned long val = simple_strtoul(buf, NULL, 10); | 684 | unsigned long val; |
| 620 | int min; | 685 | int min; |
| 621 | u8 old; | 686 | u8 old; |
| 622 | 687 | ||
| 688 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 689 | return -EINVAL; | ||
| 690 | |||
| 623 | mutex_lock(&data->update_lock); | 691 | mutex_lock(&data->update_lock); |
| 624 | old = it87_read_value(data, IT87_REG_FAN_DIV); | 692 | old = it87_read_value(data, IT87_REG_FAN_DIV); |
| 625 | 693 | ||
| @@ -651,6 +719,32 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, | |||
| 651 | mutex_unlock(&data->update_lock); | 719 | mutex_unlock(&data->update_lock); |
| 652 | return count; | 720 | return count; |
| 653 | } | 721 | } |
| 722 | |||
| 723 | /* Returns 0 if OK, -EINVAL otherwise */ | ||
| 724 | static int check_trip_points(struct device *dev, int nr) | ||
| 725 | { | ||
| 726 | const struct it87_data *data = dev_get_drvdata(dev); | ||
| 727 | int i, err = 0; | ||
| 728 | |||
| 729 | if (has_old_autopwm(data)) { | ||
| 730 | for (i = 0; i < 3; i++) { | ||
| 731 | if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) | ||
| 732 | err = -EINVAL; | ||
| 733 | } | ||
| 734 | for (i = 0; i < 2; i++) { | ||
| 735 | if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) | ||
| 736 | err = -EINVAL; | ||
| 737 | } | ||
| 738 | } | ||
| 739 | |||
| 740 | if (err) { | ||
| 741 | dev_err(dev, "Inconsistent trip points, not switching to " | ||
| 742 | "automatic mode\n"); | ||
| 743 | dev_err(dev, "Adjust the trip points and try again\n"); | ||
| 744 | } | ||
| 745 | return err; | ||
| 746 | } | ||
| 747 | |||
| 654 | static ssize_t set_pwm_enable(struct device *dev, | 748 | static ssize_t set_pwm_enable(struct device *dev, |
| 655 | struct device_attribute *attr, const char *buf, size_t count) | 749 | struct device_attribute *attr, const char *buf, size_t count) |
| 656 | { | 750 | { |
| @@ -658,7 +752,16 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
| 658 | int nr = sensor_attr->index; | 752 | int nr = sensor_attr->index; |
| 659 | 753 | ||
| 660 | struct it87_data *data = dev_get_drvdata(dev); | 754 | struct it87_data *data = dev_get_drvdata(dev); |
| 661 | int val = simple_strtol(buf, NULL, 10); | 755 | long val; |
| 756 | |||
| 757 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 2) | ||
| 758 | return -EINVAL; | ||
| 759 | |||
| 760 | /* Check trip points before switching to automatic mode */ | ||
| 761 | if (val == 2) { | ||
| 762 | if (check_trip_points(dev, nr) < 0) | ||
| 763 | return -EINVAL; | ||
| 764 | } | ||
| 662 | 765 | ||
| 663 | mutex_lock(&data->update_lock); | 766 | mutex_lock(&data->update_lock); |
| 664 | 767 | ||
| @@ -669,16 +772,18 @@ static ssize_t set_pwm_enable(struct device *dev, | |||
| 669 | it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); | 772 | it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); |
| 670 | /* set on/off mode */ | 773 | /* set on/off mode */ |
| 671 | data->fan_main_ctrl &= ~(1 << nr); | 774 | data->fan_main_ctrl &= ~(1 << nr); |
| 672 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 775 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
| 673 | } else if (val == 1) { | 776 | data->fan_main_ctrl); |
| 777 | } else { | ||
| 778 | if (val == 1) /* Manual mode */ | ||
| 779 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
| 780 | else /* Automatic mode */ | ||
| 781 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
| 782 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
| 674 | /* set SmartGuardian mode */ | 783 | /* set SmartGuardian mode */ |
| 675 | data->fan_main_ctrl |= (1 << nr); | 784 | data->fan_main_ctrl |= (1 << nr); |
| 676 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 785 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
| 677 | /* set saved pwm value, clear FAN_CTLX PWM mode bit */ | 786 | data->fan_main_ctrl); |
| 678 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | ||
| 679 | } else { | ||
| 680 | mutex_unlock(&data->update_lock); | ||
| 681 | return -EINVAL; | ||
| 682 | } | 787 | } |
| 683 | 788 | ||
| 684 | mutex_unlock(&data->update_lock); | 789 | mutex_unlock(&data->update_lock); |
| @@ -691,15 +796,19 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, | |||
| 691 | int nr = sensor_attr->index; | 796 | int nr = sensor_attr->index; |
| 692 | 797 | ||
| 693 | struct it87_data *data = dev_get_drvdata(dev); | 798 | struct it87_data *data = dev_get_drvdata(dev); |
| 694 | int val = simple_strtol(buf, NULL, 10); | 799 | long val; |
| 695 | 800 | ||
| 696 | if (val < 0 || val > 255) | 801 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255) |
| 697 | return -EINVAL; | 802 | return -EINVAL; |
| 698 | 803 | ||
| 699 | mutex_lock(&data->update_lock); | 804 | mutex_lock(&data->update_lock); |
| 700 | data->manual_pwm_ctl[nr] = val; | 805 | data->pwm_duty[nr] = PWM_TO_REG(val); |
| 701 | if (data->fan_main_ctrl & (1 << nr)) | 806 | /* If we are in manual mode, write the duty cycle immediately; |
| 702 | it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr])); | 807 | * otherwise, just store it for later use. */ |
| 808 | if (!(data->pwm_ctrl[nr] & 0x80)) { | ||
| 809 | data->pwm_ctrl[nr] = data->pwm_duty[nr]; | ||
| 810 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
| 811 | } | ||
| 703 | mutex_unlock(&data->update_lock); | 812 | mutex_unlock(&data->update_lock); |
| 704 | return count; | 813 | return count; |
| 705 | } | 814 | } |
| @@ -707,9 +816,12 @@ static ssize_t set_pwm_freq(struct device *dev, | |||
| 707 | struct device_attribute *attr, const char *buf, size_t count) | 816 | struct device_attribute *attr, const char *buf, size_t count) |
| 708 | { | 817 | { |
| 709 | struct it87_data *data = dev_get_drvdata(dev); | 818 | struct it87_data *data = dev_get_drvdata(dev); |
| 710 | unsigned long val = simple_strtoul(buf, NULL, 10); | 819 | unsigned long val; |
| 711 | int i; | 820 | int i; |
| 712 | 821 | ||
| 822 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 823 | return -EINVAL; | ||
| 824 | |||
| 713 | /* Search for the nearest available frequency */ | 825 | /* Search for the nearest available frequency */ |
| 714 | for (i = 0; i < 7; i++) { | 826 | for (i = 0; i < 7; i++) { |
| 715 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) | 827 | if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) |
| @@ -724,6 +836,132 @@ static ssize_t set_pwm_freq(struct device *dev, | |||
| 724 | 836 | ||
| 725 | return count; | 837 | return count; |
| 726 | } | 838 | } |
| 839 | static ssize_t show_pwm_temp_map(struct device *dev, | ||
| 840 | struct device_attribute *attr, char *buf) | ||
| 841 | { | ||
| 842 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 843 | int nr = sensor_attr->index; | ||
| 844 | |||
| 845 | struct it87_data *data = it87_update_device(dev); | ||
| 846 | int map; | ||
| 847 | |||
| 848 | if (data->pwm_temp_map[nr] < 3) | ||
| 849 | map = 1 << data->pwm_temp_map[nr]; | ||
| 850 | else | ||
| 851 | map = 0; /* Should never happen */ | ||
| 852 | return sprintf(buf, "%d\n", map); | ||
| 853 | } | ||
| 854 | static ssize_t set_pwm_temp_map(struct device *dev, | ||
| 855 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 856 | { | ||
| 857 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | ||
| 858 | int nr = sensor_attr->index; | ||
| 859 | |||
| 860 | struct it87_data *data = dev_get_drvdata(dev); | ||
| 861 | long val; | ||
| 862 | u8 reg; | ||
| 863 | |||
| 864 | /* This check can go away if we ever support automatic fan speed | ||
| 865 | control on newer chips. */ | ||
| 866 | if (!has_old_autopwm(data)) { | ||
| 867 | dev_notice(dev, "Mapping change disabled for safety reasons\n"); | ||
| 868 | return -EINVAL; | ||
| 869 | } | ||
| 870 | |||
| 871 | if (strict_strtol(buf, 10, &val) < 0) | ||
| 872 | return -EINVAL; | ||
| 873 | |||
| 874 | switch (val) { | ||
| 875 | case (1 << 0): | ||
| 876 | reg = 0x00; | ||
| 877 | break; | ||
| 878 | case (1 << 1): | ||
| 879 | reg = 0x01; | ||
| 880 | break; | ||
| 881 | case (1 << 2): | ||
| 882 | reg = 0x02; | ||
| 883 | break; | ||
| 884 | default: | ||
| 885 | return -EINVAL; | ||
| 886 | } | ||
| 887 | |||
| 888 | mutex_lock(&data->update_lock); | ||
| 889 | data->pwm_temp_map[nr] = reg; | ||
| 890 | /* If we are in automatic mode, write the temp mapping immediately; | ||
| 891 | * otherwise, just store it for later use. */ | ||
| 892 | if (data->pwm_ctrl[nr] & 0x80) { | ||
| 893 | data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; | ||
| 894 | it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); | ||
| 895 | } | ||
| 896 | mutex_unlock(&data->update_lock); | ||
| 897 | return count; | ||
| 898 | } | ||
| 899 | |||
| 900 | static ssize_t show_auto_pwm(struct device *dev, | ||
| 901 | struct device_attribute *attr, char *buf) | ||
| 902 | { | ||
| 903 | struct it87_data *data = it87_update_device(dev); | ||
| 904 | struct sensor_device_attribute_2 *sensor_attr = | ||
| 905 | to_sensor_dev_attr_2(attr); | ||
| 906 | int nr = sensor_attr->nr; | ||
| 907 | int point = sensor_attr->index; | ||
| 908 | |||
| 909 | return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point])); | ||
| 910 | } | ||
| 911 | |||
| 912 | static ssize_t set_auto_pwm(struct device *dev, | ||
| 913 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 914 | { | ||
| 915 | struct it87_data *data = dev_get_drvdata(dev); | ||
| 916 | struct sensor_device_attribute_2 *sensor_attr = | ||
| 917 | to_sensor_dev_attr_2(attr); | ||
| 918 | int nr = sensor_attr->nr; | ||
| 919 | int point = sensor_attr->index; | ||
| 920 | long val; | ||
| 921 | |||
| 922 | if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255) | ||
| 923 | return -EINVAL; | ||
| 924 | |||
| 925 | mutex_lock(&data->update_lock); | ||
| 926 | data->auto_pwm[nr][point] = PWM_TO_REG(val); | ||
| 927 | it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), | ||
| 928 | data->auto_pwm[nr][point]); | ||
| 929 | mutex_unlock(&data->update_lock); | ||
| 930 | return count; | ||
| 931 | } | ||
| 932 | |||
| 933 | static ssize_t show_auto_temp(struct device *dev, | ||
| 934 | struct device_attribute *attr, char *buf) | ||
| 935 | { | ||
| 936 | struct it87_data *data = it87_update_device(dev); | ||
| 937 | struct sensor_device_attribute_2 *sensor_attr = | ||
| 938 | to_sensor_dev_attr_2(attr); | ||
| 939 | int nr = sensor_attr->nr; | ||
| 940 | int point = sensor_attr->index; | ||
| 941 | |||
| 942 | return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point])); | ||
| 943 | } | ||
| 944 | |||
| 945 | static ssize_t set_auto_temp(struct device *dev, | ||
| 946 | struct device_attribute *attr, const char *buf, size_t count) | ||
| 947 | { | ||
| 948 | struct it87_data *data = dev_get_drvdata(dev); | ||
| 949 | struct sensor_device_attribute_2 *sensor_attr = | ||
| 950 | to_sensor_dev_attr_2(attr); | ||
| 951 | int nr = sensor_attr->nr; | ||
| 952 | int point = sensor_attr->index; | ||
| 953 | long val; | ||
| 954 | |||
| 955 | if (strict_strtol(buf, 10, &val) < 0 || val < -128000 || val > 127000) | ||
| 956 | return -EINVAL; | ||
| 957 | |||
| 958 | mutex_lock(&data->update_lock); | ||
| 959 | data->auto_temp[nr][point] = TEMP_TO_REG(val); | ||
| 960 | it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), | ||
| 961 | data->auto_temp[nr][point]); | ||
| 962 | mutex_unlock(&data->update_lock); | ||
| 963 | return count; | ||
| 964 | } | ||
| 727 | 965 | ||
| 728 | #define show_fan_offset(offset) \ | 966 | #define show_fan_offset(offset) \ |
| 729 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ | 967 | static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ |
| @@ -744,7 +982,36 @@ static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ | |||
| 744 | show_pwm, set_pwm, offset - 1); \ | 982 | show_pwm, set_pwm, offset - 1); \ |
| 745 | static DEVICE_ATTR(pwm##offset##_freq, \ | 983 | static DEVICE_ATTR(pwm##offset##_freq, \ |
| 746 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ | 984 | (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ |
| 747 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); | 985 | show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \ |
| 986 | static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \ | ||
| 987 | S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \ | ||
| 988 | offset - 1); \ | ||
| 989 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \ | ||
| 990 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
| 991 | offset - 1, 0); \ | ||
| 992 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \ | ||
| 993 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
| 994 | offset - 1, 1); \ | ||
| 995 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \ | ||
| 996 | S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ | ||
| 997 | offset - 1, 2); \ | ||
| 998 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \ | ||
| 999 | S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \ | ||
| 1000 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \ | ||
| 1001 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
| 1002 | offset - 1, 1); \ | ||
| 1003 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \ | ||
| 1004 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
| 1005 | offset - 1, 0); \ | ||
| 1006 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \ | ||
| 1007 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
| 1008 | offset - 1, 2); \ | ||
| 1009 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \ | ||
| 1010 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
| 1011 | offset - 1, 3); \ | ||
| 1012 | static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \ | ||
| 1013 | S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ | ||
| 1014 | offset - 1, 4); | ||
| 748 | 1015 | ||
| 749 | show_pwm_offset(1); | 1016 | show_pwm_offset(1); |
| 750 | show_pwm_offset(2); | 1017 | show_pwm_offset(2); |
| @@ -775,7 +1042,10 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, | |||
| 775 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); | 1042 | struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); |
| 776 | int nr = sensor_attr->index; | 1043 | int nr = sensor_attr->index; |
| 777 | struct it87_data *data = dev_get_drvdata(dev); | 1044 | struct it87_data *data = dev_get_drvdata(dev); |
| 778 | int val = simple_strtol(buf, NULL, 10); | 1045 | long val; |
| 1046 | |||
| 1047 | if (strict_strtol(buf, 10, &val) < 0) | ||
| 1048 | return -EINVAL; | ||
| 779 | 1049 | ||
| 780 | mutex_lock(&data->update_lock); | 1050 | mutex_lock(&data->update_lock); |
| 781 | data->fan_min[nr] = FAN16_TO_REG(val); | 1051 | data->fan_min[nr] = FAN16_TO_REG(val); |
| @@ -805,7 +1075,8 @@ show_fan16_offset(4); | |||
| 805 | show_fan16_offset(5); | 1075 | show_fan16_offset(5); |
| 806 | 1076 | ||
| 807 | /* Alarms */ | 1077 | /* Alarms */ |
| 808 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 1078 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, |
| 1079 | char *buf) | ||
| 809 | { | 1080 | { |
| 810 | struct it87_data *data = it87_update_device(dev); | 1081 | struct it87_data *data = it87_update_device(dev); |
| 811 | return sprintf(buf, "%u\n", data->alarms); | 1082 | return sprintf(buf, "%u\n", data->alarms); |
| @@ -836,27 +1107,78 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16); | |||
| 836 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); | 1107 | static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); |
| 837 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); | 1108 | static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); |
| 838 | 1109 | ||
| 839 | static ssize_t | 1110 | static ssize_t show_beep(struct device *dev, struct device_attribute *attr, |
| 840 | show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | 1111 | char *buf) |
| 1112 | { | ||
| 1113 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
| 1114 | struct it87_data *data = it87_update_device(dev); | ||
| 1115 | return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); | ||
| 1116 | } | ||
| 1117 | static ssize_t set_beep(struct device *dev, struct device_attribute *attr, | ||
| 1118 | const char *buf, size_t count) | ||
| 1119 | { | ||
| 1120 | int bitnr = to_sensor_dev_attr(attr)->index; | ||
| 1121 | struct it87_data *data = dev_get_drvdata(dev); | ||
| 1122 | long val; | ||
| 1123 | |||
| 1124 | if (strict_strtol(buf, 10, &val) < 0 | ||
| 1125 | || (val != 0 && val != 1)) | ||
| 1126 | return -EINVAL; | ||
| 1127 | |||
| 1128 | mutex_lock(&data->update_lock); | ||
| 1129 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
| 1130 | if (val) | ||
| 1131 | data->beeps |= (1 << bitnr); | ||
| 1132 | else | ||
| 1133 | data->beeps &= ~(1 << bitnr); | ||
| 1134 | it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); | ||
| 1135 | mutex_unlock(&data->update_lock); | ||
| 1136 | return count; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, | ||
| 1140 | show_beep, set_beep, 1); | ||
| 1141 | static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1142 | static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1143 | static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1144 | static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1145 | static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1146 | static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1147 | static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1); | ||
| 1148 | /* fanX_beep writability is set later */ | ||
| 1149 | static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0); | ||
| 1150 | static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0); | ||
| 1151 | static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0); | ||
| 1152 | static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0); | ||
| 1153 | static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0); | ||
| 1154 | static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, | ||
| 1155 | show_beep, set_beep, 2); | ||
| 1156 | static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2); | ||
| 1157 | static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2); | ||
| 1158 | |||
| 1159 | static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, | ||
| 1160 | char *buf) | ||
| 841 | { | 1161 | { |
| 842 | struct it87_data *data = dev_get_drvdata(dev); | 1162 | struct it87_data *data = dev_get_drvdata(dev); |
| 843 | return sprintf(buf, "%u\n", data->vrm); | 1163 | return sprintf(buf, "%u\n", data->vrm); |
| 844 | } | 1164 | } |
| 845 | static ssize_t | 1165 | static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, |
| 846 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 1166 | const char *buf, size_t count) |
| 847 | { | 1167 | { |
| 848 | struct it87_data *data = dev_get_drvdata(dev); | 1168 | struct it87_data *data = dev_get_drvdata(dev); |
| 849 | u32 val; | 1169 | unsigned long val; |
| 1170 | |||
| 1171 | if (strict_strtoul(buf, 10, &val) < 0) | ||
| 1172 | return -EINVAL; | ||
| 850 | 1173 | ||
| 851 | val = simple_strtoul(buf, NULL, 10); | ||
| 852 | data->vrm = val; | 1174 | data->vrm = val; |
| 853 | 1175 | ||
| 854 | return count; | 1176 | return count; |
| 855 | } | 1177 | } |
| 856 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); | 1178 | static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); |
| 857 | 1179 | ||
| 858 | static ssize_t | 1180 | static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, |
| 859 | show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) | 1181 | char *buf) |
| 860 | { | 1182 | { |
| 861 | struct it87_data *data = it87_update_device(dev); | 1183 | struct it87_data *data = it87_update_device(dev); |
| 862 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); | 1184 | return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); |
| @@ -931,51 +1253,176 @@ static const struct attribute_group it87_group = { | |||
| 931 | .attrs = it87_attributes, | 1253 | .attrs = it87_attributes, |
| 932 | }; | 1254 | }; |
| 933 | 1255 | ||
| 934 | static struct attribute *it87_attributes_opt[] = { | 1256 | static struct attribute *it87_attributes_beep[] = { |
| 1257 | &sensor_dev_attr_in0_beep.dev_attr.attr, | ||
| 1258 | &sensor_dev_attr_in1_beep.dev_attr.attr, | ||
| 1259 | &sensor_dev_attr_in2_beep.dev_attr.attr, | ||
| 1260 | &sensor_dev_attr_in3_beep.dev_attr.attr, | ||
| 1261 | &sensor_dev_attr_in4_beep.dev_attr.attr, | ||
| 1262 | &sensor_dev_attr_in5_beep.dev_attr.attr, | ||
| 1263 | &sensor_dev_attr_in6_beep.dev_attr.attr, | ||
| 1264 | &sensor_dev_attr_in7_beep.dev_attr.attr, | ||
| 1265 | |||
| 1266 | &sensor_dev_attr_temp1_beep.dev_attr.attr, | ||
| 1267 | &sensor_dev_attr_temp2_beep.dev_attr.attr, | ||
| 1268 | &sensor_dev_attr_temp3_beep.dev_attr.attr, | ||
| 1269 | NULL | ||
| 1270 | }; | ||
| 1271 | |||
| 1272 | static const struct attribute_group it87_group_beep = { | ||
| 1273 | .attrs = it87_attributes_beep, | ||
| 1274 | }; | ||
| 1275 | |||
| 1276 | static struct attribute *it87_attributes_fan16[5][3+1] = { { | ||
| 935 | &sensor_dev_attr_fan1_input16.dev_attr.attr, | 1277 | &sensor_dev_attr_fan1_input16.dev_attr.attr, |
| 936 | &sensor_dev_attr_fan1_min16.dev_attr.attr, | 1278 | &sensor_dev_attr_fan1_min16.dev_attr.attr, |
| 1279 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
| 1280 | NULL | ||
| 1281 | }, { | ||
| 937 | &sensor_dev_attr_fan2_input16.dev_attr.attr, | 1282 | &sensor_dev_attr_fan2_input16.dev_attr.attr, |
| 938 | &sensor_dev_attr_fan2_min16.dev_attr.attr, | 1283 | &sensor_dev_attr_fan2_min16.dev_attr.attr, |
| 1284 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
| 1285 | NULL | ||
| 1286 | }, { | ||
| 939 | &sensor_dev_attr_fan3_input16.dev_attr.attr, | 1287 | &sensor_dev_attr_fan3_input16.dev_attr.attr, |
| 940 | &sensor_dev_attr_fan3_min16.dev_attr.attr, | 1288 | &sensor_dev_attr_fan3_min16.dev_attr.attr, |
| 1289 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | ||
| 1290 | NULL | ||
| 1291 | }, { | ||
| 941 | &sensor_dev_attr_fan4_input16.dev_attr.attr, | 1292 | &sensor_dev_attr_fan4_input16.dev_attr.attr, |
| 942 | &sensor_dev_attr_fan4_min16.dev_attr.attr, | 1293 | &sensor_dev_attr_fan4_min16.dev_attr.attr, |
| 1294 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | ||
| 1295 | NULL | ||
| 1296 | }, { | ||
| 943 | &sensor_dev_attr_fan5_input16.dev_attr.attr, | 1297 | &sensor_dev_attr_fan5_input16.dev_attr.attr, |
| 944 | &sensor_dev_attr_fan5_min16.dev_attr.attr, | 1298 | &sensor_dev_attr_fan5_min16.dev_attr.attr, |
| 1299 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | ||
| 1300 | NULL | ||
| 1301 | } }; | ||
| 1302 | |||
| 1303 | static const struct attribute_group it87_group_fan16[5] = { | ||
| 1304 | { .attrs = it87_attributes_fan16[0] }, | ||
| 1305 | { .attrs = it87_attributes_fan16[1] }, | ||
| 1306 | { .attrs = it87_attributes_fan16[2] }, | ||
| 1307 | { .attrs = it87_attributes_fan16[3] }, | ||
| 1308 | { .attrs = it87_attributes_fan16[4] }, | ||
| 1309 | }; | ||
| 945 | 1310 | ||
| 1311 | static struct attribute *it87_attributes_fan[3][4+1] = { { | ||
| 946 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 1312 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
| 947 | &sensor_dev_attr_fan1_min.dev_attr.attr, | 1313 | &sensor_dev_attr_fan1_min.dev_attr.attr, |
| 948 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 1314 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
| 1315 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
| 1316 | NULL | ||
| 1317 | }, { | ||
| 949 | &sensor_dev_attr_fan2_input.dev_attr.attr, | 1318 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
| 950 | &sensor_dev_attr_fan2_min.dev_attr.attr, | 1319 | &sensor_dev_attr_fan2_min.dev_attr.attr, |
| 951 | &sensor_dev_attr_fan2_div.dev_attr.attr, | 1320 | &sensor_dev_attr_fan2_div.dev_attr.attr, |
| 1321 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
| 1322 | NULL | ||
| 1323 | }, { | ||
| 952 | &sensor_dev_attr_fan3_input.dev_attr.attr, | 1324 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
| 953 | &sensor_dev_attr_fan3_min.dev_attr.attr, | 1325 | &sensor_dev_attr_fan3_min.dev_attr.attr, |
| 954 | &sensor_dev_attr_fan3_div.dev_attr.attr, | 1326 | &sensor_dev_attr_fan3_div.dev_attr.attr, |
| 955 | |||
| 956 | &sensor_dev_attr_fan1_alarm.dev_attr.attr, | ||
| 957 | &sensor_dev_attr_fan2_alarm.dev_attr.attr, | ||
| 958 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, | 1327 | &sensor_dev_attr_fan3_alarm.dev_attr.attr, |
| 959 | &sensor_dev_attr_fan4_alarm.dev_attr.attr, | 1328 | NULL |
| 960 | &sensor_dev_attr_fan5_alarm.dev_attr.attr, | 1329 | } }; |
| 1330 | |||
| 1331 | static const struct attribute_group it87_group_fan[3] = { | ||
| 1332 | { .attrs = it87_attributes_fan[0] }, | ||
| 1333 | { .attrs = it87_attributes_fan[1] }, | ||
| 1334 | { .attrs = it87_attributes_fan[2] }, | ||
| 1335 | }; | ||
| 1336 | |||
| 1337 | static const struct attribute_group * | ||
| 1338 | it87_get_fan_group(const struct it87_data *data) | ||
| 1339 | { | ||
| 1340 | return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan; | ||
| 1341 | } | ||
| 961 | 1342 | ||
| 1343 | static struct attribute *it87_attributes_pwm[3][4+1] = { { | ||
| 962 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | 1344 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, |
| 963 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
| 964 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
| 965 | &sensor_dev_attr_pwm1.dev_attr.attr, | 1345 | &sensor_dev_attr_pwm1.dev_attr.attr, |
| 966 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
| 967 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 968 | &dev_attr_pwm1_freq.attr, | 1346 | &dev_attr_pwm1_freq.attr, |
| 1347 | &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, | ||
| 1348 | NULL | ||
| 1349 | }, { | ||
| 1350 | &sensor_dev_attr_pwm2_enable.dev_attr.attr, | ||
| 1351 | &sensor_dev_attr_pwm2.dev_attr.attr, | ||
| 969 | &dev_attr_pwm2_freq.attr, | 1352 | &dev_attr_pwm2_freq.attr, |
| 1353 | &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, | ||
| 1354 | NULL | ||
| 1355 | }, { | ||
| 1356 | &sensor_dev_attr_pwm3_enable.dev_attr.attr, | ||
| 1357 | &sensor_dev_attr_pwm3.dev_attr.attr, | ||
| 970 | &dev_attr_pwm3_freq.attr, | 1358 | &dev_attr_pwm3_freq.attr, |
| 1359 | &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, | ||
| 1360 | NULL | ||
| 1361 | } }; | ||
| 1362 | |||
| 1363 | static const struct attribute_group it87_group_pwm[3] = { | ||
| 1364 | { .attrs = it87_attributes_pwm[0] }, | ||
| 1365 | { .attrs = it87_attributes_pwm[1] }, | ||
| 1366 | { .attrs = it87_attributes_pwm[2] }, | ||
| 1367 | }; | ||
| 971 | 1368 | ||
| 1369 | static struct attribute *it87_attributes_autopwm[3][9+1] = { { | ||
| 1370 | &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, | ||
| 1371 | &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, | ||
| 1372 | &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, | ||
| 1373 | &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, | ||
| 1374 | &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, | ||
| 1375 | &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr, | ||
| 1376 | &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, | ||
| 1377 | &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, | ||
| 1378 | &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, | ||
| 1379 | NULL | ||
| 1380 | }, { | ||
| 1381 | &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, | ||
| 1382 | &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, | ||
| 1383 | &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr, | ||
| 1384 | &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr, | ||
| 1385 | &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, | ||
| 1386 | &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr, | ||
| 1387 | &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, | ||
| 1388 | &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, | ||
| 1389 | &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr, | ||
| 1390 | NULL | ||
| 1391 | }, { | ||
| 1392 | &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, | ||
| 1393 | &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, | ||
| 1394 | &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, | ||
| 1395 | &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr, | ||
| 1396 | &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, | ||
| 1397 | &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr, | ||
| 1398 | &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, | ||
| 1399 | &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, | ||
| 1400 | &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, | ||
| 1401 | NULL | ||
| 1402 | } }; | ||
| 1403 | |||
| 1404 | static const struct attribute_group it87_group_autopwm[3] = { | ||
| 1405 | { .attrs = it87_attributes_autopwm[0] }, | ||
| 1406 | { .attrs = it87_attributes_autopwm[1] }, | ||
| 1407 | { .attrs = it87_attributes_autopwm[2] }, | ||
| 1408 | }; | ||
| 1409 | |||
| 1410 | static struct attribute *it87_attributes_fan_beep[] = { | ||
| 1411 | &sensor_dev_attr_fan1_beep.dev_attr.attr, | ||
| 1412 | &sensor_dev_attr_fan2_beep.dev_attr.attr, | ||
| 1413 | &sensor_dev_attr_fan3_beep.dev_attr.attr, | ||
| 1414 | &sensor_dev_attr_fan4_beep.dev_attr.attr, | ||
| 1415 | &sensor_dev_attr_fan5_beep.dev_attr.attr, | ||
| 1416 | }; | ||
| 1417 | |||
| 1418 | static struct attribute *it87_attributes_vid[] = { | ||
| 972 | &dev_attr_vrm.attr, | 1419 | &dev_attr_vrm.attr, |
| 973 | &dev_attr_cpu0_vid.attr, | 1420 | &dev_attr_cpu0_vid.attr, |
| 974 | NULL | 1421 | NULL |
| 975 | }; | 1422 | }; |
| 976 | 1423 | ||
| 977 | static const struct attribute_group it87_group_opt = { | 1424 | static const struct attribute_group it87_group_vid = { |
| 978 | .attrs = it87_attributes_opt, | 1425 | .attrs = it87_attributes_vid, |
| 979 | }; | 1426 | }; |
| 980 | 1427 | ||
| 981 | /* SuperIO detection - will change isa_address if a chip is found */ | 1428 | /* SuperIO detection - will change isa_address if a chip is found */ |
| @@ -1035,6 +1482,10 @@ static int __init it87_find(unsigned short *address, | |||
| 1035 | if (sio_data->type == it87) { | 1482 | if (sio_data->type == it87) { |
| 1036 | /* The IT8705F doesn't have VID pins at all */ | 1483 | /* The IT8705F doesn't have VID pins at all */ |
| 1037 | sio_data->skip_vid = 1; | 1484 | sio_data->skip_vid = 1; |
| 1485 | |||
| 1486 | /* The IT8705F has a different LD number for GPIO */ | ||
| 1487 | superio_select(5); | ||
| 1488 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
| 1038 | } else { | 1489 | } else { |
| 1039 | int reg; | 1490 | int reg; |
| 1040 | 1491 | ||
| @@ -1068,7 +1519,11 @@ static int __init it87_find(unsigned short *address, | |||
| 1068 | pr_info("it87: in3 is VCC (+5V)\n"); | 1519 | pr_info("it87: in3 is VCC (+5V)\n"); |
| 1069 | if (reg & (1 << 1)) | 1520 | if (reg & (1 << 1)) |
| 1070 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); | 1521 | pr_info("it87: in7 is VCCH (+5V Stand-By)\n"); |
| 1522 | |||
| 1523 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | ||
| 1071 | } | 1524 | } |
| 1525 | if (sio_data->beep_pin) | ||
| 1526 | pr_info("it87: Beeping is supported\n"); | ||
| 1072 | 1527 | ||
| 1073 | /* Disable specific features based on DMI strings */ | 1528 | /* Disable specific features based on DMI strings */ |
| 1074 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 1529 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
| @@ -1093,14 +1548,46 @@ exit: | |||
| 1093 | return err; | 1548 | return err; |
| 1094 | } | 1549 | } |
| 1095 | 1550 | ||
| 1551 | static void it87_remove_files(struct device *dev) | ||
| 1552 | { | ||
| 1553 | struct it87_data *data = platform_get_drvdata(pdev); | ||
| 1554 | struct it87_sio_data *sio_data = dev->platform_data; | ||
| 1555 | const struct attribute_group *fan_group = it87_get_fan_group(data); | ||
| 1556 | int i; | ||
| 1557 | |||
| 1558 | sysfs_remove_group(&dev->kobj, &it87_group); | ||
| 1559 | if (sio_data->beep_pin) | ||
| 1560 | sysfs_remove_group(&dev->kobj, &it87_group_beep); | ||
| 1561 | for (i = 0; i < 5; i++) { | ||
| 1562 | if (!(data->has_fan & (1 << i))) | ||
| 1563 | continue; | ||
| 1564 | sysfs_remove_group(&dev->kobj, &fan_group[i]); | ||
| 1565 | if (sio_data->beep_pin) | ||
| 1566 | sysfs_remove_file(&dev->kobj, | ||
| 1567 | it87_attributes_fan_beep[i]); | ||
| 1568 | } | ||
| 1569 | for (i = 0; i < 3; i++) { | ||
| 1570 | if (sio_data->skip_pwm & (1 << 0)) | ||
| 1571 | continue; | ||
| 1572 | sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); | ||
| 1573 | if (has_old_autopwm(data)) | ||
| 1574 | sysfs_remove_group(&dev->kobj, | ||
| 1575 | &it87_group_autopwm[i]); | ||
| 1576 | } | ||
| 1577 | if (!sio_data->skip_vid) | ||
| 1578 | sysfs_remove_group(&dev->kobj, &it87_group_vid); | ||
| 1579 | } | ||
| 1580 | |||
| 1096 | static int __devinit it87_probe(struct platform_device *pdev) | 1581 | static int __devinit it87_probe(struct platform_device *pdev) |
| 1097 | { | 1582 | { |
| 1098 | struct it87_data *data; | 1583 | struct it87_data *data; |
| 1099 | struct resource *res; | 1584 | struct resource *res; |
| 1100 | struct device *dev = &pdev->dev; | 1585 | struct device *dev = &pdev->dev; |
| 1101 | struct it87_sio_data *sio_data = dev->platform_data; | 1586 | struct it87_sio_data *sio_data = dev->platform_data; |
| 1102 | int err = 0; | 1587 | const struct attribute_group *fan_group; |
| 1588 | int err = 0, i; | ||
| 1103 | int enable_pwm_interface; | 1589 | int enable_pwm_interface; |
| 1590 | int fan_beep_need_rw; | ||
| 1104 | static const char *names[] = { | 1591 | static const char *names[] = { |
| 1105 | "it87", | 1592 | "it87", |
| 1106 | "it8712", | 1593 | "it8712", |
| @@ -1118,7 +1605,8 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
| 1118 | goto ERROR0; | 1605 | goto ERROR0; |
| 1119 | } | 1606 | } |
| 1120 | 1607 | ||
| 1121 | if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) { | 1608 | data = kzalloc(sizeof(struct it87_data), GFP_KERNEL); |
| 1609 | if (!data) { | ||
| 1122 | err = -ENOMEM; | 1610 | err = -ENOMEM; |
| 1123 | goto ERROR1; | 1611 | goto ERROR1; |
| 1124 | } | 1612 | } |
| @@ -1146,120 +1634,60 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
| 1146 | it87_init_device(pdev); | 1634 | it87_init_device(pdev); |
| 1147 | 1635 | ||
| 1148 | /* Register sysfs hooks */ | 1636 | /* Register sysfs hooks */ |
| 1149 | if ((err = sysfs_create_group(&dev->kobj, &it87_group))) | 1637 | err = sysfs_create_group(&dev->kobj, &it87_group); |
| 1638 | if (err) | ||
| 1150 | goto ERROR2; | 1639 | goto ERROR2; |
| 1151 | 1640 | ||
| 1641 | if (sio_data->beep_pin) { | ||
| 1642 | err = sysfs_create_group(&dev->kobj, &it87_group_beep); | ||
| 1643 | if (err) | ||
| 1644 | goto ERROR4; | ||
| 1645 | } | ||
| 1646 | |||
| 1152 | /* Do not create fan files for disabled fans */ | 1647 | /* Do not create fan files for disabled fans */ |
| 1153 | if (has_16bit_fans(data)) { | 1648 | fan_group = it87_get_fan_group(data); |
| 1154 | /* 16-bit tachometers */ | 1649 | fan_beep_need_rw = 1; |
| 1155 | if (data->has_fan & (1 << 0)) { | 1650 | for (i = 0; i < 5; i++) { |
| 1156 | if ((err = device_create_file(dev, | 1651 | if (!(data->has_fan & (1 << i))) |
| 1157 | &sensor_dev_attr_fan1_input16.dev_attr)) | 1652 | continue; |
| 1158 | || (err = device_create_file(dev, | 1653 | err = sysfs_create_group(&dev->kobj, &fan_group[i]); |
| 1159 | &sensor_dev_attr_fan1_min16.dev_attr)) | 1654 | if (err) |
| 1160 | || (err = device_create_file(dev, | 1655 | goto ERROR4; |
| 1161 | &sensor_dev_attr_fan1_alarm.dev_attr))) | 1656 | |
| 1162 | goto ERROR4; | 1657 | if (sio_data->beep_pin) { |
| 1163 | } | 1658 | err = sysfs_create_file(&dev->kobj, |
| 1164 | if (data->has_fan & (1 << 1)) { | 1659 | it87_attributes_fan_beep[i]); |
| 1165 | if ((err = device_create_file(dev, | 1660 | if (err) |
| 1166 | &sensor_dev_attr_fan2_input16.dev_attr)) | ||
| 1167 | || (err = device_create_file(dev, | ||
| 1168 | &sensor_dev_attr_fan2_min16.dev_attr)) | ||
| 1169 | || (err = device_create_file(dev, | ||
| 1170 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
| 1171 | goto ERROR4; | ||
| 1172 | } | ||
| 1173 | if (data->has_fan & (1 << 2)) { | ||
| 1174 | if ((err = device_create_file(dev, | ||
| 1175 | &sensor_dev_attr_fan3_input16.dev_attr)) | ||
| 1176 | || (err = device_create_file(dev, | ||
| 1177 | &sensor_dev_attr_fan3_min16.dev_attr)) | ||
| 1178 | || (err = device_create_file(dev, | ||
| 1179 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
| 1180 | goto ERROR4; | ||
| 1181 | } | ||
| 1182 | if (data->has_fan & (1 << 3)) { | ||
| 1183 | if ((err = device_create_file(dev, | ||
| 1184 | &sensor_dev_attr_fan4_input16.dev_attr)) | ||
| 1185 | || (err = device_create_file(dev, | ||
| 1186 | &sensor_dev_attr_fan4_min16.dev_attr)) | ||
| 1187 | || (err = device_create_file(dev, | ||
| 1188 | &sensor_dev_attr_fan4_alarm.dev_attr))) | ||
| 1189 | goto ERROR4; | ||
| 1190 | } | ||
| 1191 | if (data->has_fan & (1 << 4)) { | ||
| 1192 | if ((err = device_create_file(dev, | ||
| 1193 | &sensor_dev_attr_fan5_input16.dev_attr)) | ||
| 1194 | || (err = device_create_file(dev, | ||
| 1195 | &sensor_dev_attr_fan5_min16.dev_attr)) | ||
| 1196 | || (err = device_create_file(dev, | ||
| 1197 | &sensor_dev_attr_fan5_alarm.dev_attr))) | ||
| 1198 | goto ERROR4; | ||
| 1199 | } | ||
| 1200 | } else { | ||
| 1201 | /* 8-bit tachometers with clock divider */ | ||
| 1202 | if (data->has_fan & (1 << 0)) { | ||
| 1203 | if ((err = device_create_file(dev, | ||
| 1204 | &sensor_dev_attr_fan1_input.dev_attr)) | ||
| 1205 | || (err = device_create_file(dev, | ||
| 1206 | &sensor_dev_attr_fan1_min.dev_attr)) | ||
| 1207 | || (err = device_create_file(dev, | ||
| 1208 | &sensor_dev_attr_fan1_div.dev_attr)) | ||
| 1209 | || (err = device_create_file(dev, | ||
| 1210 | &sensor_dev_attr_fan1_alarm.dev_attr))) | ||
| 1211 | goto ERROR4; | ||
| 1212 | } | ||
| 1213 | if (data->has_fan & (1 << 1)) { | ||
| 1214 | if ((err = device_create_file(dev, | ||
| 1215 | &sensor_dev_attr_fan2_input.dev_attr)) | ||
| 1216 | || (err = device_create_file(dev, | ||
| 1217 | &sensor_dev_attr_fan2_min.dev_attr)) | ||
| 1218 | || (err = device_create_file(dev, | ||
| 1219 | &sensor_dev_attr_fan2_div.dev_attr)) | ||
| 1220 | || (err = device_create_file(dev, | ||
| 1221 | &sensor_dev_attr_fan2_alarm.dev_attr))) | ||
| 1222 | goto ERROR4; | ||
| 1223 | } | ||
| 1224 | if (data->has_fan & (1 << 2)) { | ||
| 1225 | if ((err = device_create_file(dev, | ||
| 1226 | &sensor_dev_attr_fan3_input.dev_attr)) | ||
| 1227 | || (err = device_create_file(dev, | ||
| 1228 | &sensor_dev_attr_fan3_min.dev_attr)) | ||
| 1229 | || (err = device_create_file(dev, | ||
| 1230 | &sensor_dev_attr_fan3_div.dev_attr)) | ||
| 1231 | || (err = device_create_file(dev, | ||
| 1232 | &sensor_dev_attr_fan3_alarm.dev_attr))) | ||
| 1233 | goto ERROR4; | 1661 | goto ERROR4; |
| 1662 | if (!fan_beep_need_rw) | ||
| 1663 | continue; | ||
| 1664 | |||
| 1665 | /* As we have a single beep enable bit for all fans, | ||
| 1666 | * only the first enabled fan has a writable attribute | ||
| 1667 | * for it. */ | ||
| 1668 | if (sysfs_chmod_file(&dev->kobj, | ||
| 1669 | it87_attributes_fan_beep[i], | ||
| 1670 | S_IRUGO | S_IWUSR)) | ||
| 1671 | dev_dbg(dev, "chmod +w fan%d_beep failed\n", | ||
| 1672 | i + 1); | ||
| 1673 | fan_beep_need_rw = 0; | ||
| 1234 | } | 1674 | } |
| 1235 | } | 1675 | } |
| 1236 | 1676 | ||
| 1237 | if (enable_pwm_interface) { | 1677 | if (enable_pwm_interface) { |
| 1238 | if (!(sio_data->skip_pwm & (1 << 0))) { | 1678 | for (i = 0; i < 3; i++) { |
| 1239 | if ((err = device_create_file(dev, | 1679 | if (sio_data->skip_pwm & (1 << i)) |
| 1240 | &sensor_dev_attr_pwm1_enable.dev_attr)) | 1680 | continue; |
| 1241 | || (err = device_create_file(dev, | 1681 | err = sysfs_create_group(&dev->kobj, |
| 1242 | &sensor_dev_attr_pwm1.dev_attr)) | 1682 | &it87_group_pwm[i]); |
| 1243 | || (err = device_create_file(dev, | 1683 | if (err) |
| 1244 | &dev_attr_pwm1_freq))) | ||
| 1245 | goto ERROR4; | ||
| 1246 | } | ||
| 1247 | if (!(sio_data->skip_pwm & (1 << 1))) { | ||
| 1248 | if ((err = device_create_file(dev, | ||
| 1249 | &sensor_dev_attr_pwm2_enable.dev_attr)) | ||
| 1250 | || (err = device_create_file(dev, | ||
| 1251 | &sensor_dev_attr_pwm2.dev_attr)) | ||
| 1252 | || (err = device_create_file(dev, | ||
| 1253 | &dev_attr_pwm2_freq))) | ||
| 1254 | goto ERROR4; | 1684 | goto ERROR4; |
| 1255 | } | 1685 | |
| 1256 | if (!(sio_data->skip_pwm & (1 << 2))) { | 1686 | if (!has_old_autopwm(data)) |
| 1257 | if ((err = device_create_file(dev, | 1687 | continue; |
| 1258 | &sensor_dev_attr_pwm3_enable.dev_attr)) | 1688 | err = sysfs_create_group(&dev->kobj, |
| 1259 | || (err = device_create_file(dev, | 1689 | &it87_group_autopwm[i]); |
| 1260 | &sensor_dev_attr_pwm3.dev_attr)) | 1690 | if (err) |
| 1261 | || (err = device_create_file(dev, | ||
| 1262 | &dev_attr_pwm3_freq))) | ||
| 1263 | goto ERROR4; | 1691 | goto ERROR4; |
| 1264 | } | 1692 | } |
| 1265 | } | 1693 | } |
| @@ -1268,10 +1696,8 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
| 1268 | data->vrm = vid_which_vrm(); | 1696 | data->vrm = vid_which_vrm(); |
| 1269 | /* VID reading from Super-I/O config space if available */ | 1697 | /* VID reading from Super-I/O config space if available */ |
| 1270 | data->vid = sio_data->vid_value; | 1698 | data->vid = sio_data->vid_value; |
| 1271 | if ((err = device_create_file(dev, | 1699 | err = sysfs_create_group(&dev->kobj, &it87_group_vid); |
| 1272 | &dev_attr_vrm)) | 1700 | if (err) |
| 1273 | || (err = device_create_file(dev, | ||
| 1274 | &dev_attr_cpu0_vid))) | ||
| 1275 | goto ERROR4; | 1701 | goto ERROR4; |
| 1276 | } | 1702 | } |
| 1277 | 1703 | ||
| @@ -1284,8 +1710,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
| 1284 | return 0; | 1710 | return 0; |
| 1285 | 1711 | ||
| 1286 | ERROR4: | 1712 | ERROR4: |
| 1287 | sysfs_remove_group(&dev->kobj, &it87_group); | 1713 | it87_remove_files(dev); |
| 1288 | sysfs_remove_group(&dev->kobj, &it87_group_opt); | ||
| 1289 | ERROR2: | 1714 | ERROR2: |
| 1290 | platform_set_drvdata(pdev, NULL); | 1715 | platform_set_drvdata(pdev, NULL); |
| 1291 | kfree(data); | 1716 | kfree(data); |
| @@ -1300,8 +1725,7 @@ static int __devexit it87_remove(struct platform_device *pdev) | |||
| 1300 | struct it87_data *data = platform_get_drvdata(pdev); | 1725 | struct it87_data *data = platform_get_drvdata(pdev); |
| 1301 | 1726 | ||
| 1302 | hwmon_device_unregister(data->hwmon_dev); | 1727 | hwmon_device_unregister(data->hwmon_dev); |
| 1303 | sysfs_remove_group(&pdev->dev.kobj, &it87_group); | 1728 | it87_remove_files(&pdev->dev); |
| 1304 | sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt); | ||
| 1305 | 1729 | ||
| 1306 | release_region(data->addr, IT87_EC_EXTENT); | 1730 | release_region(data->addr, IT87_EC_EXTENT); |
| 1307 | platform_set_drvdata(pdev, NULL); | 1731 | platform_set_drvdata(pdev, NULL); |
| @@ -1387,15 +1811,18 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
| 1387 | int tmp, i; | 1811 | int tmp, i; |
| 1388 | u8 mask; | 1812 | u8 mask; |
| 1389 | 1813 | ||
| 1390 | /* initialize to sane defaults: | 1814 | /* For each PWM channel: |
| 1391 | * - if the chip is in manual pwm mode, this will be overwritten with | 1815 | * - If it is in automatic mode, setting to manual mode should set |
| 1392 | * the actual settings on the chip (so in this case, initialization | 1816 | * the fan to full speed by default. |
| 1393 | * is not needed) | 1817 | * - If it is in manual mode, we need a mapping to temperature |
| 1394 | * - if in automatic or on/off mode, we could switch to manual mode, | 1818 | * channels to use when later setting to automatic mode later. |
| 1395 | * read the registers and set manual_pwm_ctl accordingly, but currently | 1819 | * Use a 1:1 mapping by default (we are clueless.) |
| 1396 | * this is not implemented, so we initialize to something sane */ | 1820 | * In both cases, the value can (and should) be changed by the user |
| 1821 | * prior to switching to a different mode. */ | ||
| 1397 | for (i = 0; i < 3; i++) { | 1822 | for (i = 0; i < 3; i++) { |
| 1398 | data->manual_pwm_ctl[i] = 0xff; | 1823 | data->pwm_temp_map[i] = i; |
| 1824 | data->pwm_duty[i] = 0x7f; /* Full speed */ | ||
| 1825 | data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ | ||
| 1399 | } | 1826 | } |
| 1400 | 1827 | ||
| 1401 | /* Some chips seem to have default value 0xff for all limit | 1828 | /* Some chips seem to have default value 0xff for all limit |
| @@ -1436,7 +1863,8 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
| 1436 | if ((data->fan_main_ctrl & mask) == 0) { | 1863 | if ((data->fan_main_ctrl & mask) == 0) { |
| 1437 | /* Enable all fan tachometers */ | 1864 | /* Enable all fan tachometers */ |
| 1438 | data->fan_main_ctrl |= mask; | 1865 | data->fan_main_ctrl |= mask; |
| 1439 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); | 1866 | it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, |
| 1867 | data->fan_main_ctrl); | ||
| 1440 | } | 1868 | } |
| 1441 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; | 1869 | data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; |
| 1442 | 1870 | ||
| @@ -1461,30 +1889,32 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
| 1461 | /* Fan input pins may be used for alternative functions */ | 1889 | /* Fan input pins may be used for alternative functions */ |
| 1462 | data->has_fan &= ~sio_data->skip_fan; | 1890 | data->has_fan &= ~sio_data->skip_fan; |
| 1463 | 1891 | ||
| 1464 | /* Set current fan mode registers and the default settings for the | ||
| 1465 | * other mode registers */ | ||
| 1466 | for (i = 0; i < 3; i++) { | ||
| 1467 | if (data->fan_main_ctrl & (1 << i)) { | ||
| 1468 | /* pwm mode */ | ||
| 1469 | tmp = it87_read_value(data, IT87_REG_PWM(i)); | ||
| 1470 | if (tmp & 0x80) { | ||
| 1471 | /* automatic pwm - not yet implemented, but | ||
| 1472 | * leave the settings made by the BIOS alone | ||
| 1473 | * until a change is requested via the sysfs | ||
| 1474 | * interface */ | ||
| 1475 | } else { | ||
| 1476 | /* manual pwm */ | ||
| 1477 | data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp); | ||
| 1478 | } | ||
| 1479 | } | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | /* Start monitoring */ | 1892 | /* Start monitoring */ |
| 1483 | it87_write_value(data, IT87_REG_CONFIG, | 1893 | it87_write_value(data, IT87_REG_CONFIG, |
| 1484 | (it87_read_value(data, IT87_REG_CONFIG) & 0x36) | 1894 | (it87_read_value(data, IT87_REG_CONFIG) & 0x36) |
| 1485 | | (update_vbat ? 0x41 : 0x01)); | 1895 | | (update_vbat ? 0x41 : 0x01)); |
| 1486 | } | 1896 | } |
| 1487 | 1897 | ||
| 1898 | static void it87_update_pwm_ctrl(struct it87_data *data, int nr) | ||
| 1899 | { | ||
| 1900 | data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); | ||
| 1901 | if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ | ||
| 1902 | data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; | ||
| 1903 | else /* Manual mode */ | ||
| 1904 | data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; | ||
| 1905 | |||
| 1906 | if (has_old_autopwm(data)) { | ||
| 1907 | int i; | ||
| 1908 | |||
| 1909 | for (i = 0; i < 5 ; i++) | ||
| 1910 | data->auto_temp[nr][i] = it87_read_value(data, | ||
| 1911 | IT87_REG_AUTO_TEMP(nr, i)); | ||
| 1912 | for (i = 0; i < 3 ; i++) | ||
| 1913 | data->auto_pwm[nr][i] = it87_read_value(data, | ||
| 1914 | IT87_REG_AUTO_PWM(nr, i)); | ||
| 1915 | } | ||
| 1916 | } | ||
| 1917 | |||
| 1488 | static struct it87_data *it87_update_device(struct device *dev) | 1918 | static struct it87_data *it87_update_device(struct device *dev) |
| 1489 | { | 1919 | { |
| 1490 | struct it87_data *data = dev_get_drvdata(dev); | 1920 | struct it87_data *data = dev_get_drvdata(dev); |
| @@ -1494,24 +1924,22 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 1494 | 1924 | ||
| 1495 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 1925 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) |
| 1496 | || !data->valid) { | 1926 | || !data->valid) { |
| 1497 | |||
| 1498 | if (update_vbat) { | 1927 | if (update_vbat) { |
| 1499 | /* Cleared after each update, so reenable. Value | 1928 | /* Cleared after each update, so reenable. Value |
| 1500 | returned by this read will be previous value */ | 1929 | returned by this read will be previous value */ |
| 1501 | it87_write_value(data, IT87_REG_CONFIG, | 1930 | it87_write_value(data, IT87_REG_CONFIG, |
| 1502 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); | 1931 | it87_read_value(data, IT87_REG_CONFIG) | 0x40); |
| 1503 | } | 1932 | } |
| 1504 | for (i = 0; i <= 7; i++) { | 1933 | for (i = 0; i <= 7; i++) { |
| 1505 | data->in[i] = | 1934 | data->in[i] = |
| 1506 | it87_read_value(data, IT87_REG_VIN(i)); | 1935 | it87_read_value(data, IT87_REG_VIN(i)); |
| 1507 | data->in_min[i] = | 1936 | data->in_min[i] = |
| 1508 | it87_read_value(data, IT87_REG_VIN_MIN(i)); | 1937 | it87_read_value(data, IT87_REG_VIN_MIN(i)); |
| 1509 | data->in_max[i] = | 1938 | data->in_max[i] = |
| 1510 | it87_read_value(data, IT87_REG_VIN_MAX(i)); | 1939 | it87_read_value(data, IT87_REG_VIN_MAX(i)); |
| 1511 | } | 1940 | } |
| 1512 | /* in8 (battery) has no limit registers */ | 1941 | /* in8 (battery) has no limit registers */ |
| 1513 | data->in[8] = | 1942 | data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); |
| 1514 | it87_read_value(data, IT87_REG_VIN(8)); | ||
| 1515 | 1943 | ||
| 1516 | for (i = 0; i < 5; i++) { | 1944 | for (i = 0; i < 5; i++) { |
| 1517 | /* Skip disabled fans */ | 1945 | /* Skip disabled fans */ |
| @@ -1519,7 +1947,7 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 1519 | continue; | 1947 | continue; |
| 1520 | 1948 | ||
| 1521 | data->fan_min[i] = | 1949 | data->fan_min[i] = |
| 1522 | it87_read_value(data, IT87_REG_FAN_MIN[i]); | 1950 | it87_read_value(data, IT87_REG_FAN_MIN[i]); |
| 1523 | data->fan[i] = it87_read_value(data, | 1951 | data->fan[i] = it87_read_value(data, |
| 1524 | IT87_REG_FAN[i]); | 1952 | IT87_REG_FAN[i]); |
| 1525 | /* Add high byte if in 16-bit mode */ | 1953 | /* Add high byte if in 16-bit mode */ |
| @@ -1532,11 +1960,11 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 1532 | } | 1960 | } |
| 1533 | for (i = 0; i < 3; i++) { | 1961 | for (i = 0; i < 3; i++) { |
| 1534 | data->temp[i] = | 1962 | data->temp[i] = |
| 1535 | it87_read_value(data, IT87_REG_TEMP(i)); | 1963 | it87_read_value(data, IT87_REG_TEMP(i)); |
| 1536 | data->temp_high[i] = | 1964 | data->temp_high[i] = |
| 1537 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); | 1965 | it87_read_value(data, IT87_REG_TEMP_HIGH(i)); |
| 1538 | data->temp_low[i] = | 1966 | data->temp_low[i] = |
| 1539 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); | 1967 | it87_read_value(data, IT87_REG_TEMP_LOW(i)); |
| 1540 | } | 1968 | } |
| 1541 | 1969 | ||
| 1542 | /* Newer chips don't have clock dividers */ | 1970 | /* Newer chips don't have clock dividers */ |
| @@ -1551,9 +1979,13 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
| 1551 | it87_read_value(data, IT87_REG_ALARM1) | | 1979 | it87_read_value(data, IT87_REG_ALARM1) | |
| 1552 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | | 1980 | (it87_read_value(data, IT87_REG_ALARM2) << 8) | |
| 1553 | (it87_read_value(data, IT87_REG_ALARM3) << 16); | 1981 | (it87_read_value(data, IT87_REG_ALARM3) << 16); |
| 1982 | data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); | ||
| 1983 | |||
| 1554 | data->fan_main_ctrl = it87_read_value(data, | 1984 | data->fan_main_ctrl = it87_read_value(data, |
| 1555 | IT87_REG_FAN_MAIN_CTRL); | 1985 | IT87_REG_FAN_MAIN_CTRL); |
| 1556 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); | 1986 | data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); |
| 1987 | for (i = 0; i < 3; i++) | ||
| 1988 | it87_update_pwm_ctrl(data, i); | ||
| 1557 | 1989 | ||
| 1558 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1990 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
| 1559 | /* The 8705 does not have VID capability. | 1991 | /* The 8705 does not have VID capability. |
| @@ -1628,7 +2060,7 @@ exit: | |||
| 1628 | static int __init sm_it87_init(void) | 2060 | static int __init sm_it87_init(void) |
| 1629 | { | 2061 | { |
| 1630 | int err; | 2062 | int err; |
| 1631 | unsigned short isa_address=0; | 2063 | unsigned short isa_address = 0; |
| 1632 | struct it87_sio_data sio_data; | 2064 | struct it87_sio_data sio_data; |
| 1633 | 2065 | ||
| 1634 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); | 2066 | memset(&sio_data, 0, sizeof(struct it87_sio_data)); |
| @@ -1640,7 +2072,7 @@ static int __init sm_it87_init(void) | |||
| 1640 | return err; | 2072 | return err; |
| 1641 | 2073 | ||
| 1642 | err = it87_device_add(isa_address, &sio_data); | 2074 | err = it87_device_add(isa_address, &sio_data); |
| 1643 | if (err){ | 2075 | if (err) { |
| 1644 | platform_driver_unregister(&it87_driver); | 2076 | platform_driver_unregister(&it87_driver); |
| 1645 | return err; | 2077 | return err; |
| 1646 | } | 2078 | } |
| @@ -1661,7 +2093,8 @@ MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver"); | |||
| 1661 | module_param(update_vbat, bool, 0); | 2093 | module_param(update_vbat, bool, 0); |
| 1662 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 2094 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
| 1663 | module_param(fix_pwm_polarity, bool, 0); | 2095 | module_param(fix_pwm_polarity, bool, 0); |
| 1664 | MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)"); | 2096 | MODULE_PARM_DESC(fix_pwm_polarity, |
| 2097 | "Force PWM polarity to active high (DANGEROUS)"); | ||
| 1665 | MODULE_LICENSE("GPL"); | 2098 | MODULE_LICENSE("GPL"); |
| 1666 | 2099 | ||
| 1667 | module_init(sm_it87_init); | 2100 | module_init(sm_it87_init); |
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 7c9bdc167426..7cc2708871ab 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * lm90.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | * lm90.c - Part of lm_sensors, Linux kernel modules for hardware |
| 3 | * monitoring | 3 | * monitoring |
| 4 | * Copyright (C) 2003-2009 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> |
| 5 | * | 5 | * |
| 6 | * Based on the lm83 driver. The LM90 is a sensor chip made by National | 6 | * Based on the lm83 driver. The LM90 is a sensor chip made by National |
| 7 | * Semiconductor. It reports up to two temperatures (its own plus up to | 7 | * Semiconductor. It reports up to two temperatures (its own plus up to |
| @@ -93,7 +93,8 @@ | |||
| 93 | static const unsigned short normal_i2c[] = { | 93 | static const unsigned short normal_i2c[] = { |
| 94 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; | 94 | 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; |
| 95 | 95 | ||
| 96 | enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646 }; | 96 | enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646, |
| 97 | w83l771 }; | ||
| 97 | 98 | ||
| 98 | /* | 99 | /* |
| 99 | * The LM90 registers | 100 | * The LM90 registers |
| @@ -151,6 +152,7 @@ static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info); | |||
| 151 | static int lm90_probe(struct i2c_client *client, | 152 | static int lm90_probe(struct i2c_client *client, |
| 152 | const struct i2c_device_id *id); | 153 | const struct i2c_device_id *id); |
| 153 | static void lm90_init_client(struct i2c_client *client); | 154 | static void lm90_init_client(struct i2c_client *client); |
| 155 | static void lm90_alert(struct i2c_client *client, unsigned int flag); | ||
| 154 | static int lm90_remove(struct i2c_client *client); | 156 | static int lm90_remove(struct i2c_client *client); |
| 155 | static struct lm90_data *lm90_update_device(struct device *dev); | 157 | static struct lm90_data *lm90_update_device(struct device *dev); |
| 156 | 158 | ||
| @@ -173,6 +175,7 @@ static const struct i2c_device_id lm90_id[] = { | |||
| 173 | { "max6659", max6657 }, | 175 | { "max6659", max6657 }, |
| 174 | { "max6680", max6680 }, | 176 | { "max6680", max6680 }, |
| 175 | { "max6681", max6680 }, | 177 | { "max6681", max6680 }, |
| 178 | { "w83l771", w83l771 }, | ||
| 176 | { } | 179 | { } |
| 177 | }; | 180 | }; |
| 178 | MODULE_DEVICE_TABLE(i2c, lm90_id); | 181 | MODULE_DEVICE_TABLE(i2c, lm90_id); |
| @@ -184,6 +187,7 @@ static struct i2c_driver lm90_driver = { | |||
| 184 | }, | 187 | }, |
| 185 | .probe = lm90_probe, | 188 | .probe = lm90_probe, |
| 186 | .remove = lm90_remove, | 189 | .remove = lm90_remove, |
| 190 | .alert = lm90_alert, | ||
| 187 | .id_table = lm90_id, | 191 | .id_table = lm90_id, |
| 188 | .detect = lm90_detect, | 192 | .detect = lm90_detect, |
| 189 | .address_list = normal_i2c, | 193 | .address_list = normal_i2c, |
| @@ -201,6 +205,9 @@ struct lm90_data { | |||
| 201 | int kind; | 205 | int kind; |
| 202 | int flags; | 206 | int flags; |
| 203 | 207 | ||
| 208 | u8 config_orig; /* Original configuration register value */ | ||
| 209 | u8 alert_alarms; /* Which alarm bits trigger ALERT# */ | ||
| 210 | |||
| 204 | /* registers values */ | 211 | /* registers values */ |
| 205 | s8 temp8[4]; /* 0: local low limit | 212 | s8 temp8[4]; /* 0: local low limit |
| 206 | 1: local high limit | 213 | 1: local high limit |
| @@ -758,6 +765,14 @@ static int lm90_detect(struct i2c_client *new_client, | |||
| 758 | && reg_convrate <= 0x07) { | 765 | && reg_convrate <= 0x07) { |
| 759 | name = "max6646"; | 766 | name = "max6646"; |
| 760 | } | 767 | } |
| 768 | } else | ||
| 769 | if (address == 0x4C | ||
| 770 | && man_id == 0x5C) { /* Winbond/Nuvoton */ | ||
| 771 | if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */ | ||
| 772 | && (reg_config1 & 0x2A) == 0x00 | ||
| 773 | && reg_convrate <= 0x08) { | ||
| 774 | name = "w83l771"; | ||
| 775 | } | ||
| 761 | } | 776 | } |
| 762 | 777 | ||
| 763 | if (!name) { /* identification failed */ | 778 | if (!name) { /* identification failed */ |
| @@ -794,6 +809,19 @@ static int lm90_probe(struct i2c_client *new_client, | |||
| 794 | new_client->flags &= ~I2C_CLIENT_PEC; | 809 | new_client->flags &= ~I2C_CLIENT_PEC; |
| 795 | } | 810 | } |
| 796 | 811 | ||
| 812 | /* Different devices have different alarm bits triggering the | ||
| 813 | * ALERT# output */ | ||
| 814 | switch (data->kind) { | ||
| 815 | case lm90: | ||
| 816 | case lm99: | ||
| 817 | case lm86: | ||
| 818 | data->alert_alarms = 0x7b; | ||
| 819 | break; | ||
| 820 | default: | ||
| 821 | data->alert_alarms = 0x7c; | ||
| 822 | break; | ||
| 823 | } | ||
| 824 | |||
| 797 | /* Initialize the LM90 chip */ | 825 | /* Initialize the LM90 chip */ |
| 798 | lm90_init_client(new_client); | 826 | lm90_init_client(new_client); |
| 799 | 827 | ||
| @@ -830,7 +858,7 @@ exit: | |||
| 830 | 858 | ||
| 831 | static void lm90_init_client(struct i2c_client *client) | 859 | static void lm90_init_client(struct i2c_client *client) |
| 832 | { | 860 | { |
| 833 | u8 config, config_orig; | 861 | u8 config; |
| 834 | struct lm90_data *data = i2c_get_clientdata(client); | 862 | struct lm90_data *data = i2c_get_clientdata(client); |
| 835 | 863 | ||
| 836 | /* | 864 | /* |
| @@ -842,7 +870,7 @@ static void lm90_init_client(struct i2c_client *client) | |||
| 842 | dev_warn(&client->dev, "Initialization failed!\n"); | 870 | dev_warn(&client->dev, "Initialization failed!\n"); |
| 843 | return; | 871 | return; |
| 844 | } | 872 | } |
| 845 | config_orig = config; | 873 | data->config_orig = config; |
| 846 | 874 | ||
| 847 | /* Check Temperature Range Select */ | 875 | /* Check Temperature Range Select */ |
| 848 | if (data->kind == adt7461) { | 876 | if (data->kind == adt7461) { |
| @@ -860,7 +888,7 @@ static void lm90_init_client(struct i2c_client *client) | |||
| 860 | } | 888 | } |
| 861 | 889 | ||
| 862 | config &= 0xBF; /* run */ | 890 | config &= 0xBF; /* run */ |
| 863 | if (config != config_orig) /* Only write if changed */ | 891 | if (config != data->config_orig) /* Only write if changed */ |
| 864 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); | 892 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); |
| 865 | } | 893 | } |
| 866 | 894 | ||
| @@ -875,10 +903,46 @@ static int lm90_remove(struct i2c_client *client) | |||
| 875 | device_remove_file(&client->dev, | 903 | device_remove_file(&client->dev, |
| 876 | &sensor_dev_attr_temp2_offset.dev_attr); | 904 | &sensor_dev_attr_temp2_offset.dev_attr); |
| 877 | 905 | ||
| 906 | /* Restore initial configuration */ | ||
| 907 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, | ||
| 908 | data->config_orig); | ||
| 909 | |||
| 878 | kfree(data); | 910 | kfree(data); |
| 879 | return 0; | 911 | return 0; |
| 880 | } | 912 | } |
| 881 | 913 | ||
| 914 | static void lm90_alert(struct i2c_client *client, unsigned int flag) | ||
| 915 | { | ||
| 916 | struct lm90_data *data = i2c_get_clientdata(client); | ||
| 917 | u8 config, alarms; | ||
| 918 | |||
| 919 | lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); | ||
| 920 | if ((alarms & 0x7f) == 0) { | ||
| 921 | dev_info(&client->dev, "Everything OK\n"); | ||
| 922 | } else { | ||
| 923 | if (alarms & 0x61) | ||
| 924 | dev_warn(&client->dev, | ||
| 925 | "temp%d out of range, please check!\n", 1); | ||
| 926 | if (alarms & 0x1a) | ||
| 927 | dev_warn(&client->dev, | ||
| 928 | "temp%d out of range, please check!\n", 2); | ||
| 929 | if (alarms & 0x04) | ||
| 930 | dev_warn(&client->dev, | ||
| 931 | "temp%d diode open, please check!\n", 2); | ||
| 932 | |||
| 933 | /* Disable ALERT# output, because these chips don't implement | ||
| 934 | SMBus alert correctly; they should only hold the alert line | ||
| 935 | low briefly. */ | ||
| 936 | if ((data->kind == adm1032 || data->kind == adt7461) | ||
| 937 | && (alarms & data->alert_alarms)) { | ||
| 938 | dev_dbg(&client->dev, "Disabling ALERT#\n"); | ||
| 939 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); | ||
| 940 | i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, | ||
| 941 | config | 0x80); | ||
| 942 | } | ||
| 943 | } | ||
| 944 | } | ||
| 945 | |||
| 882 | static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) | 946 | static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) |
| 883 | { | 947 | { |
| 884 | int err; | 948 | int err; |
| @@ -966,6 +1030,21 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
| 966 | } | 1030 | } |
| 967 | lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); | 1031 | lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms); |
| 968 | 1032 | ||
| 1033 | /* Re-enable ALERT# output if it was originally enabled and | ||
| 1034 | * relevant alarms are all clear */ | ||
| 1035 | if ((data->config_orig & 0x80) == 0 | ||
| 1036 | && (data->alarms & data->alert_alarms) == 0) { | ||
| 1037 | u8 config; | ||
| 1038 | |||
| 1039 | lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); | ||
| 1040 | if (config & 0x80) { | ||
| 1041 | dev_dbg(&client->dev, "Re-enabling ALERT#\n"); | ||
| 1042 | i2c_smbus_write_byte_data(client, | ||
| 1043 | LM90_REG_W_CONFIG1, | ||
| 1044 | config & ~0x80); | ||
| 1045 | } | ||
| 1046 | } | ||
| 1047 | |||
| 969 | data->last_updated = jiffies; | 1048 | data->last_updated = jiffies; |
| 970 | data->valid = 1; | 1049 | data->valid = 1; |
| 971 | } | 1050 | } |
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index a13b30e8d8d8..d14a1af9f550 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c | |||
| @@ -134,7 +134,7 @@ struct tmp401_data { | |||
| 134 | struct mutex update_lock; | 134 | struct mutex update_lock; |
| 135 | char valid; /* zero until following fields are valid */ | 135 | char valid; /* zero until following fields are valid */ |
| 136 | unsigned long last_updated; /* in jiffies */ | 136 | unsigned long last_updated; /* in jiffies */ |
| 137 | int kind; | 137 | enum chips kind; |
| 138 | 138 | ||
| 139 | /* register values */ | 139 | /* register values */ |
| 140 | u8 status; | 140 | u8 status; |
| @@ -524,7 +524,7 @@ static int tmp401_detect(struct i2c_client *client, | |||
| 524 | if (reg > 15) | 524 | if (reg > 15) |
| 525 | return -ENODEV; | 525 | return -ENODEV; |
| 526 | 526 | ||
| 527 | strlcpy(info->type, tmp401_id[kind - 1].name, I2C_NAME_SIZE); | 527 | strlcpy(info->type, tmp401_id[kind].name, I2C_NAME_SIZE); |
| 528 | 528 | ||
| 529 | return 0; | 529 | return 0; |
| 530 | } | 530 | } |
| @@ -572,8 +572,7 @@ static int tmp401_probe(struct i2c_client *client, | |||
| 572 | goto exit_remove; | 572 | goto exit_remove; |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | dev_info(&client->dev, "Detected TI %s chip\n", | 575 | dev_info(&client->dev, "Detected TI %s chip\n", names[data->kind]); |
| 576 | names[data->kind - 1]); | ||
| 577 | 576 | ||
| 578 | return 0; | 577 | return 0; |
| 579 | 578 | ||
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 4f7c051e2d7b..738c472ece27 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c | |||
| @@ -61,9 +61,9 @@ static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 }; | |||
| 61 | #define TMP423_DEVICE_ID 0x23 | 61 | #define TMP423_DEVICE_ID 0x23 |
| 62 | 62 | ||
| 63 | static const struct i2c_device_id tmp421_id[] = { | 63 | static const struct i2c_device_id tmp421_id[] = { |
| 64 | { "tmp421", tmp421 }, | 64 | { "tmp421", 2 }, |
| 65 | { "tmp422", tmp422 }, | 65 | { "tmp422", 3 }, |
| 66 | { "tmp423", tmp423 }, | 66 | { "tmp423", 4 }, |
| 67 | { } | 67 | { } |
| 68 | }; | 68 | }; |
| 69 | MODULE_DEVICE_TABLE(i2c, tmp421_id); | 69 | MODULE_DEVICE_TABLE(i2c, tmp421_id); |
| @@ -73,21 +73,23 @@ struct tmp421_data { | |||
| 73 | struct mutex update_lock; | 73 | struct mutex update_lock; |
| 74 | char valid; | 74 | char valid; |
| 75 | unsigned long last_updated; | 75 | unsigned long last_updated; |
| 76 | int kind; | 76 | int channels; |
| 77 | u8 config; | 77 | u8 config; |
| 78 | s16 temp[4]; | 78 | s16 temp[4]; |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | static int temp_from_s16(s16 reg) | 81 | static int temp_from_s16(s16 reg) |
| 82 | { | 82 | { |
| 83 | int temp = reg; | 83 | /* Mask out status bits */ |
| 84 | int temp = reg & ~0xf; | ||
| 84 | 85 | ||
| 85 | return (temp * 1000 + 128) / 256; | 86 | return (temp * 1000 + 128) / 256; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | static int temp_from_u16(u16 reg) | 89 | static int temp_from_u16(u16 reg) |
| 89 | { | 90 | { |
| 90 | int temp = reg; | 91 | /* Mask out status bits */ |
| 92 | int temp = reg & ~0xf; | ||
| 91 | 93 | ||
| 92 | /* Add offset for extended temperature range. */ | 94 | /* Add offset for extended temperature range. */ |
| 93 | temp -= 64 * 256; | 95 | temp -= 64 * 256; |
| @@ -107,7 +109,7 @@ static struct tmp421_data *tmp421_update_device(struct device *dev) | |||
| 107 | data->config = i2c_smbus_read_byte_data(client, | 109 | data->config = i2c_smbus_read_byte_data(client, |
| 108 | TMP421_CONFIG_REG_1); | 110 | TMP421_CONFIG_REG_1); |
| 109 | 111 | ||
| 110 | for (i = 0; i <= data->kind; i++) { | 112 | for (i = 0; i < data->channels; i++) { |
| 111 | data->temp[i] = i2c_smbus_read_byte_data(client, | 113 | data->temp[i] = i2c_smbus_read_byte_data(client, |
| 112 | TMP421_TEMP_MSB[i]) << 8; | 114 | TMP421_TEMP_MSB[i]) << 8; |
| 113 | data->temp[i] |= i2c_smbus_read_byte_data(client, | 115 | data->temp[i] |= i2c_smbus_read_byte_data(client, |
| @@ -166,7 +168,7 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a, | |||
| 166 | devattr = container_of(a, struct device_attribute, attr); | 168 | devattr = container_of(a, struct device_attribute, attr); |
| 167 | index = to_sensor_dev_attr(devattr)->index; | 169 | index = to_sensor_dev_attr(devattr)->index; |
| 168 | 170 | ||
| 169 | if (data->kind > index) | 171 | if (index < data->channels) |
| 170 | return a->mode; | 172 | return a->mode; |
| 171 | 173 | ||
| 172 | return 0; | 174 | return 0; |
| @@ -252,9 +254,9 @@ static int tmp421_detect(struct i2c_client *client, | |||
| 252 | return -ENODEV; | 254 | return -ENODEV; |
| 253 | } | 255 | } |
| 254 | 256 | ||
| 255 | strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE); | 257 | strlcpy(info->type, tmp421_id[kind].name, I2C_NAME_SIZE); |
| 256 | dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n", | 258 | dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n", |
| 257 | names[kind - 1], client->addr); | 259 | names[kind], client->addr); |
| 258 | 260 | ||
| 259 | return 0; | 261 | return 0; |
| 260 | } | 262 | } |
| @@ -271,7 +273,7 @@ static int tmp421_probe(struct i2c_client *client, | |||
| 271 | 273 | ||
| 272 | i2c_set_clientdata(client, data); | 274 | i2c_set_clientdata(client, data); |
| 273 | mutex_init(&data->update_lock); | 275 | mutex_init(&data->update_lock); |
| 274 | data->kind = id->driver_data; | 276 | data->channels = id->driver_data; |
| 275 | 277 | ||
| 276 | err = tmp421_init_client(client); | 278 | err = tmp421_init_client(client); |
| 277 | if (err) | 279 | if (err) |
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index d47b4c9949c2..e6078c9f0e27 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c | |||
| @@ -948,8 +948,7 @@ static int __devinit vt8231_pci_probe(struct pci_dev *dev, | |||
| 948 | 948 | ||
| 949 | address = val & ~(VT8231_EXTENT - 1); | 949 | address = val & ~(VT8231_EXTENT - 1); |
| 950 | if (address == 0) { | 950 | if (address == 0) { |
| 951 | dev_err(&dev->dev, "base address not set -\ | 951 | dev_err(&dev->dev, "base address not set - upgrade BIOS or use force_addr=0xaddr\n"); |
| 952 | upgrade BIOS or use force_addr=0xaddr\n"); | ||
| 953 | return -ENODEV; | 952 | return -ENODEV; |
| 954 | } | 953 | } |
| 955 | 954 | ||
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 9a2022b67495..9de81a4c15a2 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c | |||
| @@ -3,6 +3,10 @@ | |||
| 3 | Copyright (C) 2006 Winbond Electronics Corp. | 3 | Copyright (C) 2006 Winbond Electronics Corp. |
| 4 | Yuan Mu | 4 | Yuan Mu |
| 5 | Rudolf Marek <r.marek@assembler.cz> | 5 | Rudolf Marek <r.marek@assembler.cz> |
| 6 | Copyright (C) 2009-2010 Sven Anders <anders@anduras.de>, ANDURAS AG. | ||
| 7 | Watchdog driver part | ||
| 8 | (Based partially on fschmd driver, | ||
| 9 | Copyright 2007-2008 by Hans de Goede) | ||
| 6 | 10 | ||
| 7 | This program is free software; you can redistribute it and/or modify | 11 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by | 12 | it under the terms of the GNU General Public License as published by |
| @@ -35,6 +39,16 @@ | |||
| 35 | #include <linux/hwmon-sysfs.h> | 39 | #include <linux/hwmon-sysfs.h> |
| 36 | #include <linux/err.h> | 40 | #include <linux/err.h> |
| 37 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
| 42 | #include <linux/fs.h> | ||
| 43 | #include <linux/watchdog.h> | ||
| 44 | #include <linux/miscdevice.h> | ||
| 45 | #include <linux/uaccess.h> | ||
| 46 | #include <linux/kref.h> | ||
| 47 | #include <linux/notifier.h> | ||
| 48 | #include <linux/reboot.h> | ||
| 49 | |||
| 50 | /* Default values */ | ||
| 51 | #define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */ | ||
| 38 | 52 | ||
| 39 | /* Addresses to scan */ | 53 | /* Addresses to scan */ |
| 40 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | 54 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, |
| @@ -51,6 +65,18 @@ static int reset; | |||
| 51 | module_param(reset, bool, 0); | 65 | module_param(reset, bool, 0); |
| 52 | MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); | 66 | MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); |
| 53 | 67 | ||
| 68 | static int timeout = WATCHDOG_TIMEOUT; /* default timeout in minutes */ | ||
| 69 | module_param(timeout, int, 0); | ||
| 70 | MODULE_PARM_DESC(timeout, | ||
| 71 | "Watchdog timeout in minutes. 2<= timeout <=255 (default=" | ||
| 72 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
| 73 | |||
| 74 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
| 75 | module_param(nowayout, int, 0); | ||
| 76 | MODULE_PARM_DESC(nowayout, | ||
| 77 | "Watchdog cannot be stopped once started (default=" | ||
| 78 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
| 79 | |||
| 54 | /* | 80 | /* |
| 55 | Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved | 81 | Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved |
| 56 | as ID, Bank Select registers | 82 | as ID, Bank Select registers |
| @@ -72,6 +98,11 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); | |||
| 72 | #define W83793_REG_VID_LATCHB 0x08 | 98 | #define W83793_REG_VID_LATCHB 0x08 |
| 73 | #define W83793_REG_VID_CTRL 0x59 | 99 | #define W83793_REG_VID_CTRL 0x59 |
| 74 | 100 | ||
| 101 | #define W83793_REG_WDT_LOCK 0x01 | ||
| 102 | #define W83793_REG_WDT_ENABLE 0x02 | ||
| 103 | #define W83793_REG_WDT_STATUS 0x03 | ||
| 104 | #define W83793_REG_WDT_TIMEOUT 0x04 | ||
| 105 | |||
| 75 | static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f }; | 106 | static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f }; |
| 76 | 107 | ||
| 77 | #define TEMP_READ 0 | 108 | #define TEMP_READ 0 |
| @@ -223,8 +254,37 @@ struct w83793_data { | |||
| 223 | u8 tolerance[3]; /* Temp tolerance(Smart Fan I/II) */ | 254 | u8 tolerance[3]; /* Temp tolerance(Smart Fan I/II) */ |
| 224 | u8 sf2_pwm[6][7]; /* Smart FanII: Fan duty cycle */ | 255 | u8 sf2_pwm[6][7]; /* Smart FanII: Fan duty cycle */ |
| 225 | u8 sf2_temp[6][7]; /* Smart FanII: Temp level point */ | 256 | u8 sf2_temp[6][7]; /* Smart FanII: Temp level point */ |
| 257 | |||
| 258 | /* watchdog */ | ||
| 259 | struct i2c_client *client; | ||
| 260 | struct mutex watchdog_lock; | ||
| 261 | struct list_head list; /* member of the watchdog_data_list */ | ||
| 262 | struct kref kref; | ||
| 263 | struct miscdevice watchdog_miscdev; | ||
| 264 | unsigned long watchdog_is_open; | ||
| 265 | char watchdog_expect_close; | ||
| 266 | char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ | ||
| 267 | unsigned int watchdog_caused_reboot; | ||
| 268 | int watchdog_timeout; /* watchdog timeout in minutes */ | ||
| 226 | }; | 269 | }; |
| 227 | 270 | ||
| 271 | /* Somewhat ugly :( global data pointer list with all devices, so that | ||
| 272 | we can find our device data as when using misc_register. There is no | ||
| 273 | other method to get to one's device data from the open file-op and | ||
| 274 | for usage in the reboot notifier callback. */ | ||
| 275 | static LIST_HEAD(watchdog_data_list); | ||
| 276 | |||
| 277 | /* Note this lock not only protect list access, but also data.kref access */ | ||
| 278 | static DEFINE_MUTEX(watchdog_data_mutex); | ||
| 279 | |||
| 280 | /* Release our data struct when we're detached from the i2c client *and* all | ||
| 281 | references to our watchdog device are released */ | ||
| 282 | static void w83793_release_resources(struct kref *ref) | ||
| 283 | { | ||
| 284 | struct w83793_data *data = container_of(ref, struct w83793_data, kref); | ||
| 285 | kfree(data); | ||
| 286 | } | ||
| 287 | |||
| 228 | static u8 w83793_read_value(struct i2c_client *client, u16 reg); | 288 | static u8 w83793_read_value(struct i2c_client *client, u16 reg); |
| 229 | static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); | 289 | static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); |
| 230 | static int w83793_probe(struct i2c_client *client, | 290 | static int w83793_probe(struct i2c_client *client, |
| @@ -1063,14 +1123,349 @@ static void w83793_init_client(struct i2c_client *client) | |||
| 1063 | /* Start monitoring */ | 1123 | /* Start monitoring */ |
| 1064 | w83793_write_value(client, W83793_REG_CONFIG, | 1124 | w83793_write_value(client, W83793_REG_CONFIG, |
| 1065 | w83793_read_value(client, W83793_REG_CONFIG) | 0x01); | 1125 | w83793_read_value(client, W83793_REG_CONFIG) | 0x01); |
| 1126 | } | ||
| 1127 | |||
| 1128 | /* | ||
| 1129 | * Watchdog routines | ||
| 1130 | */ | ||
| 1131 | |||
| 1132 | static int watchdog_set_timeout(struct w83793_data *data, int timeout) | ||
| 1133 | { | ||
| 1134 | int ret, mtimeout; | ||
| 1135 | |||
| 1136 | mtimeout = DIV_ROUND_UP(timeout, 60); | ||
| 1137 | |||
| 1138 | if (mtimeout > 255) | ||
| 1139 | return -EINVAL; | ||
| 1140 | |||
| 1141 | mutex_lock(&data->watchdog_lock); | ||
| 1142 | if (!data->client) { | ||
| 1143 | ret = -ENODEV; | ||
| 1144 | goto leave; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | data->watchdog_timeout = mtimeout; | ||
| 1148 | |||
| 1149 | /* Set Timeout value (in Minutes) */ | ||
| 1150 | w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT, | ||
| 1151 | data->watchdog_timeout); | ||
| 1152 | |||
| 1153 | ret = mtimeout * 60; | ||
| 1154 | |||
| 1155 | leave: | ||
| 1156 | mutex_unlock(&data->watchdog_lock); | ||
| 1157 | return ret; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | static int watchdog_get_timeout(struct w83793_data *data) | ||
| 1161 | { | ||
| 1162 | int timeout; | ||
| 1163 | |||
| 1164 | mutex_lock(&data->watchdog_lock); | ||
| 1165 | timeout = data->watchdog_timeout * 60; | ||
| 1166 | mutex_unlock(&data->watchdog_lock); | ||
| 1167 | |||
| 1168 | return timeout; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | static int watchdog_trigger(struct w83793_data *data) | ||
| 1172 | { | ||
| 1173 | int ret = 0; | ||
| 1174 | |||
| 1175 | mutex_lock(&data->watchdog_lock); | ||
| 1176 | if (!data->client) { | ||
| 1177 | ret = -ENODEV; | ||
| 1178 | goto leave; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | /* Set Timeout value (in Minutes) */ | ||
| 1182 | w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT, | ||
| 1183 | data->watchdog_timeout); | ||
| 1184 | |||
| 1185 | leave: | ||
| 1186 | mutex_unlock(&data->watchdog_lock); | ||
| 1187 | return ret; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | static int watchdog_enable(struct w83793_data *data) | ||
| 1191 | { | ||
| 1192 | int ret = 0; | ||
| 1193 | |||
| 1194 | mutex_lock(&data->watchdog_lock); | ||
| 1195 | if (!data->client) { | ||
| 1196 | ret = -ENODEV; | ||
| 1197 | goto leave; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | /* Set initial timeout */ | ||
| 1201 | w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT, | ||
| 1202 | data->watchdog_timeout); | ||
| 1203 | |||
| 1204 | /* Enable Soft Watchdog */ | ||
| 1205 | w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0x55); | ||
| 1206 | |||
| 1207 | leave: | ||
| 1208 | mutex_unlock(&data->watchdog_lock); | ||
| 1209 | return ret; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static int watchdog_disable(struct w83793_data *data) | ||
| 1213 | { | ||
| 1214 | int ret = 0; | ||
| 1215 | |||
| 1216 | mutex_lock(&data->watchdog_lock); | ||
| 1217 | if (!data->client) { | ||
| 1218 | ret = -ENODEV; | ||
| 1219 | goto leave; | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | /* Disable Soft Watchdog */ | ||
| 1223 | w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0xAA); | ||
| 1224 | |||
| 1225 | leave: | ||
| 1226 | mutex_unlock(&data->watchdog_lock); | ||
| 1227 | return ret; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static int watchdog_open(struct inode *inode, struct file *filp) | ||
| 1231 | { | ||
| 1232 | struct w83793_data *pos, *data = NULL; | ||
| 1233 | int watchdog_is_open; | ||
| 1234 | |||
| 1235 | /* We get called from drivers/char/misc.c with misc_mtx hold, and we | ||
| 1236 | call misc_register() from w83793_probe() with watchdog_data_mutex | ||
| 1237 | hold, as misc_register() takes the misc_mtx lock, this is a possible | ||
| 1238 | deadlock, so we use mutex_trylock here. */ | ||
| 1239 | if (!mutex_trylock(&watchdog_data_mutex)) | ||
| 1240 | return -ERESTARTSYS; | ||
| 1241 | list_for_each_entry(pos, &watchdog_data_list, list) { | ||
| 1242 | if (pos->watchdog_miscdev.minor == iminor(inode)) { | ||
| 1243 | data = pos; | ||
| 1244 | break; | ||
| 1245 | } | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | /* Check, if device is already open */ | ||
| 1249 | watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open); | ||
| 1250 | |||
| 1251 | /* Increase data reference counter (if not already done). | ||
| 1252 | Note we can never not have found data, so we don't check for this */ | ||
| 1253 | if (!watchdog_is_open) | ||
| 1254 | kref_get(&data->kref); | ||
| 1255 | |||
| 1256 | mutex_unlock(&watchdog_data_mutex); | ||
| 1257 | |||
| 1258 | /* Check, if device is already open and possibly issue error */ | ||
| 1259 | if (watchdog_is_open) | ||
| 1260 | return -EBUSY; | ||
| 1261 | |||
| 1262 | /* Enable Soft Watchdog */ | ||
| 1263 | watchdog_enable(data); | ||
| 1264 | |||
| 1265 | /* Store pointer to data into filp's private data */ | ||
| 1266 | filp->private_data = data; | ||
| 1267 | |||
| 1268 | return nonseekable_open(inode, filp); | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | static int watchdog_close(struct inode *inode, struct file *filp) | ||
| 1272 | { | ||
| 1273 | struct w83793_data *data = filp->private_data; | ||
| 1066 | 1274 | ||
| 1275 | if (data->watchdog_expect_close) { | ||
| 1276 | watchdog_disable(data); | ||
| 1277 | data->watchdog_expect_close = 0; | ||
| 1278 | } else { | ||
| 1279 | watchdog_trigger(data); | ||
| 1280 | dev_crit(&data->client->dev, | ||
| 1281 | "unexpected close, not stopping watchdog!\n"); | ||
| 1282 | } | ||
| 1283 | |||
| 1284 | clear_bit(0, &data->watchdog_is_open); | ||
| 1285 | |||
| 1286 | /* Decrease data reference counter */ | ||
| 1287 | mutex_lock(&watchdog_data_mutex); | ||
| 1288 | kref_put(&data->kref, w83793_release_resources); | ||
| 1289 | mutex_unlock(&watchdog_data_mutex); | ||
| 1290 | |||
| 1291 | return 0; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | static ssize_t watchdog_write(struct file *filp, const char __user *buf, | ||
| 1295 | size_t count, loff_t *offset) | ||
| 1296 | { | ||
| 1297 | size_t ret; | ||
| 1298 | struct w83793_data *data = filp->private_data; | ||
| 1299 | |||
| 1300 | if (count) { | ||
| 1301 | if (!nowayout) { | ||
| 1302 | size_t i; | ||
| 1303 | |||
| 1304 | /* Clear it in case it was set with a previous write */ | ||
| 1305 | data->watchdog_expect_close = 0; | ||
| 1306 | |||
| 1307 | for (i = 0; i != count; i++) { | ||
| 1308 | char c; | ||
| 1309 | if (get_user(c, buf + i)) | ||
| 1310 | return -EFAULT; | ||
| 1311 | if (c == 'V') | ||
| 1312 | data->watchdog_expect_close = 1; | ||
| 1313 | } | ||
| 1314 | } | ||
| 1315 | ret = watchdog_trigger(data); | ||
| 1316 | if (ret < 0) | ||
| 1317 | return ret; | ||
| 1318 | } | ||
| 1319 | return count; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | static int watchdog_ioctl(struct inode *inode, struct file *filp, | ||
| 1323 | unsigned int cmd, unsigned long arg) | ||
| 1324 | { | ||
| 1325 | static struct watchdog_info ident = { | ||
| 1326 | .options = WDIOF_KEEPALIVEPING | | ||
| 1327 | WDIOF_SETTIMEOUT | | ||
| 1328 | WDIOF_CARDRESET, | ||
| 1329 | .identity = "w83793 watchdog" | ||
| 1330 | }; | ||
| 1331 | |||
| 1332 | int val, ret = 0; | ||
| 1333 | struct w83793_data *data = filp->private_data; | ||
| 1334 | |||
| 1335 | switch (cmd) { | ||
| 1336 | case WDIOC_GETSUPPORT: | ||
| 1337 | if (!nowayout) | ||
| 1338 | ident.options |= WDIOF_MAGICCLOSE; | ||
| 1339 | if (copy_to_user((void __user *)arg, &ident, sizeof(ident))) | ||
| 1340 | ret = -EFAULT; | ||
| 1341 | break; | ||
| 1342 | |||
| 1343 | case WDIOC_GETSTATUS: | ||
| 1344 | val = data->watchdog_caused_reboot ? WDIOF_CARDRESET : 0; | ||
| 1345 | ret = put_user(val, (int __user *)arg); | ||
| 1346 | break; | ||
| 1347 | |||
| 1348 | case WDIOC_GETBOOTSTATUS: | ||
| 1349 | ret = put_user(0, (int __user *)arg); | ||
| 1350 | break; | ||
| 1351 | |||
| 1352 | case WDIOC_KEEPALIVE: | ||
| 1353 | ret = watchdog_trigger(data); | ||
| 1354 | break; | ||
| 1355 | |||
| 1356 | case WDIOC_GETTIMEOUT: | ||
| 1357 | val = watchdog_get_timeout(data); | ||
| 1358 | ret = put_user(val, (int __user *)arg); | ||
| 1359 | break; | ||
| 1360 | |||
| 1361 | case WDIOC_SETTIMEOUT: | ||
| 1362 | if (get_user(val, (int __user *)arg)) { | ||
| 1363 | ret = -EFAULT; | ||
| 1364 | break; | ||
| 1365 | } | ||
| 1366 | ret = watchdog_set_timeout(data, val); | ||
| 1367 | if (ret > 0) | ||
| 1368 | ret = put_user(ret, (int __user *)arg); | ||
| 1369 | break; | ||
| 1370 | |||
| 1371 | case WDIOC_SETOPTIONS: | ||
| 1372 | if (get_user(val, (int __user *)arg)) { | ||
| 1373 | ret = -EFAULT; | ||
| 1374 | break; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | if (val & WDIOS_DISABLECARD) | ||
| 1378 | ret = watchdog_disable(data); | ||
| 1379 | else if (val & WDIOS_ENABLECARD) | ||
| 1380 | ret = watchdog_enable(data); | ||
| 1381 | else | ||
| 1382 | ret = -EINVAL; | ||
| 1383 | |||
| 1384 | break; | ||
| 1385 | default: | ||
| 1386 | ret = -ENOTTY; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | return ret; | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | static const struct file_operations watchdog_fops = { | ||
| 1393 | .owner = THIS_MODULE, | ||
| 1394 | .llseek = no_llseek, | ||
| 1395 | .open = watchdog_open, | ||
| 1396 | .release = watchdog_close, | ||
| 1397 | .write = watchdog_write, | ||
| 1398 | .ioctl = watchdog_ioctl, | ||
| 1399 | }; | ||
| 1400 | |||
| 1401 | /* | ||
| 1402 | * Notifier for system down | ||
| 1403 | */ | ||
| 1404 | |||
| 1405 | static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, | ||
| 1406 | void *unused) | ||
| 1407 | { | ||
| 1408 | struct w83793_data *data = NULL; | ||
| 1409 | |||
| 1410 | if (code == SYS_DOWN || code == SYS_HALT) { | ||
| 1411 | |||
| 1412 | /* Disable each registered watchdog */ | ||
| 1413 | mutex_lock(&watchdog_data_mutex); | ||
| 1414 | list_for_each_entry(data, &watchdog_data_list, list) { | ||
| 1415 | if (data->watchdog_miscdev.minor) | ||
| 1416 | watchdog_disable(data); | ||
| 1417 | } | ||
| 1418 | mutex_unlock(&watchdog_data_mutex); | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | return NOTIFY_DONE; | ||
| 1067 | } | 1422 | } |
| 1068 | 1423 | ||
| 1424 | /* | ||
| 1425 | * The WDT needs to learn about soft shutdowns in order to | ||
| 1426 | * turn the timebomb registers off. | ||
| 1427 | */ | ||
| 1428 | |||
| 1429 | static struct notifier_block watchdog_notifier = { | ||
| 1430 | .notifier_call = watchdog_notify_sys, | ||
| 1431 | }; | ||
| 1432 | |||
| 1433 | /* | ||
| 1434 | * Init / remove routines | ||
| 1435 | */ | ||
| 1436 | |||
| 1069 | static int w83793_remove(struct i2c_client *client) | 1437 | static int w83793_remove(struct i2c_client *client) |
| 1070 | { | 1438 | { |
| 1071 | struct w83793_data *data = i2c_get_clientdata(client); | 1439 | struct w83793_data *data = i2c_get_clientdata(client); |
| 1072 | struct device *dev = &client->dev; | 1440 | struct device *dev = &client->dev; |
| 1073 | int i; | 1441 | int i, tmp; |
| 1442 | |||
| 1443 | /* Unregister the watchdog (if registered) */ | ||
| 1444 | if (data->watchdog_miscdev.minor) { | ||
| 1445 | misc_deregister(&data->watchdog_miscdev); | ||
| 1446 | |||
| 1447 | if (data->watchdog_is_open) { | ||
| 1448 | dev_warn(&client->dev, | ||
| 1449 | "i2c client detached with watchdog open! " | ||
| 1450 | "Stopping watchdog.\n"); | ||
| 1451 | watchdog_disable(data); | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | mutex_lock(&watchdog_data_mutex); | ||
| 1455 | list_del(&data->list); | ||
| 1456 | mutex_unlock(&watchdog_data_mutex); | ||
| 1457 | |||
| 1458 | /* Tell the watchdog code the client is gone */ | ||
| 1459 | mutex_lock(&data->watchdog_lock); | ||
| 1460 | data->client = NULL; | ||
| 1461 | mutex_unlock(&data->watchdog_lock); | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | /* Reset Configuration Register to Disable Watch Dog Registers */ | ||
| 1465 | tmp = w83793_read_value(client, W83793_REG_CONFIG); | ||
| 1466 | w83793_write_value(client, W83793_REG_CONFIG, tmp & ~0x04); | ||
| 1467 | |||
| 1468 | unregister_reboot_notifier(&watchdog_notifier); | ||
| 1074 | 1469 | ||
| 1075 | hwmon_device_unregister(data->hwmon_dev); | 1470 | hwmon_device_unregister(data->hwmon_dev); |
| 1076 | 1471 | ||
| @@ -1099,7 +1494,10 @@ static int w83793_remove(struct i2c_client *client) | |||
| 1099 | if (data->lm75[1] != NULL) | 1494 | if (data->lm75[1] != NULL) |
| 1100 | i2c_unregister_device(data->lm75[1]); | 1495 | i2c_unregister_device(data->lm75[1]); |
| 1101 | 1496 | ||
| 1102 | kfree(data); | 1497 | /* Decrease data reference counter */ |
| 1498 | mutex_lock(&watchdog_data_mutex); | ||
| 1499 | kref_put(&data->kref, w83793_release_resources); | ||
| 1500 | mutex_unlock(&watchdog_data_mutex); | ||
| 1103 | 1501 | ||
| 1104 | return 0; | 1502 | return 0; |
| 1105 | } | 1503 | } |
| @@ -1203,6 +1601,7 @@ static int w83793_probe(struct i2c_client *client, | |||
| 1203 | const struct i2c_device_id *id) | 1601 | const struct i2c_device_id *id) |
| 1204 | { | 1602 | { |
| 1205 | struct device *dev = &client->dev; | 1603 | struct device *dev = &client->dev; |
| 1604 | const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; | ||
| 1206 | struct w83793_data *data; | 1605 | struct w83793_data *data; |
| 1207 | int i, tmp, val, err; | 1606 | int i, tmp, val, err; |
| 1208 | int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; | 1607 | int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; |
| @@ -1218,6 +1617,14 @@ static int w83793_probe(struct i2c_client *client, | |||
| 1218 | i2c_set_clientdata(client, data); | 1617 | i2c_set_clientdata(client, data); |
| 1219 | data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); | 1618 | data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); |
| 1220 | mutex_init(&data->update_lock); | 1619 | mutex_init(&data->update_lock); |
| 1620 | mutex_init(&data->watchdog_lock); | ||
| 1621 | INIT_LIST_HEAD(&data->list); | ||
| 1622 | kref_init(&data->kref); | ||
| 1623 | |||
| 1624 | /* Store client pointer in our data struct for watchdog usage | ||
| 1625 | (where the client is found through a data ptr instead of the | ||
| 1626 | otherway around) */ | ||
| 1627 | data->client = client; | ||
| 1221 | 1628 | ||
| 1222 | err = w83793_detect_subclients(client); | 1629 | err = w83793_detect_subclients(client); |
| 1223 | if (err) | 1630 | if (err) |
| @@ -1380,8 +1787,77 @@ static int w83793_probe(struct i2c_client *client, | |||
| 1380 | goto exit_remove; | 1787 | goto exit_remove; |
| 1381 | } | 1788 | } |
| 1382 | 1789 | ||
| 1790 | /* Watchdog initialization */ | ||
| 1791 | |||
| 1792 | /* Register boot notifier */ | ||
| 1793 | err = register_reboot_notifier(&watchdog_notifier); | ||
| 1794 | if (err != 0) { | ||
| 1795 | dev_err(&client->dev, | ||
| 1796 | "cannot register reboot notifier (err=%d)\n", err); | ||
| 1797 | goto exit_devunreg; | ||
| 1798 | } | ||
| 1799 | |||
| 1800 | /* Enable Watchdog registers. | ||
| 1801 | Set Configuration Register to Enable Watch Dog Registers | ||
| 1802 | (Bit 2) = XXXX, X1XX. */ | ||
| 1803 | tmp = w83793_read_value(client, W83793_REG_CONFIG); | ||
| 1804 | w83793_write_value(client, W83793_REG_CONFIG, tmp | 0x04); | ||
| 1805 | |||
| 1806 | /* Set the default watchdog timeout */ | ||
| 1807 | data->watchdog_timeout = timeout; | ||
| 1808 | |||
| 1809 | /* Check, if last reboot was caused by watchdog */ | ||
| 1810 | data->watchdog_caused_reboot = | ||
| 1811 | w83793_read_value(data->client, W83793_REG_WDT_STATUS) & 0x01; | ||
| 1812 | |||
| 1813 | /* Disable Soft Watchdog during initialiation */ | ||
| 1814 | watchdog_disable(data); | ||
| 1815 | |||
| 1816 | /* We take the data_mutex lock early so that watchdog_open() cannot | ||
| 1817 | run when misc_register() has completed, but we've not yet added | ||
| 1818 | our data to the watchdog_data_list (and set the default timeout) */ | ||
| 1819 | mutex_lock(&watchdog_data_mutex); | ||
| 1820 | for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) { | ||
| 1821 | /* Register our watchdog part */ | ||
| 1822 | snprintf(data->watchdog_name, sizeof(data->watchdog_name), | ||
| 1823 | "watchdog%c", (i == 0) ? '\0' : ('0' + i)); | ||
| 1824 | data->watchdog_miscdev.name = data->watchdog_name; | ||
| 1825 | data->watchdog_miscdev.fops = &watchdog_fops; | ||
| 1826 | data->watchdog_miscdev.minor = watchdog_minors[i]; | ||
| 1827 | |||
| 1828 | err = misc_register(&data->watchdog_miscdev); | ||
| 1829 | if (err == -EBUSY) | ||
| 1830 | continue; | ||
| 1831 | if (err) { | ||
| 1832 | data->watchdog_miscdev.minor = 0; | ||
| 1833 | dev_err(&client->dev, | ||
| 1834 | "Registering watchdog chardev: %d\n", err); | ||
| 1835 | break; | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | list_add(&data->list, &watchdog_data_list); | ||
| 1839 | |||
| 1840 | dev_info(&client->dev, | ||
| 1841 | "Registered watchdog chardev major 10, minor: %d\n", | ||
| 1842 | watchdog_minors[i]); | ||
| 1843 | break; | ||
| 1844 | } | ||
| 1845 | if (i == ARRAY_SIZE(watchdog_minors)) { | ||
| 1846 | data->watchdog_miscdev.minor = 0; | ||
| 1847 | dev_warn(&client->dev, "Couldn't register watchdog chardev " | ||
| 1848 | "(due to no free minor)\n"); | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | mutex_unlock(&watchdog_data_mutex); | ||
| 1852 | |||
| 1383 | return 0; | 1853 | return 0; |
| 1384 | 1854 | ||
| 1855 | /* Unregister hwmon device */ | ||
| 1856 | |||
| 1857 | exit_devunreg: | ||
| 1858 | |||
| 1859 | hwmon_device_unregister(data->hwmon_dev); | ||
| 1860 | |||
| 1385 | /* Unregister sysfs hooks */ | 1861 | /* Unregister sysfs hooks */ |
| 1386 | 1862 | ||
| 1387 | exit_remove: | 1863 | exit_remove: |
| @@ -1628,7 +2104,7 @@ static void __exit sensors_w83793_exit(void) | |||
| 1628 | i2c_del_driver(&w83793_driver); | 2104 | i2c_del_driver(&w83793_driver); |
| 1629 | } | 2105 | } |
| 1630 | 2106 | ||
| 1631 | MODULE_AUTHOR("Yuan Mu"); | 2107 | MODULE_AUTHOR("Yuan Mu, Sven Anders"); |
| 1632 | MODULE_DESCRIPTION("w83793 driver"); | 2108 | MODULE_DESCRIPTION("w83793 driver"); |
| 1633 | MODULE_LICENSE("GPL"); | 2109 | MODULE_LICENSE("GPL"); |
| 1634 | 2110 | ||
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index 9e18ef97f156..3e72b69aa7f8 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c | |||
| @@ -497,13 +497,13 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) | |||
| 497 | int i; | 497 | int i; |
| 498 | 498 | ||
| 499 | if (abort_source & DW_IC_TX_ABRT_NOACK) { | 499 | if (abort_source & DW_IC_TX_ABRT_NOACK) { |
| 500 | for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) | 500 | for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) |
| 501 | dev_dbg(dev->dev, | 501 | dev_dbg(dev->dev, |
| 502 | "%s: %s\n", __func__, abort_sources[i]); | 502 | "%s: %s\n", __func__, abort_sources[i]); |
| 503 | return -EREMOTEIO; | 503 | return -EREMOTEIO; |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) | 506 | for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) |
| 507 | dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); | 507 | dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); |
| 508 | 508 | ||
| 509 | if (abort_source & DW_IC_TX_ARB_LOST) | 509 | if (abort_source & DW_IC_TX_ARB_LOST) |
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 7522008fda86..58463da814d1 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
| @@ -1193,10 +1193,7 @@ static int method_in_use(struct ib_mad_mgmt_method_table **method, | |||
| 1193 | { | 1193 | { |
| 1194 | int i; | 1194 | int i; |
| 1195 | 1195 | ||
| 1196 | for (i = find_first_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS); | 1196 | for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) { |
| 1197 | i < IB_MGMT_MAX_METHODS; | ||
| 1198 | i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS, | ||
| 1199 | 1+i)) { | ||
| 1200 | if ((*method)->agent[i]) { | 1197 | if ((*method)->agent[i]) { |
| 1201 | printk(KERN_ERR PFX "Method %d already in use\n", i); | 1198 | printk(KERN_ERR PFX "Method %d already in use\n", i); |
| 1202 | return -EINVAL; | 1199 | return -EINVAL; |
| @@ -1330,13 +1327,9 @@ static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req, | |||
| 1330 | goto error3; | 1327 | goto error3; |
| 1331 | 1328 | ||
| 1332 | /* Finally, add in methods being registered */ | 1329 | /* Finally, add in methods being registered */ |
| 1333 | for (i = find_first_bit(mad_reg_req->method_mask, | 1330 | for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) |
| 1334 | IB_MGMT_MAX_METHODS); | ||
| 1335 | i < IB_MGMT_MAX_METHODS; | ||
| 1336 | i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS, | ||
| 1337 | 1+i)) { | ||
| 1338 | (*method)->agent[i] = agent_priv; | 1331 | (*method)->agent[i] = agent_priv; |
| 1339 | } | 1332 | |
| 1340 | return 0; | 1333 | return 0; |
| 1341 | 1334 | ||
| 1342 | error3: | 1335 | error3: |
| @@ -1429,13 +1422,9 @@ check_in_use: | |||
| 1429 | goto error4; | 1422 | goto error4; |
| 1430 | 1423 | ||
| 1431 | /* Finally, add in methods being registered */ | 1424 | /* Finally, add in methods being registered */ |
| 1432 | for (i = find_first_bit(mad_reg_req->method_mask, | 1425 | for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) |
| 1433 | IB_MGMT_MAX_METHODS); | ||
| 1434 | i < IB_MGMT_MAX_METHODS; | ||
| 1435 | i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS, | ||
| 1436 | 1+i)) { | ||
| 1437 | (*method)->agent[i] = agent_priv; | 1426 | (*method)->agent[i] = agent_priv; |
| 1438 | } | 1427 | |
| 1439 | return 0; | 1428 | return 0; |
| 1440 | 1429 | ||
| 1441 | error4: | 1430 | error4: |
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index be115b3b65eb..be54fd639aca 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
| @@ -44,7 +44,7 @@ static irqreturn_t mc13783_ts_handler(int irq, void *data) | |||
| 44 | { | 44 | { |
| 45 | struct mc13783_ts_priv *priv = data; | 45 | struct mc13783_ts_priv *priv = data; |
| 46 | 46 | ||
| 47 | mc13783_ackirq(priv->mc13783, irq); | 47 | mc13783_irq_ack(priv->mc13783, irq); |
| 48 | 48 | ||
| 49 | /* | 49 | /* |
| 50 | * Kick off reading coordinates. Note that if work happens already | 50 | * Kick off reading coordinates. Note that if work happens already |
| @@ -135,7 +135,7 @@ static int mc13783_ts_open(struct input_dev *dev) | |||
| 135 | 135 | ||
| 136 | mc13783_lock(priv->mc13783); | 136 | mc13783_lock(priv->mc13783); |
| 137 | 137 | ||
| 138 | mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS); | 138 | mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS); |
| 139 | 139 | ||
| 140 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS, | 140 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS, |
| 141 | mc13783_ts_handler, MC13783_TS_NAME, priv); | 141 | mc13783_ts_handler, MC13783_TS_NAME, priv); |
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index aa266e1f69b2..addb846c1e34 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c | |||
| @@ -108,7 +108,7 @@ static void egpio_handler(unsigned int irq, struct irq_desc *desc) | |||
| 108 | ack_irqs(ei); | 108 | ack_irqs(ei); |
| 109 | /* Process all set pins. */ | 109 | /* Process all set pins. */ |
| 110 | readval &= ei->irqs_enabled; | 110 | readval &= ei->irqs_enabled; |
| 111 | for_each_bit(irqpin, &readval, ei->nirqs) { | 111 | for_each_set_bit(irqpin, &readval, ei->nirqs) { |
| 112 | /* Run irq handler */ | 112 | /* Run irq handler */ |
| 113 | pr_debug("got IRQ %d\n", irqpin); | 113 | pr_debug("got IRQ %d\n", irqpin); |
| 114 | irq = ei->irq_start + irqpin; | 114 | irq = ei->irq_start + irqpin; |
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index 735c8a4d164f..62a847e4c2d8 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
| @@ -225,7 +225,7 @@ int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset, | |||
| 225 | } | 225 | } |
| 226 | EXPORT_SYMBOL(mc13783_reg_rmw); | 226 | EXPORT_SYMBOL(mc13783_reg_rmw); |
| 227 | 227 | ||
| 228 | int mc13783_mask(struct mc13783 *mc13783, int irq) | 228 | int mc13783_irq_mask(struct mc13783 *mc13783, int irq) |
| 229 | { | 229 | { |
| 230 | int ret; | 230 | int ret; |
| 231 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | 231 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; |
| @@ -245,9 +245,9 @@ int mc13783_mask(struct mc13783 *mc13783, int irq) | |||
| 245 | 245 | ||
| 246 | return mc13783_reg_write(mc13783, offmask, mask | irqbit); | 246 | return mc13783_reg_write(mc13783, offmask, mask | irqbit); |
| 247 | } | 247 | } |
| 248 | EXPORT_SYMBOL(mc13783_mask); | 248 | EXPORT_SYMBOL(mc13783_irq_mask); |
| 249 | 249 | ||
| 250 | int mc13783_unmask(struct mc13783 *mc13783, int irq) | 250 | int mc13783_irq_unmask(struct mc13783 *mc13783, int irq) |
| 251 | { | 251 | { |
| 252 | int ret; | 252 | int ret; |
| 253 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | 253 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; |
| @@ -267,7 +267,53 @@ int mc13783_unmask(struct mc13783 *mc13783, int irq) | |||
| 267 | 267 | ||
| 268 | return mc13783_reg_write(mc13783, offmask, mask & ~irqbit); | 268 | return mc13783_reg_write(mc13783, offmask, mask & ~irqbit); |
| 269 | } | 269 | } |
| 270 | EXPORT_SYMBOL(mc13783_unmask); | 270 | EXPORT_SYMBOL(mc13783_irq_unmask); |
| 271 | |||
| 272 | int mc13783_irq_status(struct mc13783 *mc13783, int irq, | ||
| 273 | int *enabled, int *pending) | ||
| 274 | { | ||
| 275 | int ret; | ||
| 276 | unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1; | ||
| 277 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; | ||
| 278 | u32 irqbit = 1 << (irq < 24 ? irq : irq - 24); | ||
| 279 | |||
| 280 | if (irq < 0 || irq >= MC13783_NUM_IRQ) | ||
| 281 | return -EINVAL; | ||
| 282 | |||
| 283 | if (enabled) { | ||
| 284 | u32 mask; | ||
| 285 | |||
| 286 | ret = mc13783_reg_read(mc13783, offmask, &mask); | ||
| 287 | if (ret) | ||
| 288 | return ret; | ||
| 289 | |||
| 290 | *enabled = mask & irqbit; | ||
| 291 | } | ||
| 292 | |||
| 293 | if (pending) { | ||
| 294 | u32 stat; | ||
| 295 | |||
| 296 | ret = mc13783_reg_read(mc13783, offstat, &stat); | ||
| 297 | if (ret) | ||
| 298 | return ret; | ||
| 299 | |||
| 300 | *pending = stat & irqbit; | ||
| 301 | } | ||
| 302 | |||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | EXPORT_SYMBOL(mc13783_irq_status); | ||
| 306 | |||
| 307 | int mc13783_irq_ack(struct mc13783 *mc13783, int irq) | ||
| 308 | { | ||
| 309 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; | ||
| 310 | unsigned int val = 1 << (irq < 24 ? irq : irq - 24); | ||
| 311 | |||
| 312 | BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ); | ||
| 313 | |||
| 314 | return mc13783_reg_write(mc13783, offstat, val); | ||
| 315 | } | ||
| 316 | EXPORT_SYMBOL(mc13783_irq_ack); | ||
| 271 | 317 | ||
| 272 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, | 318 | int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq, |
| 273 | irq_handler_t handler, const char *name, void *dev) | 319 | irq_handler_t handler, const char *name, void *dev) |
| @@ -297,7 +343,7 @@ int mc13783_irq_request(struct mc13783 *mc13783, int irq, | |||
| 297 | if (ret) | 343 | if (ret) |
| 298 | return ret; | 344 | return ret; |
| 299 | 345 | ||
| 300 | ret = mc13783_unmask(mc13783, irq); | 346 | ret = mc13783_irq_unmask(mc13783, irq); |
| 301 | if (ret) { | 347 | if (ret) { |
| 302 | mc13783->irqhandler[irq] = NULL; | 348 | mc13783->irqhandler[irq] = NULL; |
| 303 | mc13783->irqdata[irq] = NULL; | 349 | mc13783->irqdata[irq] = NULL; |
| @@ -317,7 +363,7 @@ int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev) | |||
| 317 | mc13783->irqdata[irq] != dev) | 363 | mc13783->irqdata[irq] != dev) |
| 318 | return -EINVAL; | 364 | return -EINVAL; |
| 319 | 365 | ||
| 320 | ret = mc13783_mask(mc13783, irq); | 366 | ret = mc13783_irq_mask(mc13783, irq); |
| 321 | if (ret) | 367 | if (ret) |
| 322 | return ret; | 368 | return ret; |
| 323 | 369 | ||
| @@ -333,17 +379,6 @@ static inline irqreturn_t mc13783_irqhandler(struct mc13783 *mc13783, int irq) | |||
| 333 | return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]); | 379 | return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]); |
| 334 | } | 380 | } |
| 335 | 381 | ||
| 336 | int mc13783_ackirq(struct mc13783 *mc13783, int irq) | ||
| 337 | { | ||
| 338 | unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1; | ||
| 339 | unsigned int val = 1 << (irq < 24 ? irq : irq - 24); | ||
| 340 | |||
| 341 | BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ); | ||
| 342 | |||
| 343 | return mc13783_reg_write(mc13783, offstat, val); | ||
| 344 | } | ||
| 345 | EXPORT_SYMBOL(mc13783_ackirq); | ||
| 346 | |||
| 347 | /* | 382 | /* |
| 348 | * returns: number of handled irqs or negative error | 383 | * returns: number of handled irqs or negative error |
| 349 | * locking: holds mc13783->lock | 384 | * locking: holds mc13783->lock |
| @@ -422,7 +457,7 @@ static irqreturn_t mc13783_handler_adcdone(int irq, void *data) | |||
| 422 | { | 457 | { |
| 423 | struct mc13783_adcdone_data *adcdone_data = data; | 458 | struct mc13783_adcdone_data *adcdone_data = data; |
| 424 | 459 | ||
| 425 | mc13783_ackirq(adcdone_data->mc13783, irq); | 460 | mc13783_irq_ack(adcdone_data->mc13783, irq); |
| 426 | 461 | ||
| 427 | complete_all(&adcdone_data->done); | 462 | complete_all(&adcdone_data->done); |
| 428 | 463 | ||
| @@ -486,7 +521,7 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode, | |||
| 486 | dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__); | 521 | dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__); |
| 487 | mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE, | 522 | mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE, |
| 488 | mc13783_handler_adcdone, __func__, &adcdone_data); | 523 | mc13783_handler_adcdone, __func__, &adcdone_data); |
| 489 | mc13783_ackirq(mc13783, MC13783_IRQ_ADCDONE); | 524 | mc13783_irq_ack(mc13783, MC13783_IRQ_ADCDONE); |
| 490 | 525 | ||
| 491 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0); | 526 | mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0); |
| 492 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1); | 527 | mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1); |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e3551d20464f..d16af6a423fb 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -212,6 +212,15 @@ config CS5535_MFGPT_DEFAULT_IRQ | |||
| 212 | want to use a different IRQ by default. This is here for | 212 | want to use a different IRQ by default. This is here for |
| 213 | architectures to set as necessary. | 213 | architectures to set as necessary. |
| 214 | 214 | ||
| 215 | config CS5535_CLOCK_EVENT_SRC | ||
| 216 | tristate "CS5535/CS5536 high-res timer (MFGPT) events" | ||
| 217 | depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT | ||
| 218 | help | ||
| 219 | This driver provides a clock event source based on the MFGPT | ||
| 220 | timer(s) in the CS5535 and CS5536 companion chips. | ||
| 221 | MFGPTs have a better resolution and max interval than the | ||
| 222 | generic PIT, and are suitable for use as high-res timers. | ||
| 223 | |||
| 215 | config HP_ILO | 224 | config HP_ILO |
| 216 | tristate "Channel interface driver for HP iLO/iLO2 processor" | 225 | tristate "Channel interface driver for HP iLO/iLO2 processor" |
| 217 | depends on PCI | 226 | depends on PCI |
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c index dd0a3913bf6d..3b7292a5cea9 100644 --- a/drivers/misc/iwmc3200top/main.c +++ b/drivers/misc/iwmc3200top/main.c | |||
| @@ -597,8 +597,6 @@ static void iwmct_remove(struct sdio_func *func) | |||
| 597 | struct iwmct_work_struct *read_req; | 597 | struct iwmct_work_struct *read_req; |
| 598 | struct iwmct_priv *priv = sdio_get_drvdata(func); | 598 | struct iwmct_priv *priv = sdio_get_drvdata(func); |
| 599 | 599 | ||
| 600 | priv = sdio_get_drvdata(func); | ||
| 601 | |||
| 602 | LOG_INFO(priv, INIT, "enter\n"); | 600 | LOG_INFO(priv, INIT, "enter\n"); |
| 603 | 601 | ||
| 604 | sdio_claim_host(func); | 602 | sdio_claim_host(func); |
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 3648b23d5c92..4a0648301fdf 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
| @@ -26,21 +26,9 @@ | |||
| 26 | * It is adapted from the Linux Kernel Dump Test Tool by | 26 | * It is adapted from the Linux Kernel Dump Test Tool by |
| 27 | * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net> | 27 | * Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net> |
| 28 | * | 28 | * |
| 29 | * Usage : insmod lkdtm.ko [recur_count={>0}] cpoint_name=<> cpoint_type=<> | 29 | * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net> |
| 30 | * [cpoint_count={>0}] | ||
| 31 | * | 30 | * |
| 32 | * recur_count : Recursion level for the stack overflow test. Default is 10. | 31 | * See Documentation/fault-injection/provoke-crashes.txt for instructions |
| 33 | * | ||
| 34 | * cpoint_name : Crash point where the kernel is to be crashed. It can be | ||
| 35 | * one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY, | ||
| 36 | * FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD, | ||
| 37 | * IDE_CORE_CP | ||
| 38 | * | ||
| 39 | * cpoint_type : Indicates the action to be taken on hitting the crash point. | ||
| 40 | * It can be one of PANIC, BUG, EXCEPTION, LOOP, OVERFLOW | ||
| 41 | * | ||
| 42 | * cpoint_count : Indicates the number of times the crash point is to be hit | ||
| 43 | * to trigger an action. The default is 10. | ||
| 44 | */ | 32 | */ |
| 45 | 33 | ||
| 46 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
| @@ -53,13 +41,12 @@ | |||
| 53 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
| 54 | #include <linux/hrtimer.h> | 42 | #include <linux/hrtimer.h> |
| 55 | #include <scsi/scsi_cmnd.h> | 43 | #include <scsi/scsi_cmnd.h> |
| 44 | #include <linux/debugfs.h> | ||
| 56 | 45 | ||
| 57 | #ifdef CONFIG_IDE | 46 | #ifdef CONFIG_IDE |
| 58 | #include <linux/ide.h> | 47 | #include <linux/ide.h> |
| 59 | #endif | 48 | #endif |
| 60 | 49 | ||
| 61 | #define NUM_CPOINTS 8 | ||
| 62 | #define NUM_CPOINT_TYPES 5 | ||
| 63 | #define DEFAULT_COUNT 10 | 50 | #define DEFAULT_COUNT 10 |
| 64 | #define REC_NUM_DEFAULT 10 | 51 | #define REC_NUM_DEFAULT 10 |
| 65 | 52 | ||
| @@ -72,7 +59,8 @@ enum cname { | |||
| 72 | MEM_SWAPOUT, | 59 | MEM_SWAPOUT, |
| 73 | TIMERADD, | 60 | TIMERADD, |
| 74 | SCSI_DISPATCH_CMD, | 61 | SCSI_DISPATCH_CMD, |
| 75 | IDE_CORE_CP | 62 | IDE_CORE_CP, |
| 63 | DIRECT, | ||
| 76 | }; | 64 | }; |
| 77 | 65 | ||
| 78 | enum ctype { | 66 | enum ctype { |
| @@ -81,7 +69,11 @@ enum ctype { | |||
| 81 | BUG, | 69 | BUG, |
| 82 | EXCEPTION, | 70 | EXCEPTION, |
| 83 | LOOP, | 71 | LOOP, |
| 84 | OVERFLOW | 72 | OVERFLOW, |
| 73 | CORRUPT_STACK, | ||
| 74 | UNALIGNED_LOAD_STORE_WRITE, | ||
| 75 | OVERWRITE_ALLOCATION, | ||
| 76 | WRITE_AFTER_FREE, | ||
| 85 | }; | 77 | }; |
| 86 | 78 | ||
| 87 | static char* cp_name[] = { | 79 | static char* cp_name[] = { |
| @@ -92,7 +84,8 @@ static char* cp_name[] = { | |||
| 92 | "MEM_SWAPOUT", | 84 | "MEM_SWAPOUT", |
| 93 | "TIMERADD", | 85 | "TIMERADD", |
| 94 | "SCSI_DISPATCH_CMD", | 86 | "SCSI_DISPATCH_CMD", |
| 95 | "IDE_CORE_CP" | 87 | "IDE_CORE_CP", |
| 88 | "DIRECT", | ||
| 96 | }; | 89 | }; |
| 97 | 90 | ||
| 98 | static char* cp_type[] = { | 91 | static char* cp_type[] = { |
| @@ -100,7 +93,11 @@ static char* cp_type[] = { | |||
| 100 | "BUG", | 93 | "BUG", |
| 101 | "EXCEPTION", | 94 | "EXCEPTION", |
| 102 | "LOOP", | 95 | "LOOP", |
| 103 | "OVERFLOW" | 96 | "OVERFLOW", |
| 97 | "CORRUPT_STACK", | ||
| 98 | "UNALIGNED_LOAD_STORE_WRITE", | ||
| 99 | "OVERWRITE_ALLOCATION", | ||
| 100 | "WRITE_AFTER_FREE", | ||
| 104 | }; | 101 | }; |
| 105 | 102 | ||
| 106 | static struct jprobe lkdtm; | 103 | static struct jprobe lkdtm; |
| @@ -193,34 +190,66 @@ int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file, | |||
| 193 | } | 190 | } |
| 194 | #endif | 191 | #endif |
| 195 | 192 | ||
| 193 | /* Return the crashpoint number or NONE if the name is invalid */ | ||
| 194 | static enum ctype parse_cp_type(const char *what, size_t count) | ||
| 195 | { | ||
| 196 | int i; | ||
| 197 | |||
| 198 | for (i = 0; i < ARRAY_SIZE(cp_type); i++) { | ||
| 199 | if (!strcmp(what, cp_type[i])) | ||
| 200 | return i + 1; | ||
| 201 | } | ||
| 202 | |||
| 203 | return NONE; | ||
| 204 | } | ||
| 205 | |||
| 206 | static const char *cp_type_to_str(enum ctype type) | ||
| 207 | { | ||
| 208 | if (type == NONE || type < 0 || type > ARRAY_SIZE(cp_type)) | ||
| 209 | return "None"; | ||
| 210 | |||
| 211 | return cp_type[type - 1]; | ||
| 212 | } | ||
| 213 | |||
| 214 | static const char *cp_name_to_str(enum cname name) | ||
| 215 | { | ||
| 216 | if (name == INVALID || name < 0 || name > ARRAY_SIZE(cp_name)) | ||
| 217 | return "INVALID"; | ||
| 218 | |||
| 219 | return cp_name[name - 1]; | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 196 | static int lkdtm_parse_commandline(void) | 223 | static int lkdtm_parse_commandline(void) |
| 197 | { | 224 | { |
| 198 | int i; | 225 | int i; |
| 199 | 226 | ||
| 200 | if (cpoint_name == NULL || cpoint_type == NULL || | 227 | if (cpoint_count < 1 || recur_count < 1) |
| 201 | cpoint_count < 1 || recur_count < 1) | ||
| 202 | return -EINVAL; | 228 | return -EINVAL; |
| 203 | 229 | ||
| 204 | for (i = 0; i < NUM_CPOINTS; ++i) { | 230 | count = cpoint_count; |
| 231 | |||
| 232 | /* No special parameters */ | ||
| 233 | if (!cpoint_type && !cpoint_name) | ||
| 234 | return 0; | ||
| 235 | |||
| 236 | /* Neither or both of these need to be set */ | ||
| 237 | if (!cpoint_type || !cpoint_name) | ||
| 238 | return -EINVAL; | ||
| 239 | |||
| 240 | cptype = parse_cp_type(cpoint_type, strlen(cpoint_type)); | ||
| 241 | if (cptype == NONE) | ||
| 242 | return -EINVAL; | ||
| 243 | |||
| 244 | for (i = 0; i < ARRAY_SIZE(cp_name); i++) { | ||
| 205 | if (!strcmp(cpoint_name, cp_name[i])) { | 245 | if (!strcmp(cpoint_name, cp_name[i])) { |
| 206 | cpoint = i + 1; | 246 | cpoint = i + 1; |
| 207 | break; | 247 | return 0; |
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | for (i = 0; i < NUM_CPOINT_TYPES; ++i) { | ||
| 212 | if (!strcmp(cpoint_type, cp_type[i])) { | ||
| 213 | cptype = i + 1; | ||
| 214 | break; | ||
| 215 | } | 248 | } |
| 216 | } | 249 | } |
| 217 | 250 | ||
| 218 | if (cpoint == INVALID || cptype == NONE) | 251 | /* Could not find a valid crash point */ |
| 219 | return -EINVAL; | 252 | return -EINVAL; |
| 220 | |||
| 221 | count = cpoint_count; | ||
| 222 | |||
| 223 | return 0; | ||
| 224 | } | 253 | } |
| 225 | 254 | ||
| 226 | static int recursive_loop(int a) | 255 | static int recursive_loop(int a) |
| @@ -235,53 +264,92 @@ static int recursive_loop(int a) | |||
| 235 | return recursive_loop(a); | 264 | return recursive_loop(a); |
| 236 | } | 265 | } |
| 237 | 266 | ||
| 238 | void lkdtm_handler(void) | 267 | static void lkdtm_do_action(enum ctype which) |
| 239 | { | 268 | { |
| 240 | printk(KERN_INFO "lkdtm : Crash point %s of type %s hit\n", | 269 | switch (which) { |
| 241 | cpoint_name, cpoint_type); | 270 | case PANIC: |
| 242 | --count; | 271 | panic("dumptest"); |
| 272 | break; | ||
| 273 | case BUG: | ||
| 274 | BUG(); | ||
| 275 | break; | ||
| 276 | case EXCEPTION: | ||
| 277 | *((int *) 0) = 0; | ||
| 278 | break; | ||
| 279 | case LOOP: | ||
| 280 | for (;;) | ||
| 281 | ; | ||
| 282 | break; | ||
| 283 | case OVERFLOW: | ||
| 284 | (void) recursive_loop(0); | ||
| 285 | break; | ||
| 286 | case CORRUPT_STACK: { | ||
| 287 | volatile u32 data[8]; | ||
| 288 | volatile u32 *p = data; | ||
| 289 | |||
| 290 | p[12] = 0x12345678; | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | case UNALIGNED_LOAD_STORE_WRITE: { | ||
| 294 | static u8 data[5] __attribute__((aligned(4))) = {1, 2, | ||
| 295 | 3, 4, 5}; | ||
| 296 | u32 *p; | ||
| 297 | u32 val = 0x12345678; | ||
| 298 | |||
| 299 | p = (u32 *)(data + 1); | ||
| 300 | if (*p == 0) | ||
| 301 | val = 0x87654321; | ||
| 302 | *p = val; | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | case OVERWRITE_ALLOCATION: { | ||
| 306 | size_t len = 1020; | ||
| 307 | u32 *data = kmalloc(len, GFP_KERNEL); | ||
| 308 | |||
| 309 | data[1024 / sizeof(u32)] = 0x12345678; | ||
| 310 | kfree(data); | ||
| 311 | break; | ||
| 312 | } | ||
| 313 | case WRITE_AFTER_FREE: { | ||
| 314 | size_t len = 1024; | ||
| 315 | u32 *data = kmalloc(len, GFP_KERNEL); | ||
| 316 | |||
| 317 | kfree(data); | ||
| 318 | schedule(); | ||
| 319 | memset(data, 0x78, len); | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | case NONE: | ||
| 323 | default: | ||
| 324 | break; | ||
| 325 | } | ||
| 326 | |||
| 327 | } | ||
| 328 | |||
| 329 | static void lkdtm_handler(void) | ||
| 330 | { | ||
| 331 | count--; | ||
| 332 | printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n", | ||
| 333 | cp_name_to_str(cpoint), cp_type_to_str(cptype), count); | ||
| 243 | 334 | ||
| 244 | if (count == 0) { | 335 | if (count == 0) { |
| 245 | switch (cptype) { | 336 | lkdtm_do_action(cptype); |
| 246 | case NONE: | ||
| 247 | break; | ||
| 248 | case PANIC: | ||
| 249 | printk(KERN_INFO "lkdtm : PANIC\n"); | ||
| 250 | panic("dumptest"); | ||
| 251 | break; | ||
| 252 | case BUG: | ||
| 253 | printk(KERN_INFO "lkdtm : BUG\n"); | ||
| 254 | BUG(); | ||
| 255 | break; | ||
| 256 | case EXCEPTION: | ||
| 257 | printk(KERN_INFO "lkdtm : EXCEPTION\n"); | ||
| 258 | *((int *) 0) = 0; | ||
| 259 | break; | ||
| 260 | case LOOP: | ||
| 261 | printk(KERN_INFO "lkdtm : LOOP\n"); | ||
| 262 | for (;;); | ||
| 263 | break; | ||
| 264 | case OVERFLOW: | ||
| 265 | printk(KERN_INFO "lkdtm : OVERFLOW\n"); | ||
| 266 | (void) recursive_loop(0); | ||
| 267 | break; | ||
| 268 | default: | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | count = cpoint_count; | 337 | count = cpoint_count; |
| 272 | } | 338 | } |
| 273 | } | 339 | } |
| 274 | 340 | ||
| 275 | static int __init lkdtm_module_init(void) | 341 | static int lkdtm_register_cpoint(enum cname which) |
| 276 | { | 342 | { |
| 277 | int ret; | 343 | int ret; |
| 278 | 344 | ||
| 279 | if (lkdtm_parse_commandline() == -EINVAL) { | 345 | cpoint = INVALID; |
| 280 | printk(KERN_INFO "lkdtm : Invalid command\n"); | 346 | if (lkdtm.entry != NULL) |
| 281 | return -EINVAL; | 347 | unregister_jprobe(&lkdtm); |
| 282 | } | ||
| 283 | 348 | ||
| 284 | switch (cpoint) { | 349 | switch (which) { |
| 350 | case DIRECT: | ||
| 351 | lkdtm_do_action(cptype); | ||
| 352 | return 0; | ||
| 285 | case INT_HARDWARE_ENTRY: | 353 | case INT_HARDWARE_ENTRY: |
| 286 | lkdtm.kp.symbol_name = "do_IRQ"; | 354 | lkdtm.kp.symbol_name = "do_IRQ"; |
| 287 | lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; | 355 | lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; |
| @@ -315,28 +383,268 @@ static int __init lkdtm_module_init(void) | |||
| 315 | lkdtm.kp.symbol_name = "generic_ide_ioctl"; | 383 | lkdtm.kp.symbol_name = "generic_ide_ioctl"; |
| 316 | lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; | 384 | lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl; |
| 317 | #else | 385 | #else |
| 318 | printk(KERN_INFO "lkdtm : Crash point not available\n"); | 386 | printk(KERN_INFO "lkdtm: Crash point not available\n"); |
| 387 | return -EINVAL; | ||
| 319 | #endif | 388 | #endif |
| 320 | break; | 389 | break; |
| 321 | default: | 390 | default: |
| 322 | printk(KERN_INFO "lkdtm : Invalid Crash Point\n"); | 391 | printk(KERN_INFO "lkdtm: Invalid Crash Point\n"); |
| 323 | break; | 392 | return -EINVAL; |
| 324 | } | 393 | } |
| 325 | 394 | ||
| 395 | cpoint = which; | ||
| 326 | if ((ret = register_jprobe(&lkdtm)) < 0) { | 396 | if ((ret = register_jprobe(&lkdtm)) < 0) { |
| 327 | printk(KERN_INFO "lkdtm : Couldn't register jprobe\n"); | 397 | printk(KERN_INFO "lkdtm: Couldn't register jprobe\n"); |
| 328 | return ret; | 398 | cpoint = INVALID; |
| 399 | } | ||
| 400 | |||
| 401 | return ret; | ||
| 402 | } | ||
| 403 | |||
| 404 | static ssize_t do_register_entry(enum cname which, struct file *f, | ||
| 405 | const char __user *user_buf, size_t count, loff_t *off) | ||
| 406 | { | ||
| 407 | char *buf; | ||
| 408 | int err; | ||
| 409 | |||
| 410 | if (count >= PAGE_SIZE) | ||
| 411 | return -EINVAL; | ||
| 412 | |||
| 413 | buf = (char *)__get_free_page(GFP_KERNEL); | ||
| 414 | if (!buf) | ||
| 415 | return -ENOMEM; | ||
| 416 | if (copy_from_user(buf, user_buf, count)) { | ||
| 417 | free_page((unsigned long) buf); | ||
| 418 | return -EFAULT; | ||
| 419 | } | ||
| 420 | /* NULL-terminate and remove enter */ | ||
| 421 | buf[count] = '\0'; | ||
| 422 | strim(buf); | ||
| 423 | |||
| 424 | cptype = parse_cp_type(buf, count); | ||
| 425 | free_page((unsigned long) buf); | ||
| 426 | |||
| 427 | if (cptype == NONE) | ||
| 428 | return -EINVAL; | ||
| 429 | |||
| 430 | err = lkdtm_register_cpoint(which); | ||
| 431 | if (err < 0) | ||
| 432 | return err; | ||
| 433 | |||
| 434 | *off += count; | ||
| 435 | |||
| 436 | return count; | ||
| 437 | } | ||
| 438 | |||
| 439 | /* Generic read callback that just prints out the available crash types */ | ||
| 440 | static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf, | ||
| 441 | size_t count, loff_t *off) | ||
| 442 | { | ||
| 443 | char *buf; | ||
| 444 | int i, n, out; | ||
| 445 | |||
| 446 | buf = (char *)__get_free_page(GFP_KERNEL); | ||
| 447 | |||
| 448 | n = snprintf(buf, PAGE_SIZE, "Available crash types:\n"); | ||
| 449 | for (i = 0; i < ARRAY_SIZE(cp_type); i++) | ||
| 450 | n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]); | ||
| 451 | buf[n] = '\0'; | ||
| 452 | |||
| 453 | out = simple_read_from_buffer(user_buf, count, off, | ||
| 454 | buf, n); | ||
| 455 | free_page((unsigned long) buf); | ||
| 456 | |||
| 457 | return out; | ||
| 458 | } | ||
| 459 | |||
| 460 | static int lkdtm_debugfs_open(struct inode *inode, struct file *file) | ||
| 461 | { | ||
| 462 | return 0; | ||
| 463 | } | ||
| 464 | |||
| 465 | |||
| 466 | static ssize_t int_hardware_entry(struct file *f, const char __user *buf, | ||
| 467 | size_t count, loff_t *off) | ||
| 468 | { | ||
| 469 | return do_register_entry(INT_HARDWARE_ENTRY, f, buf, count, off); | ||
| 470 | } | ||
| 471 | |||
| 472 | static ssize_t int_hw_irq_en(struct file *f, const char __user *buf, | ||
| 473 | size_t count, loff_t *off) | ||
| 474 | { | ||
| 475 | return do_register_entry(INT_HW_IRQ_EN, f, buf, count, off); | ||
| 476 | } | ||
| 477 | |||
| 478 | static ssize_t int_tasklet_entry(struct file *f, const char __user *buf, | ||
| 479 | size_t count, loff_t *off) | ||
| 480 | { | ||
| 481 | return do_register_entry(INT_TASKLET_ENTRY, f, buf, count, off); | ||
| 482 | } | ||
| 483 | |||
| 484 | static ssize_t fs_devrw_entry(struct file *f, const char __user *buf, | ||
| 485 | size_t count, loff_t *off) | ||
| 486 | { | ||
| 487 | return do_register_entry(FS_DEVRW, f, buf, count, off); | ||
| 488 | } | ||
| 489 | |||
| 490 | static ssize_t mem_swapout_entry(struct file *f, const char __user *buf, | ||
| 491 | size_t count, loff_t *off) | ||
| 492 | { | ||
| 493 | return do_register_entry(MEM_SWAPOUT, f, buf, count, off); | ||
| 494 | } | ||
| 495 | |||
| 496 | static ssize_t timeradd_entry(struct file *f, const char __user *buf, | ||
| 497 | size_t count, loff_t *off) | ||
| 498 | { | ||
| 499 | return do_register_entry(TIMERADD, f, buf, count, off); | ||
| 500 | } | ||
| 501 | |||
| 502 | static ssize_t scsi_dispatch_cmd_entry(struct file *f, | ||
| 503 | const char __user *buf, size_t count, loff_t *off) | ||
| 504 | { | ||
| 505 | return do_register_entry(SCSI_DISPATCH_CMD, f, buf, count, off); | ||
| 506 | } | ||
| 507 | |||
| 508 | static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf, | ||
| 509 | size_t count, loff_t *off) | ||
| 510 | { | ||
| 511 | return do_register_entry(IDE_CORE_CP, f, buf, count, off); | ||
| 512 | } | ||
| 513 | |||
| 514 | /* Special entry to just crash directly. Available without KPROBEs */ | ||
| 515 | static ssize_t direct_entry(struct file *f, const char __user *user_buf, | ||
| 516 | size_t count, loff_t *off) | ||
| 517 | { | ||
| 518 | enum ctype type; | ||
| 519 | char *buf; | ||
| 520 | |||
| 521 | if (count >= PAGE_SIZE) | ||
| 522 | return -EINVAL; | ||
| 523 | if (count < 1) | ||
| 524 | return -EINVAL; | ||
| 525 | |||
| 526 | buf = (char *)__get_free_page(GFP_KERNEL); | ||
| 527 | if (!buf) | ||
| 528 | return -ENOMEM; | ||
| 529 | if (copy_from_user(buf, user_buf, count)) { | ||
| 530 | free_page((unsigned long) buf); | ||
| 531 | return -EFAULT; | ||
| 532 | } | ||
| 533 | /* NULL-terminate and remove enter */ | ||
| 534 | buf[count] = '\0'; | ||
| 535 | strim(buf); | ||
| 536 | |||
| 537 | type = parse_cp_type(buf, count); | ||
| 538 | free_page((unsigned long) buf); | ||
| 539 | if (type == NONE) | ||
| 540 | return -EINVAL; | ||
| 541 | |||
| 542 | printk(KERN_INFO "lkdtm: Performing direct entry %s\n", | ||
| 543 | cp_type_to_str(type)); | ||
| 544 | lkdtm_do_action(type); | ||
| 545 | *off += count; | ||
| 546 | |||
| 547 | return count; | ||
| 548 | } | ||
| 549 | |||
| 550 | struct crash_entry { | ||
| 551 | const char *name; | ||
| 552 | const struct file_operations fops; | ||
| 553 | }; | ||
| 554 | |||
| 555 | static const struct crash_entry crash_entries[] = { | ||
| 556 | {"DIRECT", {.read = lkdtm_debugfs_read, | ||
| 557 | .open = lkdtm_debugfs_open, | ||
| 558 | .write = direct_entry} }, | ||
| 559 | {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read, | ||
| 560 | .open = lkdtm_debugfs_open, | ||
| 561 | .write = int_hardware_entry} }, | ||
| 562 | {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read, | ||
| 563 | .open = lkdtm_debugfs_open, | ||
| 564 | .write = int_hw_irq_en} }, | ||
| 565 | {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read, | ||
| 566 | .open = lkdtm_debugfs_open, | ||
| 567 | .write = int_tasklet_entry} }, | ||
| 568 | {"FS_DEVRW", {.read = lkdtm_debugfs_read, | ||
| 569 | .open = lkdtm_debugfs_open, | ||
| 570 | .write = fs_devrw_entry} }, | ||
| 571 | {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read, | ||
| 572 | .open = lkdtm_debugfs_open, | ||
| 573 | .write = mem_swapout_entry} }, | ||
| 574 | {"TIMERADD", {.read = lkdtm_debugfs_read, | ||
| 575 | .open = lkdtm_debugfs_open, | ||
| 576 | .write = timeradd_entry} }, | ||
| 577 | {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read, | ||
| 578 | .open = lkdtm_debugfs_open, | ||
| 579 | .write = scsi_dispatch_cmd_entry} }, | ||
| 580 | {"IDE_CORE_CP", {.read = lkdtm_debugfs_read, | ||
| 581 | .open = lkdtm_debugfs_open, | ||
| 582 | .write = ide_core_cp_entry} }, | ||
| 583 | }; | ||
| 584 | |||
| 585 | static struct dentry *lkdtm_debugfs_root; | ||
| 586 | |||
| 587 | static int __init lkdtm_module_init(void) | ||
| 588 | { | ||
| 589 | int ret = -EINVAL; | ||
| 590 | int n_debugfs_entries = 1; /* Assume only the direct entry */ | ||
| 591 | int i; | ||
| 592 | |||
| 593 | /* Register debugfs interface */ | ||
| 594 | lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL); | ||
| 595 | if (!lkdtm_debugfs_root) { | ||
| 596 | printk(KERN_ERR "lkdtm: creating root dir failed\n"); | ||
| 597 | return -ENODEV; | ||
| 598 | } | ||
| 599 | |||
| 600 | #ifdef CONFIG_KPROBES | ||
| 601 | n_debugfs_entries = ARRAY_SIZE(crash_entries); | ||
| 602 | #endif | ||
| 603 | |||
| 604 | for (i = 0; i < n_debugfs_entries; i++) { | ||
| 605 | const struct crash_entry *cur = &crash_entries[i]; | ||
| 606 | struct dentry *de; | ||
| 607 | |||
| 608 | de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root, | ||
| 609 | NULL, &cur->fops); | ||
| 610 | if (de == NULL) { | ||
| 611 | printk(KERN_ERR "lkdtm: could not create %s\n", | ||
| 612 | cur->name); | ||
| 613 | goto out_err; | ||
| 614 | } | ||
| 615 | } | ||
| 616 | |||
| 617 | if (lkdtm_parse_commandline() == -EINVAL) { | ||
| 618 | printk(KERN_INFO "lkdtm: Invalid command\n"); | ||
| 619 | goto out_err; | ||
| 620 | } | ||
| 621 | |||
| 622 | if (cpoint != INVALID && cptype != NONE) { | ||
| 623 | ret = lkdtm_register_cpoint(cpoint); | ||
| 624 | if (ret < 0) { | ||
| 625 | printk(KERN_INFO "lkdtm: Invalid crash point %d\n", | ||
| 626 | cpoint); | ||
| 627 | goto out_err; | ||
| 628 | } | ||
| 629 | printk(KERN_INFO "lkdtm: Crash point %s of type %s registered\n", | ||
| 630 | cpoint_name, cpoint_type); | ||
| 631 | } else { | ||
| 632 | printk(KERN_INFO "lkdtm: No crash points registered, enable through debugfs\n"); | ||
| 329 | } | 633 | } |
| 330 | 634 | ||
| 331 | printk(KERN_INFO "lkdtm : Crash point %s of type %s registered\n", | ||
| 332 | cpoint_name, cpoint_type); | ||
| 333 | return 0; | 635 | return 0; |
| 636 | |||
| 637 | out_err: | ||
| 638 | debugfs_remove_recursive(lkdtm_debugfs_root); | ||
| 639 | return ret; | ||
| 334 | } | 640 | } |
| 335 | 641 | ||
| 336 | static void __exit lkdtm_module_exit(void) | 642 | static void __exit lkdtm_module_exit(void) |
| 337 | { | 643 | { |
| 338 | unregister_jprobe(&lkdtm); | 644 | debugfs_remove_recursive(lkdtm_debugfs_root); |
| 339 | printk(KERN_INFO "lkdtm : Crash point unregistered\n"); | 645 | |
| 646 | unregister_jprobe(&lkdtm); | ||
| 647 | printk(KERN_INFO "lkdtm: Crash point unregistered\n"); | ||
| 340 | } | 648 | } |
| 341 | 649 | ||
| 342 | module_init(lkdtm_module_init); | 650 | module_init(lkdtm_module_init); |
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 16f0abda1423..57b152f8d1b9 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c | |||
| @@ -475,7 +475,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 475 | 475 | ||
| 476 | if (skb->data[0] == 0xff) { | 476 | if (skb->data[0] == 0xff) { |
| 477 | /* we are being asked to broadcast to all partitions */ | 477 | /* we are being asked to broadcast to all partitions */ |
| 478 | for_each_bit(dest_partid, xpnet_broadcast_partitions, | 478 | for_each_set_bit(dest_partid, xpnet_broadcast_partitions, |
| 479 | xp_max_npartitions) { | 479 | xp_max_npartitions) { |
| 480 | 480 | ||
| 481 | xpnet_send(skb, queued_msg, start_addr, end_addr, | 481 | xpnet_send(skb, queued_msg, start_addr, end_addr, |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 30acd5265821..f4b97d3c3d0f 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -1151,6 +1151,9 @@ void mmc_stop_host(struct mmc_host *host) | |||
| 1151 | cancel_delayed_work(&host->detect); | 1151 | cancel_delayed_work(&host->detect); |
| 1152 | mmc_flush_scheduled_work(); | 1152 | mmc_flush_scheduled_work(); |
| 1153 | 1153 | ||
| 1154 | /* clear pm flags now and let card drivers set them as needed */ | ||
| 1155 | host->pm_flags = 0; | ||
| 1156 | |||
| 1154 | mmc_bus_get(host); | 1157 | mmc_bus_get(host); |
| 1155 | if (host->bus_ops && !host->bus_dead) { | 1158 | if (host->bus_ops && !host->bus_dead) { |
| 1156 | if (host->bus_ops->remove) | 1159 | if (host->bus_ops->remove) |
| @@ -1273,12 +1276,13 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) | |||
| 1273 | mmc_claim_host(host); | 1276 | mmc_claim_host(host); |
| 1274 | mmc_detach_bus(host); | 1277 | mmc_detach_bus(host); |
| 1275 | mmc_release_host(host); | 1278 | mmc_release_host(host); |
| 1279 | host->pm_flags = 0; | ||
| 1276 | err = 0; | 1280 | err = 0; |
| 1277 | } | 1281 | } |
| 1278 | } | 1282 | } |
| 1279 | mmc_bus_put(host); | 1283 | mmc_bus_put(host); |
| 1280 | 1284 | ||
| 1281 | if (!err) | 1285 | if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) |
| 1282 | mmc_power_off(host); | 1286 | mmc_power_off(host); |
| 1283 | 1287 | ||
| 1284 | return err; | 1288 | return err; |
| @@ -1296,8 +1300,10 @@ int mmc_resume_host(struct mmc_host *host) | |||
| 1296 | 1300 | ||
| 1297 | mmc_bus_get(host); | 1301 | mmc_bus_get(host); |
| 1298 | if (host->bus_ops && !host->bus_dead) { | 1302 | if (host->bus_ops && !host->bus_dead) { |
| 1299 | mmc_power_up(host); | 1303 | if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { |
| 1300 | mmc_select_voltage(host, host->ocr); | 1304 | mmc_power_up(host); |
| 1305 | mmc_select_voltage(host, host->ocr); | ||
| 1306 | } | ||
| 1301 | BUG_ON(!host->bus_ops->resume); | 1307 | BUG_ON(!host->bus_ops->resume); |
| 1302 | err = host->bus_ops->resume(host); | 1308 | err = host->bus_ops->resume(host); |
| 1303 | if (err) { | 1309 | if (err) { |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 06b64085a355..2dd4cfe7ca17 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -188,6 +188,40 @@ static int sdio_disable_cd(struct mmc_card *card) | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | /* | 190 | /* |
| 191 | * Devices that remain active during a system suspend are | ||
| 192 | * put back into 1-bit mode. | ||
| 193 | */ | ||
| 194 | static int sdio_disable_wide(struct mmc_card *card) | ||
| 195 | { | ||
| 196 | int ret; | ||
| 197 | u8 ctrl; | ||
| 198 | |||
| 199 | if (!(card->host->caps & MMC_CAP_4_BIT_DATA)) | ||
| 200 | return 0; | ||
| 201 | |||
| 202 | if (card->cccr.low_speed && !card->cccr.wide_bus) | ||
| 203 | return 0; | ||
| 204 | |||
| 205 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); | ||
| 206 | if (ret) | ||
| 207 | return ret; | ||
| 208 | |||
| 209 | if (!(ctrl & SDIO_BUS_WIDTH_4BIT)) | ||
| 210 | return 0; | ||
| 211 | |||
| 212 | ctrl &= ~SDIO_BUS_WIDTH_4BIT; | ||
| 213 | ctrl |= SDIO_BUS_ASYNC_INT; | ||
| 214 | |||
| 215 | ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); | ||
| 216 | if (ret) | ||
| 217 | return ret; | ||
| 218 | |||
| 219 | mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1); | ||
| 220 | |||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | |||
| 224 | /* | ||
| 191 | * Test if the card supports high-speed mode and, if so, switch to it. | 225 | * Test if the card supports high-speed mode and, if so, switch to it. |
| 192 | */ | 226 | */ |
| 193 | static int sdio_enable_hs(struct mmc_card *card) | 227 | static int sdio_enable_hs(struct mmc_card *card) |
| @@ -224,7 +258,7 @@ static int sdio_enable_hs(struct mmc_card *card) | |||
| 224 | * we're trying to reinitialise. | 258 | * we're trying to reinitialise. |
| 225 | */ | 259 | */ |
| 226 | static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | 260 | static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, |
| 227 | struct mmc_card *oldcard) | 261 | struct mmc_card *oldcard, int powered_resume) |
| 228 | { | 262 | { |
| 229 | struct mmc_card *card; | 263 | struct mmc_card *card; |
| 230 | int err; | 264 | int err; |
| @@ -235,9 +269,11 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 235 | /* | 269 | /* |
| 236 | * Inform the card of the voltage | 270 | * Inform the card of the voltage |
| 237 | */ | 271 | */ |
| 238 | err = mmc_send_io_op_cond(host, host->ocr, &ocr); | 272 | if (!powered_resume) { |
| 239 | if (err) | 273 | err = mmc_send_io_op_cond(host, host->ocr, &ocr); |
| 240 | goto err; | 274 | if (err) |
| 275 | goto err; | ||
| 276 | } | ||
| 241 | 277 | ||
| 242 | /* | 278 | /* |
| 243 | * For SPI, enable CRC as appropriate. | 279 | * For SPI, enable CRC as appropriate. |
| @@ -262,7 +298,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 262 | /* | 298 | /* |
| 263 | * For native busses: set card RCA and quit open drain mode. | 299 | * For native busses: set card RCA and quit open drain mode. |
| 264 | */ | 300 | */ |
| 265 | if (!mmc_host_is_spi(host)) { | 301 | if (!powered_resume && !mmc_host_is_spi(host)) { |
| 266 | err = mmc_send_relative_addr(host, &card->rca); | 302 | err = mmc_send_relative_addr(host, &card->rca); |
| 267 | if (err) | 303 | if (err) |
| 268 | goto remove; | 304 | goto remove; |
| @@ -273,7 +309,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
| 273 | /* | 309 | /* |
| 274 | * Select card, as all following commands rely on that. | 310 | * Select card, as all following commands rely on that. |
| 275 | */ | 311 | */ |
| 276 | if (!mmc_host_is_spi(host)) { | 312 | if (!powered_resume && !mmc_host_is_spi(host)) { |
| 277 | err = mmc_select_card(card); | 313 | err = mmc_select_card(card); |
| 278 | if (err) | 314 | if (err) |
| 279 | goto remove; | 315 | goto remove; |
| @@ -425,6 +461,12 @@ static int mmc_sdio_suspend(struct mmc_host *host) | |||
| 425 | } | 461 | } |
| 426 | } | 462 | } |
| 427 | 463 | ||
| 464 | if (!err && host->pm_flags & MMC_PM_KEEP_POWER) { | ||
| 465 | mmc_claim_host(host); | ||
| 466 | sdio_disable_wide(host->card); | ||
| 467 | mmc_release_host(host); | ||
| 468 | } | ||
| 469 | |||
| 428 | return err; | 470 | return err; |
| 429 | } | 471 | } |
| 430 | 472 | ||
| @@ -437,7 +479,13 @@ static int mmc_sdio_resume(struct mmc_host *host) | |||
| 437 | 479 | ||
| 438 | /* Basic card reinitialization. */ | 480 | /* Basic card reinitialization. */ |
| 439 | mmc_claim_host(host); | 481 | mmc_claim_host(host); |
| 440 | err = mmc_sdio_init_card(host, host->ocr, host->card); | 482 | err = mmc_sdio_init_card(host, host->ocr, host->card, |
| 483 | (host->pm_flags & MMC_PM_KEEP_POWER)); | ||
| 484 | if (!err) | ||
| 485 | /* We may have switched to 1-bit mode during suspend. */ | ||
| 486 | err = sdio_enable_wide(host->card); | ||
| 487 | if (!err && host->sdio_irqs) | ||
| 488 | mmc_signal_sdio_irq(host); | ||
| 441 | mmc_release_host(host); | 489 | mmc_release_host(host); |
| 442 | 490 | ||
| 443 | /* | 491 | /* |
| @@ -507,7 +555,7 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
| 507 | /* | 555 | /* |
| 508 | * Detect and init the card. | 556 | * Detect and init the card. |
| 509 | */ | 557 | */ |
| 510 | err = mmc_sdio_init_card(host, host->ocr, NULL); | 558 | err = mmc_sdio_init_card(host, host->ocr, NULL, 0); |
| 511 | if (err) | 559 | if (err) |
| 512 | goto err; | 560 | goto err; |
| 513 | card = host->card; | 561 | card = host->card; |
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index f9aa8a7deffa..ff27c8c71355 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c | |||
| @@ -189,7 +189,12 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func) | |||
| 189 | { | 189 | { |
| 190 | unsigned mval = min(func->card->host->max_seg_size, | 190 | unsigned mval = min(func->card->host->max_seg_size, |
| 191 | func->card->host->max_blk_size); | 191 | func->card->host->max_blk_size); |
| 192 | mval = min(mval, func->max_blksize); | 192 | |
| 193 | if (mmc_blksz_for_byte_mode(func->card)) | ||
| 194 | mval = min(mval, func->cur_blksize); | ||
| 195 | else | ||
| 196 | mval = min(mval, func->max_blksize); | ||
| 197 | |||
| 193 | return min(mval, 512u); /* maximum size for byte mode */ | 198 | return min(mval, 512u); /* maximum size for byte mode */ |
| 194 | } | 199 | } |
| 195 | 200 | ||
| @@ -635,3 +640,52 @@ void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, | |||
| 635 | *err_ret = ret; | 640 | *err_ret = ret; |
| 636 | } | 641 | } |
| 637 | EXPORT_SYMBOL_GPL(sdio_f0_writeb); | 642 | EXPORT_SYMBOL_GPL(sdio_f0_writeb); |
| 643 | |||
| 644 | /** | ||
| 645 | * sdio_get_host_pm_caps - get host power management capabilities | ||
| 646 | * @func: SDIO function attached to host | ||
| 647 | * | ||
| 648 | * Returns a capability bitmask corresponding to power management | ||
| 649 | * features supported by the host controller that the card function | ||
| 650 | * might rely upon during a system suspend. The host doesn't need | ||
| 651 | * to be claimed, nor the function active, for this information to be | ||
| 652 | * obtained. | ||
| 653 | */ | ||
| 654 | mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func) | ||
| 655 | { | ||
| 656 | BUG_ON(!func); | ||
| 657 | BUG_ON(!func->card); | ||
| 658 | |||
| 659 | return func->card->host->pm_caps; | ||
| 660 | } | ||
| 661 | EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps); | ||
| 662 | |||
| 663 | /** | ||
| 664 | * sdio_set_host_pm_flags - set wanted host power management capabilities | ||
| 665 | * @func: SDIO function attached to host | ||
| 666 | * | ||
| 667 | * Set a capability bitmask corresponding to wanted host controller | ||
| 668 | * power management features for the upcoming suspend state. | ||
| 669 | * This must be called, if needed, each time the suspend method of | ||
| 670 | * the function driver is called, and must contain only bits that | ||
| 671 | * were returned by sdio_get_host_pm_caps(). | ||
| 672 | * The host doesn't need to be claimed, nor the function active, | ||
| 673 | * for this information to be set. | ||
| 674 | */ | ||
| 675 | int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags) | ||
| 676 | { | ||
| 677 | struct mmc_host *host; | ||
| 678 | |||
| 679 | BUG_ON(!func); | ||
| 680 | BUG_ON(!func->card); | ||
| 681 | |||
| 682 | host = func->card->host; | ||
| 683 | |||
| 684 | if (flags & ~host->pm_caps) | ||
| 685 | return -EINVAL; | ||
| 686 | |||
| 687 | /* function suspend methods are serialized, hence no lock needed */ | ||
| 688 | host->pm_flags |= flags; | ||
| 689 | return 0; | ||
| 690 | } | ||
| 691 | EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags); | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index ce1d28884e29..7b431bbab7f1 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -69,20 +69,16 @@ config MMC_SDHCI_PCI | |||
| 69 | If unsure, say N. | 69 | If unsure, say N. |
| 70 | 70 | ||
| 71 | config MMC_RICOH_MMC | 71 | config MMC_RICOH_MMC |
| 72 | tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)" | 72 | bool "Ricoh MMC Controller Disabler (EXPERIMENTAL)" |
| 73 | depends on MMC_SDHCI_PCI | 73 | depends on MMC_SDHCI_PCI |
| 74 | help | 74 | help |
| 75 | This selects the disabler for the Ricoh MMC Controller. This | 75 | This adds a pci quirk to disable Ricoh MMC Controller. This |
| 76 | proprietary controller is unnecessary because the SDHCI driver | 76 | proprietary controller is unnecessary because the SDHCI driver |
| 77 | supports MMC cards on the SD controller, but if it is not | 77 | supports MMC cards on the SD controller, but if it is not |
| 78 | disabled, it will steal the MMC cards away - rendering them | 78 | disabled, it will steal the MMC cards away - rendering them |
| 79 | useless. It is safe to select this driver even if you don't | 79 | useless. It is safe to select this even if you don't |
| 80 | have a Ricoh based card reader. | 80 | have a Ricoh based card reader. |
| 81 | 81 | ||
| 82 | |||
| 83 | To compile this driver as a module, choose M here: | ||
| 84 | the module will be called ricoh_mmc. | ||
| 85 | |||
| 86 | If unsure, say Y. | 82 | If unsure, say Y. |
| 87 | 83 | ||
| 88 | config MMC_SDHCI_OF | 84 | config MMC_SDHCI_OF |
| @@ -193,6 +189,7 @@ config MMC_AU1X | |||
| 193 | 189 | ||
| 194 | choice | 190 | choice |
| 195 | prompt "Atmel SD/MMC Driver" | 191 | prompt "Atmel SD/MMC Driver" |
| 192 | depends on AVR32 || ARCH_AT91 | ||
| 196 | default MMC_ATMELMCI if AVR32 | 193 | default MMC_ATMELMCI if AVR32 |
| 197 | help | 194 | help |
| 198 | Choose which driver to use for the Atmel MCI Silicon | 195 | Choose which driver to use for the Atmel MCI Silicon |
| @@ -399,7 +396,7 @@ config MMC_VIA_SDMMC | |||
| 399 | 396 | ||
| 400 | config SDH_BFIN | 397 | config SDH_BFIN |
| 401 | tristate "Blackfin Secure Digital Host support" | 398 | tristate "Blackfin Secure Digital Host support" |
| 402 | depends on MMC && ((BF54x && !BF544) || (BF51x && !BF512)) | 399 | depends on (BF54x && !BF544) || (BF51x && !BF512) |
| 403 | help | 400 | help |
| 404 | If you say yes here you will get support for the Blackfin on-chip | 401 | If you say yes here you will get support for the Blackfin on-chip |
| 405 | Secure Digital Host interface. This includes support for MMC and | 402 | Secure Digital Host interface. This includes support for MMC and |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 3d253dd4240f..f4803977dfce 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -12,7 +12,6 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o | |||
| 12 | obj-$(CONFIG_MMC_MXC) += mxcmmc.o | 12 | obj-$(CONFIG_MMC_MXC) += mxcmmc.o |
| 13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
| 14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
| 15 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o | ||
| 16 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o | 15 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o |
| 17 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 16 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
| 18 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 17 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 63924e0c7ea9..91dc60cd032b 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
| @@ -78,6 +78,17 @@ | |||
| 78 | 78 | ||
| 79 | #define DRIVER_NAME "at91_mci" | 79 | #define DRIVER_NAME "at91_mci" |
| 80 | 80 | ||
| 81 | static inline int at91mci_is_mci1rev2xx(void) | ||
| 82 | { | ||
| 83 | return ( cpu_is_at91sam9260() | ||
| 84 | || cpu_is_at91sam9263() | ||
| 85 | || cpu_is_at91cap9() | ||
| 86 | || cpu_is_at91sam9rl() | ||
| 87 | || cpu_is_at91sam9g10() | ||
| 88 | || cpu_is_at91sam9g20() | ||
| 89 | ); | ||
| 90 | } | ||
| 91 | |||
| 81 | #define FL_SENT_COMMAND (1 << 0) | 92 | #define FL_SENT_COMMAND (1 << 0) |
| 82 | #define FL_SENT_STOP (1 << 1) | 93 | #define FL_SENT_STOP (1 << 1) |
| 83 | 94 | ||
| @@ -88,6 +99,10 @@ | |||
| 88 | #define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg)) | 99 | #define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg)) |
| 89 | #define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg)) | 100 | #define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg)) |
| 90 | 101 | ||
| 102 | #define MCI_BLKSIZE 512 | ||
| 103 | #define MCI_MAXBLKSIZE 4095 | ||
| 104 | #define MCI_BLKATONCE 256 | ||
| 105 | #define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE) | ||
| 91 | 106 | ||
| 92 | /* | 107 | /* |
| 93 | * Low level type for this driver | 108 | * Low level type for this driver |
| @@ -200,8 +215,8 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
| 200 | size = data->blksz * data->blocks; | 215 | size = data->blksz * data->blocks; |
| 201 | len = data->sg_len; | 216 | len = data->sg_len; |
| 202 | 217 | ||
| 203 | /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */ | 218 | /* MCI1 rev2xx Data Write Operation and number of bytes erratum */ |
| 204 | if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) | 219 | if (at91mci_is_mci1rev2xx()) |
| 205 | if (host->total_length == 12) | 220 | if (host->total_length == 12) |
| 206 | memset(dmabuf, 0, 12); | 221 | memset(dmabuf, 0, 12); |
| 207 | 222 | ||
| @@ -227,8 +242,10 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
| 227 | for (index = 0; index < (amount / 4); index++) | 242 | for (index = 0; index < (amount / 4); index++) |
| 228 | *dmabuf++ = swab32(sgbuffer[index]); | 243 | *dmabuf++ = swab32(sgbuffer[index]); |
| 229 | } else { | 244 | } else { |
| 230 | memcpy(dmabuf, sgbuffer, amount); | 245 | char *tmpv = (char *)dmabuf; |
| 231 | dmabuf += amount; | 246 | memcpy(tmpv, sgbuffer, amount); |
| 247 | tmpv += amount; | ||
| 248 | dmabuf = (unsigned *)tmpv; | ||
| 232 | } | 249 | } |
| 233 | 250 | ||
| 234 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 251 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); |
| @@ -245,80 +262,14 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data | |||
| 245 | } | 262 | } |
| 246 | 263 | ||
| 247 | /* | 264 | /* |
| 248 | * Prepare a dma read | ||
| 249 | */ | ||
| 250 | static void at91_mci_pre_dma_read(struct at91mci_host *host) | ||
| 251 | { | ||
| 252 | int i; | ||
| 253 | struct scatterlist *sg; | ||
| 254 | struct mmc_command *cmd; | ||
| 255 | struct mmc_data *data; | ||
| 256 | |||
| 257 | pr_debug("pre dma read\n"); | ||
| 258 | |||
| 259 | cmd = host->cmd; | ||
| 260 | if (!cmd) { | ||
| 261 | pr_debug("no command\n"); | ||
| 262 | return; | ||
| 263 | } | ||
| 264 | |||
| 265 | data = cmd->data; | ||
| 266 | if (!data) { | ||
| 267 | pr_debug("no data\n"); | ||
| 268 | return; | ||
| 269 | } | ||
| 270 | |||
| 271 | for (i = 0; i < 2; i++) { | ||
| 272 | /* nothing left to transfer */ | ||
| 273 | if (host->transfer_index >= data->sg_len) { | ||
| 274 | pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index); | ||
| 275 | break; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* Check to see if this needs filling */ | ||
| 279 | if (i == 0) { | ||
| 280 | if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) { | ||
| 281 | pr_debug("Transfer active in current\n"); | ||
| 282 | continue; | ||
| 283 | } | ||
| 284 | } | ||
| 285 | else { | ||
| 286 | if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) { | ||
| 287 | pr_debug("Transfer active in next\n"); | ||
| 288 | continue; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | /* Setup the next transfer */ | ||
| 293 | pr_debug("Using transfer index %d\n", host->transfer_index); | ||
| 294 | |||
| 295 | sg = &data->sg[host->transfer_index++]; | ||
| 296 | pr_debug("sg = %p\n", sg); | ||
| 297 | |||
| 298 | sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE); | ||
| 299 | |||
| 300 | pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); | ||
| 301 | |||
| 302 | if (i == 0) { | ||
| 303 | at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address); | ||
| 304 | at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4); | ||
| 305 | } | ||
| 306 | else { | ||
| 307 | at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address); | ||
| 308 | at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | pr_debug("pre dma read done\n"); | ||
| 313 | } | ||
| 314 | |||
| 315 | /* | ||
| 316 | * Handle after a dma read | 265 | * Handle after a dma read |
| 317 | */ | 266 | */ |
| 318 | static void at91_mci_post_dma_read(struct at91mci_host *host) | 267 | static void at91_mci_post_dma_read(struct at91mci_host *host) |
| 319 | { | 268 | { |
| 320 | struct mmc_command *cmd; | 269 | struct mmc_command *cmd; |
| 321 | struct mmc_data *data; | 270 | struct mmc_data *data; |
| 271 | unsigned int len, i, size; | ||
| 272 | unsigned *dmabuf = host->buffer; | ||
| 322 | 273 | ||
| 323 | pr_debug("post dma read\n"); | 274 | pr_debug("post dma read\n"); |
| 324 | 275 | ||
| @@ -334,42 +285,39 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) | |||
| 334 | return; | 285 | return; |
| 335 | } | 286 | } |
| 336 | 287 | ||
| 337 | while (host->in_use_index < host->transfer_index) { | 288 | size = data->blksz * data->blocks; |
| 338 | struct scatterlist *sg; | 289 | len = data->sg_len; |
| 339 | 290 | ||
| 340 | pr_debug("finishing index %d\n", host->in_use_index); | 291 | at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX); |
| 292 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); | ||
| 341 | 293 | ||
| 342 | sg = &data->sg[host->in_use_index++]; | 294 | for (i = 0; i < len; i++) { |
| 295 | struct scatterlist *sg; | ||
| 296 | int amount; | ||
| 297 | unsigned int *sgbuffer; | ||
| 343 | 298 | ||
| 344 | pr_debug("Unmapping page %08X\n", sg->dma_address); | 299 | sg = &data->sg[i]; |
| 345 | 300 | ||
| 346 | dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE); | 301 | sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; |
| 302 | amount = min(size, sg->length); | ||
| 303 | size -= amount; | ||
| 347 | 304 | ||
| 348 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ | 305 | if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */ |
| 349 | unsigned int *buffer; | ||
| 350 | int index; | 306 | int index; |
| 351 | 307 | for (index = 0; index < (amount / 4); index++) | |
| 352 | /* Swap the contents of the buffer */ | 308 | sgbuffer[index] = swab32(*dmabuf++); |
| 353 | buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | 309 | } else { |
| 354 | pr_debug("buffer = %p, length = %d\n", buffer, sg->length); | 310 | char *tmpv = (char *)dmabuf; |
| 355 | 311 | memcpy(sgbuffer, tmpv, amount); | |
| 356 | for (index = 0; index < (sg->length / 4); index++) | 312 | tmpv += amount; |
| 357 | buffer[index] = swab32(buffer[index]); | 313 | dmabuf = (unsigned *)tmpv; |
| 358 | |||
| 359 | kunmap_atomic(buffer, KM_BIO_SRC_IRQ); | ||
| 360 | } | 314 | } |
| 361 | 315 | ||
| 362 | flush_dcache_page(sg_page(sg)); | 316 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); |
| 363 | 317 | dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount); | |
| 364 | data->bytes_xfered += sg->length; | 318 | data->bytes_xfered += amount; |
| 365 | } | 319 | if (size == 0) |
| 366 | 320 | break; | |
| 367 | /* Is there another transfer to trigger? */ | ||
| 368 | if (host->transfer_index < data->sg_len) | ||
| 369 | at91_mci_pre_dma_read(host); | ||
| 370 | else { | ||
| 371 | at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX); | ||
| 372 | at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF); | ||
| 373 | } | 321 | } |
| 374 | 322 | ||
| 375 | pr_debug("post dma read done\n"); | 323 | pr_debug("post dma read done\n"); |
| @@ -461,7 +409,7 @@ static void at91_mci_enable(struct at91mci_host *host) | |||
| 461 | at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); | 409 | at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC); |
| 462 | mr = AT91_MCI_PDCMODE | 0x34a; | 410 | mr = AT91_MCI_PDCMODE | 0x34a; |
| 463 | 411 | ||
| 464 | if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) | 412 | if (at91mci_is_mci1rev2xx()) |
| 465 | mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF; | 413 | mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF; |
| 466 | 414 | ||
| 467 | at91_mci_write(host, AT91_MCI_MR, mr); | 415 | at91_mci_write(host, AT91_MCI_MR, mr); |
| @@ -602,10 +550,14 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
| 602 | /* | 550 | /* |
| 603 | * Handle a read | 551 | * Handle a read |
| 604 | */ | 552 | */ |
| 605 | host->buffer = NULL; | ||
| 606 | host->total_length = 0; | 553 | host->total_length = 0; |
| 607 | 554 | ||
| 608 | at91_mci_pre_dma_read(host); | 555 | at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address); |
| 556 | at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? | ||
| 557 | (blocks * block_length) : (blocks * block_length) / 4); | ||
| 558 | at91_mci_write(host, ATMEL_PDC_RNPR, 0); | ||
| 559 | at91_mci_write(host, ATMEL_PDC_RNCR, 0); | ||
| 560 | |||
| 609 | ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */; | 561 | ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */; |
| 610 | } | 562 | } |
| 611 | else { | 563 | else { |
| @@ -614,27 +566,15 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command | |||
| 614 | */ | 566 | */ |
| 615 | host->total_length = block_length * blocks; | 567 | host->total_length = block_length * blocks; |
| 616 | /* | 568 | /* |
| 617 | * AT91SAM926[0/3] Data Write Operation and | 569 | * MCI1 rev2xx Data Write Operation and |
| 618 | * number of bytes erratum | 570 | * number of bytes erratum |
| 619 | */ | 571 | */ |
| 620 | if (cpu_is_at91sam9260 () || cpu_is_at91sam9263()) | 572 | if (at91mci_is_mci1rev2xx()) |
| 621 | if (host->total_length < 12) | 573 | if (host->total_length < 12) |
| 622 | host->total_length = 12; | 574 | host->total_length = 12; |
| 623 | 575 | ||
| 624 | host->buffer = kmalloc(host->total_length, GFP_KERNEL); | ||
| 625 | if (!host->buffer) { | ||
| 626 | pr_debug("Can't alloc tx buffer\n"); | ||
| 627 | cmd->error = -ENOMEM; | ||
| 628 | mmc_request_done(host->mmc, host->request); | ||
| 629 | return; | ||
| 630 | } | ||
| 631 | |||
| 632 | at91_mci_sg_to_dma(host, data); | 576 | at91_mci_sg_to_dma(host, data); |
| 633 | 577 | ||
| 634 | host->physical_address = dma_map_single(NULL, | ||
| 635 | host->buffer, host->total_length, | ||
| 636 | DMA_TO_DEVICE); | ||
| 637 | |||
| 638 | pr_debug("Transmitting %d bytes\n", host->total_length); | 578 | pr_debug("Transmitting %d bytes\n", host->total_length); |
| 639 | 579 | ||
| 640 | at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); | 580 | at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address); |
| @@ -701,14 +641,6 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s | |||
| 701 | cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2)); | 641 | cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2)); |
| 702 | cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); | 642 | cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3)); |
| 703 | 643 | ||
| 704 | if (host->buffer) { | ||
| 705 | dma_unmap_single(NULL, | ||
| 706 | host->physical_address, host->total_length, | ||
| 707 | DMA_TO_DEVICE); | ||
| 708 | kfree(host->buffer); | ||
| 709 | host->buffer = NULL; | ||
| 710 | } | ||
| 711 | |||
| 712 | pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n", | 644 | pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n", |
| 713 | status, at91_mci_read(host, AT91_MCI_SR), | 645 | status, at91_mci_read(host, AT91_MCI_SR), |
| 714 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); | 646 | cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); |
| @@ -754,7 +686,8 @@ static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 754 | host->request = mrq; | 686 | host->request = mrq; |
| 755 | host->flags = 0; | 687 | host->flags = 0; |
| 756 | 688 | ||
| 757 | mod_timer(&host->timer, jiffies + HZ); | 689 | /* more than 1s timeout needed with slow SD cards */ |
| 690 | mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000)); | ||
| 758 | 691 | ||
| 759 | at91_mci_process_next(host); | 692 | at91_mci_process_next(host); |
| 760 | } | 693 | } |
| @@ -942,7 +875,8 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host) | |||
| 942 | pr_debug("****** Resetting SD-card bus width ******\n"); | 875 | pr_debug("****** Resetting SD-card bus width ******\n"); |
| 943 | at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); | 876 | at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS); |
| 944 | } | 877 | } |
| 945 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | 878 | /* 0.5s needed because of early card detect switch firing */ |
| 879 | mmc_detect_change(host->mmc, msecs_to_jiffies(500)); | ||
| 946 | } | 880 | } |
| 947 | return IRQ_HANDLED; | 881 | return IRQ_HANDLED; |
| 948 | } | 882 | } |
| @@ -1006,24 +940,42 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 1006 | mmc->f_min = 375000; | 940 | mmc->f_min = 375000; |
| 1007 | mmc->f_max = 25000000; | 941 | mmc->f_max = 25000000; |
| 1008 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 942 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
| 1009 | mmc->caps = MMC_CAP_SDIO_IRQ; | 943 | mmc->caps = 0; |
| 1010 | 944 | ||
| 1011 | mmc->max_blk_size = 4095; | 945 | mmc->max_blk_size = MCI_MAXBLKSIZE; |
| 1012 | mmc->max_blk_count = mmc->max_req_size; | 946 | mmc->max_blk_count = MCI_BLKATONCE; |
| 947 | mmc->max_req_size = MCI_BUFSIZE; | ||
| 948 | mmc->max_phys_segs = MCI_BLKATONCE; | ||
| 949 | mmc->max_hw_segs = MCI_BLKATONCE; | ||
| 950 | mmc->max_seg_size = MCI_BUFSIZE; | ||
| 1013 | 951 | ||
| 1014 | host = mmc_priv(mmc); | 952 | host = mmc_priv(mmc); |
| 1015 | host->mmc = mmc; | 953 | host->mmc = mmc; |
| 1016 | host->buffer = NULL; | ||
| 1017 | host->bus_mode = 0; | 954 | host->bus_mode = 0; |
| 1018 | host->board = pdev->dev.platform_data; | 955 | host->board = pdev->dev.platform_data; |
| 1019 | if (host->board->wire4) { | 956 | if (host->board->wire4) { |
| 1020 | if (cpu_is_at91sam9260() || cpu_is_at91sam9263()) | 957 | if (at91mci_is_mci1rev2xx()) |
| 1021 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 958 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
| 1022 | else | 959 | else |
| 1023 | dev_warn(&pdev->dev, "4 wire bus mode not supported" | 960 | dev_warn(&pdev->dev, "4 wire bus mode not supported" |
| 1024 | " - using 1 wire\n"); | 961 | " - using 1 wire\n"); |
| 1025 | } | 962 | } |
| 1026 | 963 | ||
| 964 | host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE, | ||
| 965 | &host->physical_address, GFP_KERNEL); | ||
| 966 | if (!host->buffer) { | ||
| 967 | ret = -ENOMEM; | ||
| 968 | dev_err(&pdev->dev, "Can't allocate transmit buffer\n"); | ||
| 969 | goto fail5; | ||
| 970 | } | ||
| 971 | |||
| 972 | /* Add SDIO capability when available */ | ||
| 973 | if (at91mci_is_mci1rev2xx()) { | ||
| 974 | /* at91mci MCI1 rev2xx sdio interrupt erratum */ | ||
| 975 | if (host->board->wire4 || !host->board->slot_b) | ||
| 976 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
| 977 | } | ||
| 978 | |||
| 1027 | /* | 979 | /* |
| 1028 | * Reserve GPIOs ... board init code makes sure these pins are set | 980 | * Reserve GPIOs ... board init code makes sure these pins are set |
| 1029 | * up as GPIOs with the right direction (input, except for vcc) | 981 | * up as GPIOs with the right direction (input, except for vcc) |
| @@ -1032,7 +984,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
| 1032 | ret = gpio_request(host->board->det_pin, "mmc_detect"); | 984 | ret = gpio_request(host->board->det_pin, "mmc_detect"); |
| 1033 | if (ret < 0) { | 985 | if (ret < 0) { |
| 1034 | dev_dbg(&pdev->dev, "couldn't claim card detect pin\n"); | 986 | dev_dbg(&pdev->dev, "couldn't claim card detect pin\n"); |
| 1035 | goto fail5; | 987 | goto fail4b; |
| 1036 | } | 988 | } |
| 1037 | } | 989 | } |
| 1038 | if (host->board->wp_pin) { | 990 | if (host->board->wp_pin) { |
| @@ -1132,6 +1084,10 @@ fail3: | |||
| 1132 | fail4: | 1084 | fail4: |
| 1133 | if (host->board->det_pin) | 1085 | if (host->board->det_pin) |
| 1134 | gpio_free(host->board->det_pin); | 1086 | gpio_free(host->board->det_pin); |
| 1087 | fail4b: | ||
| 1088 | if (host->buffer) | ||
| 1089 | dma_free_coherent(&pdev->dev, MCI_BUFSIZE, | ||
| 1090 | host->buffer, host->physical_address); | ||
| 1135 | fail5: | 1091 | fail5: |
| 1136 | mmc_free_host(mmc); | 1092 | mmc_free_host(mmc); |
| 1137 | fail6: | 1093 | fail6: |
| @@ -1154,6 +1110,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev) | |||
| 1154 | 1110 | ||
| 1155 | host = mmc_priv(mmc); | 1111 | host = mmc_priv(mmc); |
| 1156 | 1112 | ||
| 1113 | if (host->buffer) | ||
| 1114 | dma_free_coherent(&pdev->dev, MCI_BUFSIZE, | ||
| 1115 | host->buffer, host->physical_address); | ||
| 1116 | |||
| 1157 | if (host->board->det_pin) { | 1117 | if (host->board->det_pin) { |
| 1158 | if (device_can_wakeup(&pdev->dev)) | 1118 | if (device_can_wakeup(&pdev->dev)) |
| 1159 | free_irq(gpio_to_irq(host->board->det_pin), host); | 1119 | free_irq(gpio_to_irq(host->board->det_pin), host); |
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 3343a57355cc..56f7b448b911 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
| @@ -115,7 +115,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 115 | unsigned int length; | 115 | unsigned int length; |
| 116 | unsigned int data_ctl; | 116 | unsigned int data_ctl; |
| 117 | unsigned int dma_cfg; | 117 | unsigned int dma_cfg; |
| 118 | struct scatterlist *sg; | 118 | unsigned int cycle_ns, timeout; |
| 119 | 119 | ||
| 120 | dev_dbg(mmc_dev(host->mmc), "%s enter flags: 0x%x\n", __func__, data->flags); | 120 | dev_dbg(mmc_dev(host->mmc), "%s enter flags: 0x%x\n", __func__, data->flags); |
| 121 | host->data = data; | 121 | host->data = data; |
| @@ -136,8 +136,11 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 136 | data_ctl |= ((ffs(data->blksz) - 1) << 4); | 136 | data_ctl |= ((ffs(data->blksz) - 1) << 4); |
| 137 | 137 | ||
| 138 | bfin_write_SDH_DATA_CTL(data_ctl); | 138 | bfin_write_SDH_DATA_CTL(data_ctl); |
| 139 | 139 | /* the time of a host clock period in ns */ | |
| 140 | bfin_write_SDH_DATA_TIMER(0xFFFF); | 140 | cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1))); |
| 141 | timeout = data->timeout_ns / cycle_ns; | ||
| 142 | timeout += data->timeout_clks; | ||
| 143 | bfin_write_SDH_DATA_TIMER(timeout); | ||
| 141 | SSYNC(); | 144 | SSYNC(); |
| 142 | 145 | ||
| 143 | if (data->flags & MMC_DATA_READ) { | 146 | if (data->flags & MMC_DATA_READ) { |
| @@ -151,6 +154,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
| 151 | #if defined(CONFIG_BF54x) | 154 | #if defined(CONFIG_BF54x) |
| 152 | dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN; | 155 | dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN; |
| 153 | { | 156 | { |
| 157 | struct scatterlist *sg; | ||
| 154 | int i; | 158 | int i; |
| 155 | for_each_sg(data->sg, sg, host->dma_len, i) { | 159 | for_each_sg(data->sg, sg, host->dma_len, i) { |
| 156 | host->sg_cpu[i].start_addr = sg_dma_address(sg); | 160 | host->sg_cpu[i].start_addr = sg_dma_address(sg); |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index dd45e7c3517e..3bd0ba294e9d 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -73,6 +73,7 @@ | |||
| 73 | /* DAVINCI_MMCCTL definitions */ | 73 | /* DAVINCI_MMCCTL definitions */ |
| 74 | #define MMCCTL_DATRST (1 << 0) | 74 | #define MMCCTL_DATRST (1 << 0) |
| 75 | #define MMCCTL_CMDRST (1 << 1) | 75 | #define MMCCTL_CMDRST (1 << 1) |
| 76 | #define MMCCTL_WIDTH_8_BIT (1 << 8) | ||
| 76 | #define MMCCTL_WIDTH_4_BIT (1 << 2) | 77 | #define MMCCTL_WIDTH_4_BIT (1 << 2) |
| 77 | #define MMCCTL_DATEG_DISABLED (0 << 6) | 78 | #define MMCCTL_DATEG_DISABLED (0 << 6) |
| 78 | #define MMCCTL_DATEG_RISING (1 << 6) | 79 | #define MMCCTL_DATEG_RISING (1 << 6) |
| @@ -791,22 +792,42 @@ static void calculate_clk_divider(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 791 | 792 | ||
| 792 | static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 793 | static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
| 793 | { | 794 | { |
| 794 | unsigned int mmc_pclk = 0; | ||
| 795 | struct mmc_davinci_host *host = mmc_priv(mmc); | 795 | struct mmc_davinci_host *host = mmc_priv(mmc); |
| 796 | 796 | ||
| 797 | mmc_pclk = host->mmc_input_clk; | ||
| 798 | dev_dbg(mmc_dev(host->mmc), | 797 | dev_dbg(mmc_dev(host->mmc), |
| 799 | "clock %dHz busmode %d powermode %d Vdd %04x\n", | 798 | "clock %dHz busmode %d powermode %d Vdd %04x\n", |
| 800 | ios->clock, ios->bus_mode, ios->power_mode, | 799 | ios->clock, ios->bus_mode, ios->power_mode, |
| 801 | ios->vdd); | 800 | ios->vdd); |
| 802 | if (ios->bus_width == MMC_BUS_WIDTH_4) { | 801 | |
| 803 | dev_dbg(mmc_dev(host->mmc), "Enabling 4 bit mode\n"); | 802 | switch (ios->bus_width) { |
| 804 | writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_WIDTH_4_BIT, | 803 | case MMC_BUS_WIDTH_8: |
| 805 | host->base + DAVINCI_MMCCTL); | 804 | dev_dbg(mmc_dev(host->mmc), "Enabling 8 bit mode\n"); |
| 806 | } else { | 805 | writel((readl(host->base + DAVINCI_MMCCTL) & |
| 807 | dev_dbg(mmc_dev(host->mmc), "Disabling 4 bit mode\n"); | 806 | ~MMCCTL_WIDTH_4_BIT) | MMCCTL_WIDTH_8_BIT, |
| 808 | writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_WIDTH_4_BIT, | ||
| 809 | host->base + DAVINCI_MMCCTL); | 807 | host->base + DAVINCI_MMCCTL); |
| 808 | break; | ||
| 809 | case MMC_BUS_WIDTH_4: | ||
| 810 | dev_dbg(mmc_dev(host->mmc), "Enabling 4 bit mode\n"); | ||
| 811 | if (host->version == MMC_CTLR_VERSION_2) | ||
| 812 | writel((readl(host->base + DAVINCI_MMCCTL) & | ||
| 813 | ~MMCCTL_WIDTH_8_BIT) | MMCCTL_WIDTH_4_BIT, | ||
| 814 | host->base + DAVINCI_MMCCTL); | ||
| 815 | else | ||
| 816 | writel(readl(host->base + DAVINCI_MMCCTL) | | ||
| 817 | MMCCTL_WIDTH_4_BIT, | ||
| 818 | host->base + DAVINCI_MMCCTL); | ||
| 819 | break; | ||
| 820 | case MMC_BUS_WIDTH_1: | ||
| 821 | dev_dbg(mmc_dev(host->mmc), "Enabling 1 bit mode\n"); | ||
| 822 | if (host->version == MMC_CTLR_VERSION_2) | ||
| 823 | writel(readl(host->base + DAVINCI_MMCCTL) & | ||
| 824 | ~(MMCCTL_WIDTH_8_BIT | MMCCTL_WIDTH_4_BIT), | ||
| 825 | host->base + DAVINCI_MMCCTL); | ||
| 826 | else | ||
| 827 | writel(readl(host->base + DAVINCI_MMCCTL) & | ||
| 828 | ~MMCCTL_WIDTH_4_BIT, | ||
| 829 | host->base + DAVINCI_MMCCTL); | ||
| 830 | break; | ||
| 810 | } | 831 | } |
| 811 | 832 | ||
| 812 | calculate_clk_divider(mmc, ios); | 833 | calculate_clk_divider(mmc, ios); |
| @@ -1189,10 +1210,14 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
| 1189 | 1210 | ||
| 1190 | /* REVISIT: someday, support IRQ-driven card detection. */ | 1211 | /* REVISIT: someday, support IRQ-driven card detection. */ |
| 1191 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 1212 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
| 1213 | mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; | ||
| 1192 | 1214 | ||
| 1193 | if (!pdata || pdata->wires == 4 || pdata->wires == 0) | 1215 | if (pdata && (pdata->wires == 4 || pdata->wires == 0)) |
| 1194 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1216 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
| 1195 | 1217 | ||
| 1218 | if (pdata && (pdata->wires == 8)) | ||
| 1219 | mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA); | ||
| 1220 | |||
| 1196 | host->version = pdata->version; | 1221 | host->version = pdata->version; |
| 1197 | 1222 | ||
| 1198 | mmc->ops = &mmc_davinci_ops; | 1223 | mmc->ops = &mmc_davinci_ops; |
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c deleted file mode 100644 index f62790513322..000000000000 --- a/drivers/mmc/host/ricoh_mmc.c +++ /dev/null | |||
| @@ -1,262 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * ricoh_mmc.c - Dummy driver to disable the Rioch MMC controller. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Philip Langdale, All Rights Reserved. | ||
| 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 (at | ||
| 9 | * your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* | ||
| 13 | * This is a conceptually ridiculous driver, but it is required by the way | ||
| 14 | * the Ricoh multi-function chips (R5CXXX) work. These chips implement | ||
| 15 | * the four main memory card controllers (SD, MMC, MS, xD) and one or both | ||
| 16 | * of cardbus or firewire. It happens that they implement SD and MMC | ||
| 17 | * support as separate controllers (and PCI functions). The linux SDHCI | ||
| 18 | * driver supports MMC cards but the chip detects MMC cards in hardware | ||
| 19 | * and directs them to the MMC controller - so the SDHCI driver never sees | ||
| 20 | * them. To get around this, we must disable the useless MMC controller. | ||
| 21 | * At that point, the SDHCI controller will start seeing them. As a bonus, | ||
| 22 | * a detection event occurs immediately, even if the MMC card is already | ||
| 23 | * in the reader. | ||
| 24 | * | ||
| 25 | * It seems to be the case that the relevant PCI registers to deactivate the | ||
| 26 | * MMC controller live on PCI function 0, which might be the cardbus controller | ||
| 27 | * or the firewire controller, depending on the particular chip in question. As | ||
| 28 | * such, it makes what this driver has to do unavoidably ugly. Such is life. | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/pci.h> | ||
| 32 | |||
| 33 | #define DRIVER_NAME "ricoh-mmc" | ||
| 34 | |||
| 35 | static const struct pci_device_id pci_ids[] __devinitdata = { | ||
| 36 | { | ||
| 37 | .vendor = PCI_VENDOR_ID_RICOH, | ||
| 38 | .device = PCI_DEVICE_ID_RICOH_R5C843, | ||
| 39 | .subvendor = PCI_ANY_ID, | ||
| 40 | .subdevice = PCI_ANY_ID, | ||
| 41 | }, | ||
| 42 | { /* end: all zeroes */ }, | ||
| 43 | }; | ||
| 44 | |||
| 45 | MODULE_DEVICE_TABLE(pci, pci_ids); | ||
| 46 | |||
| 47 | static int ricoh_mmc_disable(struct pci_dev *fw_dev) | ||
| 48 | { | ||
| 49 | u8 write_enable; | ||
| 50 | u8 write_target; | ||
| 51 | u8 disable; | ||
| 52 | |||
| 53 | if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) { | ||
| 54 | /* via RL5C476 */ | ||
| 55 | |||
| 56 | pci_read_config_byte(fw_dev, 0xB7, &disable); | ||
| 57 | if (disable & 0x02) { | ||
| 58 | printk(KERN_INFO DRIVER_NAME | ||
| 59 | ": Controller already disabled. " \ | ||
| 60 | "Nothing to do.\n"); | ||
| 61 | return -ENODEV; | ||
| 62 | } | ||
| 63 | |||
| 64 | pci_read_config_byte(fw_dev, 0x8E, &write_enable); | ||
| 65 | pci_write_config_byte(fw_dev, 0x8E, 0xAA); | ||
| 66 | pci_read_config_byte(fw_dev, 0x8D, &write_target); | ||
| 67 | pci_write_config_byte(fw_dev, 0x8D, 0xB7); | ||
| 68 | pci_write_config_byte(fw_dev, 0xB7, disable | 0x02); | ||
| 69 | pci_write_config_byte(fw_dev, 0x8E, write_enable); | ||
| 70 | pci_write_config_byte(fw_dev, 0x8D, write_target); | ||
| 71 | } else { | ||
| 72 | /* via R5C832 */ | ||
| 73 | |||
| 74 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 75 | if (disable & 0x02) { | ||
| 76 | printk(KERN_INFO DRIVER_NAME | ||
| 77 | ": Controller already disabled. " \ | ||
| 78 | "Nothing to do.\n"); | ||
| 79 | return -ENODEV; | ||
| 80 | } | ||
| 81 | |||
| 82 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 83 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 84 | pci_write_config_byte(fw_dev, 0xCB, disable | 0x02); | ||
| 85 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 86 | } | ||
| 87 | |||
| 88 | printk(KERN_INFO DRIVER_NAME | ||
| 89 | ": Controller is now disabled.\n"); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static int ricoh_mmc_enable(struct pci_dev *fw_dev) | ||
| 95 | { | ||
| 96 | u8 write_enable; | ||
| 97 | u8 write_target; | ||
| 98 | u8 disable; | ||
| 99 | |||
| 100 | if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) { | ||
| 101 | /* via RL5C476 */ | ||
| 102 | |||
| 103 | pci_read_config_byte(fw_dev, 0x8E, &write_enable); | ||
| 104 | pci_write_config_byte(fw_dev, 0x8E, 0xAA); | ||
| 105 | pci_read_config_byte(fw_dev, 0x8D, &write_target); | ||
| 106 | pci_write_config_byte(fw_dev, 0x8D, 0xB7); | ||
| 107 | pci_read_config_byte(fw_dev, 0xB7, &disable); | ||
| 108 | pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02); | ||
| 109 | pci_write_config_byte(fw_dev, 0x8E, write_enable); | ||
| 110 | pci_write_config_byte(fw_dev, 0x8D, write_target); | ||
| 111 | } else { | ||
| 112 | /* via R5C832 */ | ||
| 113 | |||
| 114 | pci_read_config_byte(fw_dev, 0xCA, &write_enable); | ||
| 115 | pci_read_config_byte(fw_dev, 0xCB, &disable); | ||
| 116 | pci_write_config_byte(fw_dev, 0xCA, 0x57); | ||
| 117 | pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02); | ||
| 118 | pci_write_config_byte(fw_dev, 0xCA, write_enable); | ||
| 119 | } | ||
| 120 | |||
| 121 | printk(KERN_INFO DRIVER_NAME | ||
| 122 | ": Controller is now re-enabled.\n"); | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int __devinit ricoh_mmc_probe(struct pci_dev *pdev, | ||
| 128 | const struct pci_device_id *ent) | ||
| 129 | { | ||
| 130 | u8 rev; | ||
| 131 | u8 ctrlfound = 0; | ||
| 132 | |||
| 133 | struct pci_dev *fw_dev = NULL; | ||
| 134 | |||
| 135 | BUG_ON(pdev == NULL); | ||
| 136 | BUG_ON(ent == NULL); | ||
| 137 | |||
| 138 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev); | ||
| 139 | |||
| 140 | printk(KERN_INFO DRIVER_NAME | ||
| 141 | ": Ricoh MMC controller found at %s [%04x:%04x] (rev %x)\n", | ||
| 142 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, | ||
| 143 | (int)rev); | ||
| 144 | |||
| 145 | while ((fw_dev = | ||
| 146 | pci_get_device(PCI_VENDOR_ID_RICOH, | ||
| 147 | PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) { | ||
| 148 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | ||
| 149 | PCI_FUNC(fw_dev->devfn) == 0 && | ||
| 150 | pdev->bus == fw_dev->bus) { | ||
| 151 | if (ricoh_mmc_disable(fw_dev) != 0) | ||
| 152 | return -ENODEV; | ||
| 153 | |||
| 154 | pci_set_drvdata(pdev, fw_dev); | ||
| 155 | |||
| 156 | ++ctrlfound; | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | fw_dev = NULL; | ||
| 162 | |||
| 163 | while (!ctrlfound && | ||
| 164 | (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, | ||
| 165 | PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) { | ||
| 166 | if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) && | ||
| 167 | PCI_FUNC(fw_dev->devfn) == 0 && | ||
| 168 | pdev->bus == fw_dev->bus) { | ||
| 169 | if (ricoh_mmc_disable(fw_dev) != 0) | ||
| 170 | return -ENODEV; | ||
| 171 | |||
| 172 | pci_set_drvdata(pdev, fw_dev); | ||
| 173 | |||
| 174 | ++ctrlfound; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | if (!ctrlfound) { | ||
| 179 | printk(KERN_WARNING DRIVER_NAME | ||
| 180 | ": Main Ricoh function not found. Cannot disable controller.\n"); | ||
| 181 | return -ENODEV; | ||
| 182 | } | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static void __devexit ricoh_mmc_remove(struct pci_dev *pdev) | ||
| 188 | { | ||
| 189 | struct pci_dev *fw_dev = NULL; | ||
| 190 | |||
| 191 | fw_dev = pci_get_drvdata(pdev); | ||
| 192 | BUG_ON(fw_dev == NULL); | ||
| 193 | |||
| 194 | ricoh_mmc_enable(fw_dev); | ||
| 195 | |||
| 196 | pci_set_drvdata(pdev, NULL); | ||
| 197 | } | ||
| 198 | |||
| 199 | static int ricoh_mmc_suspend_late(struct pci_dev *pdev, pm_message_t state) | ||
| 200 | { | ||
| 201 | struct pci_dev *fw_dev = NULL; | ||
| 202 | |||
| 203 | fw_dev = pci_get_drvdata(pdev); | ||
| 204 | BUG_ON(fw_dev == NULL); | ||
| 205 | |||
| 206 | printk(KERN_INFO DRIVER_NAME ": Suspending.\n"); | ||
| 207 | |||
| 208 | ricoh_mmc_enable(fw_dev); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int ricoh_mmc_resume_early(struct pci_dev *pdev) | ||
| 214 | { | ||
| 215 | struct pci_dev *fw_dev = NULL; | ||
| 216 | |||
| 217 | fw_dev = pci_get_drvdata(pdev); | ||
| 218 | BUG_ON(fw_dev == NULL); | ||
| 219 | |||
| 220 | printk(KERN_INFO DRIVER_NAME ": Resuming.\n"); | ||
| 221 | |||
| 222 | ricoh_mmc_disable(fw_dev); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static struct pci_driver ricoh_mmc_driver = { | ||
| 228 | .name = DRIVER_NAME, | ||
| 229 | .id_table = pci_ids, | ||
| 230 | .probe = ricoh_mmc_probe, | ||
| 231 | .remove = __devexit_p(ricoh_mmc_remove), | ||
| 232 | .suspend_late = ricoh_mmc_suspend_late, | ||
| 233 | .resume_early = ricoh_mmc_resume_early, | ||
| 234 | }; | ||
| 235 | |||
| 236 | /*****************************************************************************\ | ||
| 237 | * * | ||
| 238 | * Driver init/exit * | ||
| 239 | * * | ||
| 240 | \*****************************************************************************/ | ||
| 241 | |||
| 242 | static int __init ricoh_mmc_drv_init(void) | ||
| 243 | { | ||
| 244 | printk(KERN_INFO DRIVER_NAME | ||
| 245 | ": Ricoh MMC Controller disabling driver\n"); | ||
| 246 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Philip Langdale\n"); | ||
| 247 | |||
| 248 | return pci_register_driver(&ricoh_mmc_driver); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void __exit ricoh_mmc_drv_exit(void) | ||
| 252 | { | ||
| 253 | pci_unregister_driver(&ricoh_mmc_driver); | ||
| 254 | } | ||
| 255 | |||
| 256 | module_init(ricoh_mmc_drv_init); | ||
| 257 | module_exit(ricoh_mmc_drv_exit); | ||
| 258 | |||
| 259 | MODULE_AUTHOR("Philip Langdale <philipl@alumni.utexas.net>"); | ||
| 260 | MODULE_DESCRIPTION("Ricoh MMC Controller disabling driver"); | ||
| 261 | MODULE_LICENSE("GPL"); | ||
| 262 | |||
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index d96e1abf2d64..2fdf7689ae6c 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
| @@ -1179,7 +1179,7 @@ static int s3cmci_card_present(struct mmc_host *mmc) | |||
| 1179 | struct s3c24xx_mci_pdata *pdata = host->pdata; | 1179 | struct s3c24xx_mci_pdata *pdata = host->pdata; |
| 1180 | int ret; | 1180 | int ret; |
| 1181 | 1181 | ||
| 1182 | if (pdata->gpio_detect == 0) | 1182 | if (pdata->no_detect) |
| 1183 | return -ENOSYS; | 1183 | return -ENOSYS; |
| 1184 | 1184 | ||
| 1185 | ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1; | 1185 | ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1; |
| @@ -1360,6 +1360,8 @@ static struct mmc_host_ops s3cmci_ops = { | |||
| 1360 | static struct s3c24xx_mci_pdata s3cmci_def_pdata = { | 1360 | static struct s3c24xx_mci_pdata s3cmci_def_pdata = { |
| 1361 | /* This is currently here to avoid a number of if (host->pdata) | 1361 | /* This is currently here to avoid a number of if (host->pdata) |
| 1362 | * checks. Any zero fields to ensure reasonable defaults are picked. */ | 1362 | * checks. Any zero fields to ensure reasonable defaults are picked. */ |
| 1363 | .no_wprotect = 1, | ||
| 1364 | .no_detect = 1, | ||
| 1363 | }; | 1365 | }; |
| 1364 | 1366 | ||
| 1365 | #ifdef CONFIG_CPU_FREQ | 1367 | #ifdef CONFIG_CPU_FREQ |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 5c3a1767770a..8e1020cf73f4 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -80,9 +80,6 @@ struct sdhci_pci_chip { | |||
| 80 | 80 | ||
| 81 | static int ricoh_probe(struct sdhci_pci_chip *chip) | 81 | static int ricoh_probe(struct sdhci_pci_chip *chip) |
| 82 | { | 82 | { |
| 83 | if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) | ||
| 84 | chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET; | ||
| 85 | |||
| 86 | if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG || | 83 | if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG || |
| 87 | chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY) | 84 | chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY) |
| 88 | chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET; | 85 | chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET; |
| @@ -92,7 +89,9 @@ static int ricoh_probe(struct sdhci_pci_chip *chip) | |||
| 92 | 89 | ||
| 93 | static const struct sdhci_pci_fixes sdhci_ricoh = { | 90 | static const struct sdhci_pci_fixes sdhci_ricoh = { |
| 94 | .probe = ricoh_probe, | 91 | .probe = ricoh_probe, |
| 95 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR, | 92 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | |
| 93 | SDHCI_QUIRK_FORCE_DMA | | ||
| 94 | SDHCI_QUIRK_CLOCK_BEFORE_RESET, | ||
| 96 | }; | 95 | }; |
| 97 | 96 | ||
| 98 | static const struct sdhci_pci_fixes sdhci_ene_712 = { | 97 | static const struct sdhci_pci_fixes sdhci_ene_712 = { |
| @@ -501,6 +500,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 501 | { | 500 | { |
| 502 | struct sdhci_pci_chip *chip; | 501 | struct sdhci_pci_chip *chip; |
| 503 | struct sdhci_pci_slot *slot; | 502 | struct sdhci_pci_slot *slot; |
| 503 | mmc_pm_flag_t pm_flags = 0; | ||
| 504 | int i, ret; | 504 | int i, ret; |
| 505 | 505 | ||
| 506 | chip = pci_get_drvdata(pdev); | 506 | chip = pci_get_drvdata(pdev); |
| @@ -519,6 +519,8 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 519 | sdhci_resume_host(chip->slots[i]->host); | 519 | sdhci_resume_host(chip->slots[i]->host); |
| 520 | return ret; | 520 | return ret; |
| 521 | } | 521 | } |
| 522 | |||
| 523 | pm_flags |= slot->host->mmc->pm_flags; | ||
| 522 | } | 524 | } |
| 523 | 525 | ||
| 524 | if (chip->fixes && chip->fixes->suspend) { | 526 | if (chip->fixes && chip->fixes->suspend) { |
| @@ -531,9 +533,15 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | |||
| 531 | } | 533 | } |
| 532 | 534 | ||
| 533 | pci_save_state(pdev); | 535 | pci_save_state(pdev); |
| 534 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | 536 | if (pm_flags & MMC_PM_KEEP_POWER) { |
| 535 | pci_disable_device(pdev); | 537 | if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) |
| 536 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 538 | pci_enable_wake(pdev, PCI_D3hot, 1); |
| 539 | pci_set_power_state(pdev, PCI_D3hot); | ||
| 540 | } else { | ||
| 541 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
| 542 | pci_disable_device(pdev); | ||
| 543 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
| 544 | } | ||
| 537 | 545 | ||
| 538 | return 0; | 546 | return 0; |
| 539 | } | 547 | } |
| @@ -653,6 +661,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
| 653 | goto unmap; | 661 | goto unmap; |
| 654 | } | 662 | } |
| 655 | 663 | ||
| 664 | host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; | ||
| 665 | |||
| 656 | ret = sdhci_add_host(host); | 666 | ret = sdhci_add_host(host); |
| 657 | if (ret) | 667 | if (ret) |
| 658 | goto remove; | 668 | goto remove; |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c279fbc4c2e5..d6ab62d539fb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -174,20 +174,31 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
| 174 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); | 174 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static void sdhci_init(struct sdhci_host *host) | 177 | static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); |
| 178 | |||
| 179 | static void sdhci_init(struct sdhci_host *host, int soft) | ||
| 178 | { | 180 | { |
| 179 | sdhci_reset(host, SDHCI_RESET_ALL); | 181 | if (soft) |
| 182 | sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); | ||
| 183 | else | ||
| 184 | sdhci_reset(host, SDHCI_RESET_ALL); | ||
| 180 | 185 | ||
| 181 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, | 186 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, |
| 182 | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | | 187 | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | |
| 183 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | | 188 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | |
| 184 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | | 189 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | |
| 185 | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); | 190 | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); |
| 191 | |||
| 192 | if (soft) { | ||
| 193 | /* force clock reconfiguration */ | ||
| 194 | host->clock = 0; | ||
| 195 | sdhci_set_ios(host->mmc, &host->mmc->ios); | ||
| 196 | } | ||
| 186 | } | 197 | } |
| 187 | 198 | ||
| 188 | static void sdhci_reinit(struct sdhci_host *host) | 199 | static void sdhci_reinit(struct sdhci_host *host) |
| 189 | { | 200 | { |
| 190 | sdhci_init(host); | 201 | sdhci_init(host, 0); |
| 191 | sdhci_enable_card_detection(host); | 202 | sdhci_enable_card_detection(host); |
| 192 | } | 203 | } |
| 193 | 204 | ||
| @@ -376,6 +387,20 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags) | |||
| 376 | local_irq_restore(*flags); | 387 | local_irq_restore(*flags); |
| 377 | } | 388 | } |
| 378 | 389 | ||
| 390 | static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd) | ||
| 391 | { | ||
| 392 | __le32 *dataddr = (__le32 __force *)(desc + 4); | ||
| 393 | __le16 *cmdlen = (__le16 __force *)desc; | ||
| 394 | |||
| 395 | /* SDHCI specification says ADMA descriptors should be 4 byte | ||
| 396 | * aligned, so using 16 or 32bit operations should be safe. */ | ||
| 397 | |||
| 398 | cmdlen[0] = cpu_to_le16(cmd); | ||
| 399 | cmdlen[1] = cpu_to_le16(len); | ||
| 400 | |||
| 401 | dataddr[0] = cpu_to_le32(addr); | ||
| 402 | } | ||
| 403 | |||
| 379 | static int sdhci_adma_table_pre(struct sdhci_host *host, | 404 | static int sdhci_adma_table_pre(struct sdhci_host *host, |
| 380 | struct mmc_data *data) | 405 | struct mmc_data *data) |
| 381 | { | 406 | { |
| @@ -443,19 +468,11 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
| 443 | sdhci_kunmap_atomic(buffer, &flags); | 468 | sdhci_kunmap_atomic(buffer, &flags); |
| 444 | } | 469 | } |
| 445 | 470 | ||
| 446 | desc[7] = (align_addr >> 24) & 0xff; | 471 | /* tran, valid */ |
| 447 | desc[6] = (align_addr >> 16) & 0xff; | 472 | sdhci_set_adma_desc(desc, align_addr, offset, 0x21); |
| 448 | desc[5] = (align_addr >> 8) & 0xff; | ||
| 449 | desc[4] = (align_addr >> 0) & 0xff; | ||
| 450 | 473 | ||
| 451 | BUG_ON(offset > 65536); | 474 | BUG_ON(offset > 65536); |
| 452 | 475 | ||
| 453 | desc[3] = (offset >> 8) & 0xff; | ||
| 454 | desc[2] = (offset >> 0) & 0xff; | ||
| 455 | |||
| 456 | desc[1] = 0x00; | ||
| 457 | desc[0] = 0x21; /* tran, valid */ | ||
| 458 | |||
| 459 | align += 4; | 476 | align += 4; |
| 460 | align_addr += 4; | 477 | align_addr += 4; |
| 461 | 478 | ||
| @@ -465,19 +482,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
| 465 | len -= offset; | 482 | len -= offset; |
| 466 | } | 483 | } |
| 467 | 484 | ||
| 468 | desc[7] = (addr >> 24) & 0xff; | ||
| 469 | desc[6] = (addr >> 16) & 0xff; | ||
| 470 | desc[5] = (addr >> 8) & 0xff; | ||
| 471 | desc[4] = (addr >> 0) & 0xff; | ||
| 472 | |||
| 473 | BUG_ON(len > 65536); | 485 | BUG_ON(len > 65536); |
| 474 | 486 | ||
| 475 | desc[3] = (len >> 8) & 0xff; | 487 | /* tran, valid */ |
| 476 | desc[2] = (len >> 0) & 0xff; | 488 | sdhci_set_adma_desc(desc, addr, len, 0x21); |
| 477 | |||
| 478 | desc[1] = 0x00; | ||
| 479 | desc[0] = 0x21; /* tran, valid */ | ||
| 480 | |||
| 481 | desc += 8; | 489 | desc += 8; |
| 482 | 490 | ||
| 483 | /* | 491 | /* |
| @@ -490,16 +498,9 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
| 490 | /* | 498 | /* |
| 491 | * Add a terminating entry. | 499 | * Add a terminating entry. |
| 492 | */ | 500 | */ |
| 493 | desc[7] = 0; | ||
| 494 | desc[6] = 0; | ||
| 495 | desc[5] = 0; | ||
| 496 | desc[4] = 0; | ||
| 497 | 501 | ||
| 498 | desc[3] = 0; | 502 | /* nop, end, valid */ |
| 499 | desc[2] = 0; | 503 | sdhci_set_adma_desc(desc, 0, 0, 0x3); |
| 500 | |||
| 501 | desc[1] = 0x00; | ||
| 502 | desc[0] = 0x03; /* nop, end, valid */ | ||
| 503 | 504 | ||
| 504 | /* | 505 | /* |
| 505 | * Resync align buffer as we might have changed it. | 506 | * Resync align buffer as we might have changed it. |
| @@ -1610,16 +1611,13 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
| 1610 | if (ret) | 1611 | if (ret) |
| 1611 | return ret; | 1612 | return ret; |
| 1612 | 1613 | ||
| 1613 | sdhci_init(host); | 1614 | sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); |
| 1614 | mmiowb(); | 1615 | mmiowb(); |
| 1615 | 1616 | ||
| 1616 | ret = mmc_resume_host(host->mmc); | 1617 | ret = mmc_resume_host(host->mmc); |
| 1617 | if (ret) | ||
| 1618 | return ret; | ||
| 1619 | |||
| 1620 | sdhci_enable_card_detection(host); | 1618 | sdhci_enable_card_detection(host); |
| 1621 | 1619 | ||
| 1622 | return 0; | 1620 | return ret; |
| 1623 | } | 1621 | } |
| 1624 | 1622 | ||
| 1625 | EXPORT_SYMBOL_GPL(sdhci_resume_host); | 1623 | EXPORT_SYMBOL_GPL(sdhci_resume_host); |
| @@ -1874,7 +1872,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 1874 | if (ret) | 1872 | if (ret) |
| 1875 | goto untasklet; | 1873 | goto untasklet; |
| 1876 | 1874 | ||
| 1877 | sdhci_init(host); | 1875 | sdhci_init(host, 0); |
| 1878 | 1876 | ||
| 1879 | #ifdef CONFIG_MMC_DEBUG | 1877 | #ifdef CONFIG_MMC_DEBUG |
| 1880 | sdhci_dumpregs(host); | 1878 | sdhci_dumpregs(host); |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 14cec04c34f9..bc45ef9af17d 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| 38 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
| 39 | #include <linux/stringify.h> | 39 | #include <linux/stringify.h> |
| 40 | #include <linux/namei.h> | ||
| 40 | #include <linux/stat.h> | 41 | #include <linux/stat.h> |
| 41 | #include <linux/miscdevice.h> | 42 | #include <linux/miscdevice.h> |
| 42 | #include <linux/log2.h> | 43 | #include <linux/log2.h> |
| @@ -50,7 +51,8 @@ | |||
| 50 | 51 | ||
| 51 | /** | 52 | /** |
| 52 | * struct mtd_dev_param - MTD device parameter description data structure. | 53 | * struct mtd_dev_param - MTD device parameter description data structure. |
| 53 | * @name: MTD device name or number string | 54 | * @name: MTD character device node path, MTD device name, or MTD device number |
| 55 | * string | ||
| 54 | * @vid_hdr_offs: VID header offset | 56 | * @vid_hdr_offs: VID header offset |
| 55 | */ | 57 | */ |
| 56 | struct mtd_dev_param { | 58 | struct mtd_dev_param { |
| @@ -59,10 +61,10 @@ struct mtd_dev_param { | |||
| 59 | }; | 61 | }; |
| 60 | 62 | ||
| 61 | /* Numbers of elements set in the @mtd_dev_param array */ | 63 | /* Numbers of elements set in the @mtd_dev_param array */ |
| 62 | static int mtd_devs; | 64 | static int __initdata mtd_devs; |
| 63 | 65 | ||
| 64 | /* MTD devices specification parameters */ | 66 | /* MTD devices specification parameters */ |
| 65 | static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; | 67 | static struct mtd_dev_param __initdata mtd_dev_param[UBI_MAX_DEVICES]; |
| 66 | 68 | ||
| 67 | /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ | 69 | /* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ |
| 68 | struct class *ubi_class; | 70 | struct class *ubi_class; |
| @@ -363,11 +365,13 @@ static void dev_release(struct device *dev) | |||
| 363 | /** | 365 | /** |
| 364 | * ubi_sysfs_init - initialize sysfs for an UBI device. | 366 | * ubi_sysfs_init - initialize sysfs for an UBI device. |
| 365 | * @ubi: UBI device description object | 367 | * @ubi: UBI device description object |
| 368 | * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was | ||
| 369 | * taken | ||
| 366 | * | 370 | * |
| 367 | * This function returns zero in case of success and a negative error code in | 371 | * This function returns zero in case of success and a negative error code in |
| 368 | * case of failure. | 372 | * case of failure. |
| 369 | */ | 373 | */ |
| 370 | static int ubi_sysfs_init(struct ubi_device *ubi) | 374 | static int ubi_sysfs_init(struct ubi_device *ubi, int *ref) |
| 371 | { | 375 | { |
| 372 | int err; | 376 | int err; |
| 373 | 377 | ||
| @@ -379,6 +383,7 @@ static int ubi_sysfs_init(struct ubi_device *ubi) | |||
| 379 | if (err) | 383 | if (err) |
| 380 | return err; | 384 | return err; |
| 381 | 385 | ||
| 386 | *ref = 1; | ||
| 382 | err = device_create_file(&ubi->dev, &dev_eraseblock_size); | 387 | err = device_create_file(&ubi->dev, &dev_eraseblock_size); |
| 383 | if (err) | 388 | if (err) |
| 384 | return err; | 389 | return err; |
| @@ -434,7 +439,7 @@ static void ubi_sysfs_close(struct ubi_device *ubi) | |||
| 434 | } | 439 | } |
| 435 | 440 | ||
| 436 | /** | 441 | /** |
| 437 | * kill_volumes - destroy all volumes. | 442 | * kill_volumes - destroy all user volumes. |
| 438 | * @ubi: UBI device description object | 443 | * @ubi: UBI device description object |
| 439 | */ | 444 | */ |
| 440 | static void kill_volumes(struct ubi_device *ubi) | 445 | static void kill_volumes(struct ubi_device *ubi) |
| @@ -447,36 +452,29 @@ static void kill_volumes(struct ubi_device *ubi) | |||
| 447 | } | 452 | } |
| 448 | 453 | ||
| 449 | /** | 454 | /** |
| 450 | * free_user_volumes - free all user volumes. | ||
| 451 | * @ubi: UBI device description object | ||
| 452 | * | ||
| 453 | * Normally the volumes are freed at the release function of the volume device | ||
| 454 | * objects. However, on error paths the volumes have to be freed before the | ||
| 455 | * device objects have been initialized. | ||
| 456 | */ | ||
| 457 | static void free_user_volumes(struct ubi_device *ubi) | ||
| 458 | { | ||
| 459 | int i; | ||
| 460 | |||
| 461 | for (i = 0; i < ubi->vtbl_slots; i++) | ||
| 462 | if (ubi->volumes[i]) { | ||
| 463 | kfree(ubi->volumes[i]->eba_tbl); | ||
| 464 | kfree(ubi->volumes[i]); | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | /** | ||
| 469 | * uif_init - initialize user interfaces for an UBI device. | 455 | * uif_init - initialize user interfaces for an UBI device. |
| 470 | * @ubi: UBI device description object | 456 | * @ubi: UBI device description object |
| 457 | * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was | ||
| 458 | * taken, otherwise set to %0 | ||
| 459 | * | ||
| 460 | * This function initializes various user interfaces for an UBI device. If the | ||
| 461 | * initialization fails at an early stage, this function frees all the | ||
| 462 | * resources it allocated, returns an error, and @ref is set to %0. However, | ||
| 463 | * if the initialization fails after the UBI device was registered in the | ||
| 464 | * driver core subsystem, this function takes a reference to @ubi->dev, because | ||
| 465 | * otherwise the release function ('dev_release()') would free whole @ubi | ||
| 466 | * object. The @ref argument is set to %1 in this case. The caller has to put | ||
| 467 | * this reference. | ||
| 471 | * | 468 | * |
| 472 | * This function returns zero in case of success and a negative error code in | 469 | * This function returns zero in case of success and a negative error code in |
| 473 | * case of failure. Note, this function destroys all volumes if it fails. | 470 | * case of failure. |
| 474 | */ | 471 | */ |
| 475 | static int uif_init(struct ubi_device *ubi) | 472 | static int uif_init(struct ubi_device *ubi, int *ref) |
| 476 | { | 473 | { |
| 477 | int i, err; | 474 | int i, err; |
| 478 | dev_t dev; | 475 | dev_t dev; |
| 479 | 476 | ||
| 477 | *ref = 0; | ||
| 480 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); | 478 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); |
| 481 | 479 | ||
| 482 | /* | 480 | /* |
| @@ -504,7 +502,7 @@ static int uif_init(struct ubi_device *ubi) | |||
| 504 | goto out_unreg; | 502 | goto out_unreg; |
| 505 | } | 503 | } |
| 506 | 504 | ||
| 507 | err = ubi_sysfs_init(ubi); | 505 | err = ubi_sysfs_init(ubi, ref); |
| 508 | if (err) | 506 | if (err) |
| 509 | goto out_sysfs; | 507 | goto out_sysfs; |
| 510 | 508 | ||
| @@ -522,6 +520,8 @@ static int uif_init(struct ubi_device *ubi) | |||
| 522 | out_volumes: | 520 | out_volumes: |
| 523 | kill_volumes(ubi); | 521 | kill_volumes(ubi); |
| 524 | out_sysfs: | 522 | out_sysfs: |
| 523 | if (*ref) | ||
| 524 | get_device(&ubi->dev); | ||
| 525 | ubi_sysfs_close(ubi); | 525 | ubi_sysfs_close(ubi); |
| 526 | cdev_del(&ubi->cdev); | 526 | cdev_del(&ubi->cdev); |
| 527 | out_unreg: | 527 | out_unreg: |
| @@ -875,7 +875,7 @@ static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state, | |||
| 875 | int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | 875 | int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) |
| 876 | { | 876 | { |
| 877 | struct ubi_device *ubi; | 877 | struct ubi_device *ubi; |
| 878 | int i, err, do_free = 1; | 878 | int i, err, ref = 0; |
| 879 | 879 | ||
| 880 | /* | 880 | /* |
| 881 | * Check if we already have the same MTD device attached. | 881 | * Check if we already have the same MTD device attached. |
| @@ -975,9 +975,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 975 | goto out_detach; | 975 | goto out_detach; |
| 976 | } | 976 | } |
| 977 | 977 | ||
| 978 | err = uif_init(ubi); | 978 | err = uif_init(ubi, &ref); |
| 979 | if (err) | 979 | if (err) |
| 980 | goto out_nofree; | 980 | goto out_detach; |
| 981 | 981 | ||
| 982 | ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); | 982 | ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); |
| 983 | if (IS_ERR(ubi->bgt_thread)) { | 983 | if (IS_ERR(ubi->bgt_thread)) { |
| @@ -1025,12 +1025,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 1025 | 1025 | ||
| 1026 | out_uif: | 1026 | out_uif: |
| 1027 | uif_close(ubi); | 1027 | uif_close(ubi); |
| 1028 | out_nofree: | ||
| 1029 | do_free = 0; | ||
| 1030 | out_detach: | 1028 | out_detach: |
| 1031 | ubi_wl_close(ubi); | 1029 | ubi_wl_close(ubi); |
| 1032 | if (do_free) | ||
| 1033 | free_user_volumes(ubi); | ||
| 1034 | free_internal_volumes(ubi); | 1030 | free_internal_volumes(ubi); |
| 1035 | vfree(ubi->vtbl); | 1031 | vfree(ubi->vtbl); |
| 1036 | out_free: | 1032 | out_free: |
| @@ -1039,7 +1035,10 @@ out_free: | |||
| 1039 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 1035 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| 1040 | vfree(ubi->dbg_peb_buf); | 1036 | vfree(ubi->dbg_peb_buf); |
| 1041 | #endif | 1037 | #endif |
| 1042 | kfree(ubi); | 1038 | if (ref) |
| 1039 | put_device(&ubi->dev); | ||
| 1040 | else | ||
| 1041 | kfree(ubi); | ||
| 1043 | return err; | 1042 | return err; |
| 1044 | } | 1043 | } |
| 1045 | 1044 | ||
| @@ -1096,7 +1095,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
| 1096 | 1095 | ||
| 1097 | /* | 1096 | /* |
| 1098 | * Get a reference to the device in order to prevent 'dev_release()' | 1097 | * Get a reference to the device in order to prevent 'dev_release()' |
| 1099 | * from freeing @ubi object. | 1098 | * from freeing the @ubi object. |
| 1100 | */ | 1099 | */ |
| 1101 | get_device(&ubi->dev); | 1100 | get_device(&ubi->dev); |
| 1102 | 1101 | ||
| @@ -1116,13 +1115,50 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
| 1116 | } | 1115 | } |
| 1117 | 1116 | ||
| 1118 | /** | 1117 | /** |
| 1119 | * find_mtd_device - open an MTD device by its name or number. | 1118 | * open_mtd_by_chdev - open an MTD device by its character device node path. |
| 1120 | * @mtd_dev: name or number of the device | 1119 | * @mtd_dev: MTD character device node path |
| 1120 | * | ||
| 1121 | * This helper function opens an MTD device by its character node device path. | ||
| 1122 | * Returns MTD device description object in case of success and a negative | ||
| 1123 | * error code in case of failure. | ||
| 1124 | */ | ||
| 1125 | static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev) | ||
| 1126 | { | ||
| 1127 | int err, major, minor, mode; | ||
| 1128 | struct path path; | ||
| 1129 | |||
| 1130 | /* Probably this is an MTD character device node path */ | ||
| 1131 | err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path); | ||
| 1132 | if (err) | ||
| 1133 | return ERR_PTR(err); | ||
| 1134 | |||
| 1135 | /* MTD device number is defined by the major / minor numbers */ | ||
| 1136 | major = imajor(path.dentry->d_inode); | ||
| 1137 | minor = iminor(path.dentry->d_inode); | ||
| 1138 | mode = path.dentry->d_inode->i_mode; | ||
| 1139 | path_put(&path); | ||
| 1140 | if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode)) | ||
| 1141 | return ERR_PTR(-EINVAL); | ||
| 1142 | |||
| 1143 | if (minor & 1) | ||
| 1144 | /* | ||
| 1145 | * Just do not think the "/dev/mtdrX" devices support is need, | ||
| 1146 | * so do not support them to avoid doing extra work. | ||
| 1147 | */ | ||
| 1148 | return ERR_PTR(-EINVAL); | ||
| 1149 | |||
| 1150 | return get_mtd_device(NULL, minor / 2); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | /** | ||
| 1154 | * open_mtd_device - open MTD device by name, character device path, or number. | ||
| 1155 | * @mtd_dev: name, character device node path, or MTD device device number | ||
| 1121 | * | 1156 | * |
| 1122 | * This function tries to open and MTD device described by @mtd_dev string, | 1157 | * This function tries to open and MTD device described by @mtd_dev string, |
| 1123 | * which is first treated as an ASCII number, and if it is not true, it is | 1158 | * which is first treated as ASCII MTD device number, and if it is not true, it |
| 1124 | * treated as MTD device name. Returns MTD device description object in case of | 1159 | * is treated as MTD device name, and if that is also not true, it is treated |
| 1125 | * success and a negative error code in case of failure. | 1160 | * as MTD character device node path. Returns MTD device description object in |
| 1161 | * case of success and a negative error code in case of failure. | ||
| 1126 | */ | 1162 | */ |
| 1127 | static struct mtd_info * __init open_mtd_device(const char *mtd_dev) | 1163 | static struct mtd_info * __init open_mtd_device(const char *mtd_dev) |
| 1128 | { | 1164 | { |
| @@ -1137,6 +1173,9 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev) | |||
| 1137 | * MTD device name. | 1173 | * MTD device name. |
| 1138 | */ | 1174 | */ |
| 1139 | mtd = get_mtd_device_nm(mtd_dev); | 1175 | mtd = get_mtd_device_nm(mtd_dev); |
| 1176 | if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV) | ||
| 1177 | /* Probably this is an MTD character device node path */ | ||
| 1178 | mtd = open_mtd_by_chdev(mtd_dev); | ||
| 1140 | } else | 1179 | } else |
| 1141 | mtd = get_mtd_device(NULL, mtd_num); | 1180 | mtd = get_mtd_device(NULL, mtd_num); |
| 1142 | 1181 | ||
| @@ -1352,13 +1391,15 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp) | |||
| 1352 | 1391 | ||
| 1353 | module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000); | 1392 | module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000); |
| 1354 | MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: " | 1393 | MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: " |
| 1355 | "mtd=<name|num>[,<vid_hdr_offs>].\n" | 1394 | "mtd=<name|num|path>[,<vid_hdr_offs>].\n" |
| 1356 | "Multiple \"mtd\" parameters may be specified.\n" | 1395 | "Multiple \"mtd\" parameters may be specified.\n" |
| 1357 | "MTD devices may be specified by their number or name.\n" | 1396 | "MTD devices may be specified by their number, name, or " |
| 1397 | "path to the MTD character device node.\n" | ||
| 1358 | "Optional \"vid_hdr_offs\" parameter specifies UBI VID " | 1398 | "Optional \"vid_hdr_offs\" parameter specifies UBI VID " |
| 1359 | "header position and data starting position to be used " | 1399 | "header position to be used by UBI.\n" |
| 1360 | "by UBI.\n" | 1400 | "Example 1: mtd=/dev/mtd0 - attach MTD device " |
| 1361 | "Example: mtd=content,1984 mtd=4 - attach MTD device" | 1401 | "/dev/mtd0.\n" |
| 1402 | "Example 2: mtd=content,1984 mtd=4 - attach MTD device " | ||
| 1362 | "with name \"content\" using VID header offset 1984, and " | 1403 | "with name \"content\" using VID header offset 1984, and " |
| 1363 | "MTD device number 4 with default VID header offset."); | 1404 | "MTD device number 4 with default VID header offset."); |
| 1364 | 1405 | ||
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index f30bcb372c05..17a107129726 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
| @@ -96,8 +96,11 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); | |||
| 96 | 96 | ||
| 97 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 97 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| 98 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); | 98 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); |
| 99 | int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, | ||
| 100 | int offset, int len); | ||
| 99 | #else | 101 | #else |
| 100 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | 102 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 |
| 103 | #define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 | ||
| 101 | #endif | 104 | #endif |
| 102 | 105 | ||
| 103 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | 106 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT |
| @@ -176,6 +179,7 @@ static inline int ubi_dbg_is_erase_failure(void) | |||
| 176 | #define ubi_dbg_is_write_failure() 0 | 179 | #define ubi_dbg_is_write_failure() 0 |
| 177 | #define ubi_dbg_is_erase_failure() 0 | 180 | #define ubi_dbg_is_erase_failure() 0 |
| 178 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | 181 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 |
| 182 | #define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 | ||
| 179 | 183 | ||
| 180 | #endif /* !CONFIG_MTD_UBI_DEBUG */ | 184 | #endif /* !CONFIG_MTD_UBI_DEBUG */ |
| 181 | #endif /* !__UBI_DEBUG_H__ */ | 185 | #endif /* !__UBI_DEBUG_H__ */ |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 8aa51e7a6a7d..b4ecc84c7549 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
| @@ -143,7 +143,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, | |||
| 143 | 143 | ||
| 144 | err = paranoid_check_not_bad(ubi, pnum); | 144 | err = paranoid_check_not_bad(ubi, pnum); |
| 145 | if (err) | 145 | if (err) |
| 146 | return err > 0 ? -EINVAL : err; | 146 | return err; |
| 147 | 147 | ||
| 148 | addr = (loff_t)pnum * ubi->peb_size + offset; | 148 | addr = (loff_t)pnum * ubi->peb_size + offset; |
| 149 | retry: | 149 | retry: |
| @@ -236,12 +236,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
| 236 | 236 | ||
| 237 | err = paranoid_check_not_bad(ubi, pnum); | 237 | err = paranoid_check_not_bad(ubi, pnum); |
| 238 | if (err) | 238 | if (err) |
| 239 | return err > 0 ? -EINVAL : err; | 239 | return err; |
| 240 | 240 | ||
| 241 | /* The area we are writing to has to contain all 0xFF bytes */ | 241 | /* The area we are writing to has to contain all 0xFF bytes */ |
| 242 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); | 242 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); |
| 243 | if (err) | 243 | if (err) |
| 244 | return err > 0 ? -EINVAL : err; | 244 | return err; |
| 245 | 245 | ||
| 246 | if (offset >= ubi->leb_start) { | 246 | if (offset >= ubi->leb_start) { |
| 247 | /* | 247 | /* |
| @@ -250,10 +250,10 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
| 250 | */ | 250 | */ |
| 251 | err = paranoid_check_peb_ec_hdr(ubi, pnum); | 251 | err = paranoid_check_peb_ec_hdr(ubi, pnum); |
| 252 | if (err) | 252 | if (err) |
| 253 | return err > 0 ? -EINVAL : err; | 253 | return err; |
| 254 | err = paranoid_check_peb_vid_hdr(ubi, pnum); | 254 | err = paranoid_check_peb_vid_hdr(ubi, pnum); |
| 255 | if (err) | 255 | if (err) |
| 256 | return err > 0 ? -EINVAL : err; | 256 | return err; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | if (ubi_dbg_is_write_failure()) { | 259 | if (ubi_dbg_is_write_failure()) { |
| @@ -273,6 +273,21 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
| 273 | } else | 273 | } else |
| 274 | ubi_assert(written == len); | 274 | ubi_assert(written == len); |
| 275 | 275 | ||
| 276 | if (!err) { | ||
| 277 | err = ubi_dbg_check_write(ubi, buf, pnum, offset, len); | ||
| 278 | if (err) | ||
| 279 | return err; | ||
| 280 | |||
| 281 | /* | ||
| 282 | * Since we always write sequentially, the rest of the PEB has | ||
| 283 | * to contain only 0xFF bytes. | ||
| 284 | */ | ||
| 285 | offset += len; | ||
| 286 | len = ubi->peb_size - offset; | ||
| 287 | if (len) | ||
| 288 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); | ||
| 289 | } | ||
| 290 | |||
| 276 | return err; | 291 | return err; |
| 277 | } | 292 | } |
| 278 | 293 | ||
| @@ -348,7 +363,7 @@ retry: | |||
| 348 | 363 | ||
| 349 | err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); | 364 | err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); |
| 350 | if (err) | 365 | if (err) |
| 351 | return err > 0 ? -EINVAL : err; | 366 | return err; |
| 352 | 367 | ||
| 353 | if (ubi_dbg_is_erase_failure() && !err) { | 368 | if (ubi_dbg_is_erase_failure() && !err) { |
| 354 | dbg_err("cannot erase PEB %d (emulated)", pnum); | 369 | dbg_err("cannot erase PEB %d (emulated)", pnum); |
| @@ -542,7 +557,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) | |||
| 542 | 557 | ||
| 543 | err = paranoid_check_not_bad(ubi, pnum); | 558 | err = paranoid_check_not_bad(ubi, pnum); |
| 544 | if (err != 0) | 559 | if (err != 0) |
| 545 | return err > 0 ? -EINVAL : err; | 560 | return err; |
| 546 | 561 | ||
| 547 | if (ubi->ro_mode) { | 562 | if (ubi->ro_mode) { |
| 548 | ubi_err("read-only mode"); | 563 | ubi_err("read-only mode"); |
| @@ -819,7 +834,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, | |||
| 819 | 834 | ||
| 820 | err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr); | 835 | err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr); |
| 821 | if (err) | 836 | if (err) |
| 822 | return -EINVAL; | 837 | return err; |
| 823 | 838 | ||
| 824 | err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); | 839 | err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); |
| 825 | return err; | 840 | return err; |
| @@ -1083,7 +1098,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, | |||
| 1083 | 1098 | ||
| 1084 | err = paranoid_check_peb_ec_hdr(ubi, pnum); | 1099 | err = paranoid_check_peb_ec_hdr(ubi, pnum); |
| 1085 | if (err) | 1100 | if (err) |
| 1086 | return err > 0 ? -EINVAL : err; | 1101 | return err; |
| 1087 | 1102 | ||
| 1088 | vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); | 1103 | vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); |
| 1089 | vid_hdr->version = UBI_VERSION; | 1104 | vid_hdr->version = UBI_VERSION; |
| @@ -1092,7 +1107,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, | |||
| 1092 | 1107 | ||
| 1093 | err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); | 1108 | err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); |
| 1094 | if (err) | 1109 | if (err) |
| 1095 | return -EINVAL; | 1110 | return err; |
| 1096 | 1111 | ||
| 1097 | p = (char *)vid_hdr - ubi->vid_hdr_shift; | 1112 | p = (char *)vid_hdr - ubi->vid_hdr_shift; |
| 1098 | err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, | 1113 | err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, |
| @@ -1107,8 +1122,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, | |||
| 1107 | * @ubi: UBI device description object | 1122 | * @ubi: UBI device description object |
| 1108 | * @pnum: physical eraseblock number to check | 1123 | * @pnum: physical eraseblock number to check |
| 1109 | * | 1124 | * |
| 1110 | * This function returns zero if the physical eraseblock is good, a positive | 1125 | * This function returns zero if the physical eraseblock is good, %-EINVAL if |
| 1111 | * number if it is bad and a negative error code if an error occurred. | 1126 | * it is bad and a negative error code if an error occurred. |
| 1112 | */ | 1127 | */ |
| 1113 | static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) | 1128 | static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) |
| 1114 | { | 1129 | { |
| @@ -1120,7 +1135,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) | |||
| 1120 | 1135 | ||
| 1121 | ubi_err("paranoid check failed for PEB %d", pnum); | 1136 | ubi_err("paranoid check failed for PEB %d", pnum); |
| 1122 | ubi_dbg_dump_stack(); | 1137 | ubi_dbg_dump_stack(); |
| 1123 | return err; | 1138 | return err > 0 ? -EINVAL : err; |
| 1124 | } | 1139 | } |
| 1125 | 1140 | ||
| 1126 | /** | 1141 | /** |
| @@ -1130,7 +1145,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) | |||
| 1130 | * @ec_hdr: the erase counter header to check | 1145 | * @ec_hdr: the erase counter header to check |
| 1131 | * | 1146 | * |
| 1132 | * This function returns zero if the erase counter header contains valid | 1147 | * This function returns zero if the erase counter header contains valid |
| 1133 | * values, and %1 if not. | 1148 | * values, and %-EINVAL if not. |
| 1134 | */ | 1149 | */ |
| 1135 | static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, | 1150 | static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, |
| 1136 | const struct ubi_ec_hdr *ec_hdr) | 1151 | const struct ubi_ec_hdr *ec_hdr) |
| @@ -1156,7 +1171,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
| 1156 | fail: | 1171 | fail: |
| 1157 | ubi_dbg_dump_ec_hdr(ec_hdr); | 1172 | ubi_dbg_dump_ec_hdr(ec_hdr); |
| 1158 | ubi_dbg_dump_stack(); | 1173 | ubi_dbg_dump_stack(); |
| 1159 | return 1; | 1174 | return -EINVAL; |
| 1160 | } | 1175 | } |
| 1161 | 1176 | ||
| 1162 | /** | 1177 | /** |
| @@ -1164,8 +1179,8 @@ fail: | |||
| 1164 | * @ubi: UBI device description object | 1179 | * @ubi: UBI device description object |
| 1165 | * @pnum: the physical eraseblock number to check | 1180 | * @pnum: the physical eraseblock number to check |
| 1166 | * | 1181 | * |
| 1167 | * This function returns zero if the erase counter header is all right, %1 if | 1182 | * This function returns zero if the erase counter header is all right and and |
| 1168 | * not, and a negative error code if an error occurred. | 1183 | * a negative error code if not or if an error occurred. |
| 1169 | */ | 1184 | */ |
| 1170 | static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) | 1185 | static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) |
| 1171 | { | 1186 | { |
| @@ -1188,7 +1203,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) | |||
| 1188 | ubi_err("paranoid check failed for PEB %d", pnum); | 1203 | ubi_err("paranoid check failed for PEB %d", pnum); |
| 1189 | ubi_dbg_dump_ec_hdr(ec_hdr); | 1204 | ubi_dbg_dump_ec_hdr(ec_hdr); |
| 1190 | ubi_dbg_dump_stack(); | 1205 | ubi_dbg_dump_stack(); |
| 1191 | err = 1; | 1206 | err = -EINVAL; |
| 1192 | goto exit; | 1207 | goto exit; |
| 1193 | } | 1208 | } |
| 1194 | 1209 | ||
| @@ -1206,7 +1221,7 @@ exit: | |||
| 1206 | * @vid_hdr: the volume identifier header to check | 1221 | * @vid_hdr: the volume identifier header to check |
| 1207 | * | 1222 | * |
| 1208 | * This function returns zero if the volume identifier header is all right, and | 1223 | * This function returns zero if the volume identifier header is all right, and |
| 1209 | * %1 if not. | 1224 | * %-EINVAL if not. |
| 1210 | */ | 1225 | */ |
| 1211 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, | 1226 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, |
| 1212 | const struct ubi_vid_hdr *vid_hdr) | 1227 | const struct ubi_vid_hdr *vid_hdr) |
| @@ -1233,7 +1248,7 @@ fail: | |||
| 1233 | ubi_err("paranoid check failed for PEB %d", pnum); | 1248 | ubi_err("paranoid check failed for PEB %d", pnum); |
| 1234 | ubi_dbg_dump_vid_hdr(vid_hdr); | 1249 | ubi_dbg_dump_vid_hdr(vid_hdr); |
| 1235 | ubi_dbg_dump_stack(); | 1250 | ubi_dbg_dump_stack(); |
| 1236 | return 1; | 1251 | return -EINVAL; |
| 1237 | 1252 | ||
| 1238 | } | 1253 | } |
| 1239 | 1254 | ||
| @@ -1243,7 +1258,7 @@ fail: | |||
| 1243 | * @pnum: the physical eraseblock number to check | 1258 | * @pnum: the physical eraseblock number to check |
| 1244 | * | 1259 | * |
| 1245 | * This function returns zero if the volume identifier header is all right, | 1260 | * This function returns zero if the volume identifier header is all right, |
| 1246 | * %1 if not, and a negative error code if an error occurred. | 1261 | * and a negative error code if not or if an error occurred. |
| 1247 | */ | 1262 | */ |
| 1248 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) | 1263 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) |
| 1249 | { | 1264 | { |
| @@ -1270,7 +1285,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) | |||
| 1270 | ubi_err("paranoid check failed for PEB %d", pnum); | 1285 | ubi_err("paranoid check failed for PEB %d", pnum); |
| 1271 | ubi_dbg_dump_vid_hdr(vid_hdr); | 1286 | ubi_dbg_dump_vid_hdr(vid_hdr); |
| 1272 | ubi_dbg_dump_stack(); | 1287 | ubi_dbg_dump_stack(); |
| 1273 | err = 1; | 1288 | err = -EINVAL; |
| 1274 | goto exit; | 1289 | goto exit; |
| 1275 | } | 1290 | } |
| 1276 | 1291 | ||
| @@ -1282,6 +1297,61 @@ exit: | |||
| 1282 | } | 1297 | } |
| 1283 | 1298 | ||
| 1284 | /** | 1299 | /** |
| 1300 | * ubi_dbg_check_write - make sure write succeeded. | ||
| 1301 | * @ubi: UBI device description object | ||
| 1302 | * @buf: buffer with data which were written | ||
| 1303 | * @pnum: physical eraseblock number the data were written to | ||
| 1304 | * @offset: offset within the physical eraseblock the data were written to | ||
| 1305 | * @len: how many bytes were written | ||
| 1306 | * | ||
| 1307 | * This functions reads data which were recently written and compares it with | ||
| 1308 | * the original data buffer - the data have to match. Returns zero if the data | ||
| 1309 | * match and a negative error code if not or in case of failure. | ||
| 1310 | */ | ||
| 1311 | int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, | ||
| 1312 | int offset, int len) | ||
| 1313 | { | ||
| 1314 | int err, i; | ||
| 1315 | |||
| 1316 | mutex_lock(&ubi->dbg_buf_mutex); | ||
| 1317 | err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len); | ||
| 1318 | if (err) | ||
| 1319 | goto out_unlock; | ||
| 1320 | |||
| 1321 | for (i = 0; i < len; i++) { | ||
| 1322 | uint8_t c = ((uint8_t *)buf)[i]; | ||
| 1323 | uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i]; | ||
| 1324 | int dump_len; | ||
| 1325 | |||
| 1326 | if (c == c1) | ||
| 1327 | continue; | ||
| 1328 | |||
| 1329 | ubi_err("paranoid check failed for PEB %d:%d, len %d", | ||
| 1330 | pnum, offset, len); | ||
| 1331 | ubi_msg("data differ at position %d", i); | ||
| 1332 | dump_len = max_t(int, 128, len - i); | ||
| 1333 | ubi_msg("hex dump of the original buffer from %d to %d", | ||
| 1334 | i, i + dump_len); | ||
| 1335 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
| 1336 | buf + i, dump_len, 1); | ||
| 1337 | ubi_msg("hex dump of the read buffer from %d to %d", | ||
| 1338 | i, i + dump_len); | ||
| 1339 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
| 1340 | ubi->dbg_peb_buf + i, dump_len, 1); | ||
| 1341 | ubi_dbg_dump_stack(); | ||
| 1342 | err = -EINVAL; | ||
| 1343 | goto out_unlock; | ||
| 1344 | } | ||
| 1345 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
| 1346 | |||
| 1347 | return 0; | ||
| 1348 | |||
| 1349 | out_unlock: | ||
| 1350 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
| 1351 | return err; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | /** | ||
| 1285 | * ubi_dbg_check_all_ff - check that a region of flash is empty. | 1355 | * ubi_dbg_check_all_ff - check that a region of flash is empty. |
| 1286 | * @ubi: UBI device description object | 1356 | * @ubi: UBI device description object |
| 1287 | * @pnum: the physical eraseblock number to check | 1357 | * @pnum: the physical eraseblock number to check |
| @@ -1289,8 +1359,8 @@ exit: | |||
| 1289 | * @len: the length of the region to check | 1359 | * @len: the length of the region to check |
| 1290 | * | 1360 | * |
| 1291 | * This function returns zero if only 0xFF bytes are present at offset | 1361 | * This function returns zero if only 0xFF bytes are present at offset |
| 1292 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error | 1362 | * @offset of the physical eraseblock @pnum, and a negative error code if not |
| 1293 | * code if an error occurred. | 1363 | * or if an error occurred. |
| 1294 | */ | 1364 | */ |
| 1295 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) | 1365 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) |
| 1296 | { | 1366 | { |
| @@ -1321,7 +1391,7 @@ fail: | |||
| 1321 | ubi_msg("hex dump of the %d-%d region", offset, offset + len); | 1391 | ubi_msg("hex dump of the %d-%d region", offset, offset + len); |
| 1322 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | 1392 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, |
| 1323 | ubi->dbg_peb_buf, len, 1); | 1393 | ubi->dbg_peb_buf, len, 1); |
| 1324 | err = 1; | 1394 | err = -EINVAL; |
| 1325 | error: | 1395 | error: |
| 1326 | ubi_dbg_dump_stack(); | 1396 | ubi_dbg_dump_stack(); |
| 1327 | mutex_unlock(&ubi->dbg_buf_mutex); | 1397 | mutex_unlock(&ubi->dbg_buf_mutex); |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 90af61a2c3e4..594184bbd56a 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -974,11 +974,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
| 974 | seb->ec = si->mean_ec; | 974 | seb->ec = si->mean_ec; |
| 975 | 975 | ||
| 976 | err = paranoid_check_si(ubi, si); | 976 | err = paranoid_check_si(ubi, si); |
| 977 | if (err) { | 977 | if (err) |
| 978 | if (err > 0) | ||
| 979 | err = -EINVAL; | ||
| 980 | goto out_vidh; | 978 | goto out_vidh; |
| 981 | } | ||
| 982 | 979 | ||
| 983 | ubi_free_vid_hdr(ubi, vidh); | 980 | ubi_free_vid_hdr(ubi, vidh); |
| 984 | kfree(ech); | 981 | kfree(ech); |
| @@ -1086,8 +1083,8 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) | |||
| 1086 | * @ubi: UBI device description object | 1083 | * @ubi: UBI device description object |
| 1087 | * @si: scanning information | 1084 | * @si: scanning information |
| 1088 | * | 1085 | * |
| 1089 | * This function returns zero if the scanning information is all right, %1 if | 1086 | * This function returns zero if the scanning information is all right, and a |
| 1090 | * not and a negative error code if an error occurred. | 1087 | * negative error code if not or if an error occurred. |
| 1091 | */ | 1088 | */ |
| 1092 | static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) | 1089 | static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) |
| 1093 | { | 1090 | { |
| @@ -1346,7 +1343,7 @@ bad_vid_hdr: | |||
| 1346 | 1343 | ||
| 1347 | out: | 1344 | out: |
| 1348 | ubi_dbg_dump_stack(); | 1345 | ubi_dbg_dump_stack(); |
| 1349 | return 1; | 1346 | return -EINVAL; |
| 1350 | } | 1347 | } |
| 1351 | 1348 | ||
| 1352 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ | 1349 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 600c7229d5cf..f64ddabd4ac8 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
| @@ -464,7 +464,7 @@ retry: | |||
| 464 | ubi->peb_size - ubi->vid_hdr_aloffset); | 464 | ubi->peb_size - ubi->vid_hdr_aloffset); |
| 465 | if (err) { | 465 | if (err) { |
| 466 | ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); | 466 | ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); |
| 467 | return err > 0 ? -EINVAL : err; | 467 | return err; |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | return e->pnum; | 470 | return e->pnum; |
| @@ -513,7 +513,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, | |||
| 513 | dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec); | 513 | dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec); |
| 514 | 514 | ||
| 515 | err = paranoid_check_ec(ubi, e->pnum, e->ec); | 515 | err = paranoid_check_ec(ubi, e->pnum, e->ec); |
| 516 | if (err > 0) | 516 | if (err) |
| 517 | return -EINVAL; | 517 | return -EINVAL; |
| 518 | 518 | ||
| 519 | ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); | 519 | ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); |
| @@ -1572,8 +1572,7 @@ void ubi_wl_close(struct ubi_device *ubi) | |||
| 1572 | * @ec: the erase counter to check | 1572 | * @ec: the erase counter to check |
| 1573 | * | 1573 | * |
| 1574 | * This function returns zero if the erase counter of physical eraseblock @pnum | 1574 | * This function returns zero if the erase counter of physical eraseblock @pnum |
| 1575 | * is equivalent to @ec, %1 if not, and a negative error code if an error | 1575 | * is equivalent to @ec, and a negative error code if not or if an error occurred. |
| 1576 | * occurred. | ||
| 1577 | */ | 1576 | */ |
| 1578 | static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec) | 1577 | static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec) |
| 1579 | { | 1578 | { |
| @@ -1611,8 +1610,8 @@ out_free: | |||
| 1611 | * @e: the wear-leveling entry to check | 1610 | * @e: the wear-leveling entry to check |
| 1612 | * @root: the root of the tree | 1611 | * @root: the root of the tree |
| 1613 | * | 1612 | * |
| 1614 | * This function returns zero if @e is in the @root RB-tree and %1 if it is | 1613 | * This function returns zero if @e is in the @root RB-tree and %-EINVAL if it |
| 1615 | * not. | 1614 | * is not. |
| 1616 | */ | 1615 | */ |
| 1617 | static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, | 1616 | static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, |
| 1618 | struct rb_root *root) | 1617 | struct rb_root *root) |
| @@ -1623,7 +1622,7 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, | |||
| 1623 | ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ", | 1622 | ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ", |
| 1624 | e->pnum, e->ec, root); | 1623 | e->pnum, e->ec, root); |
| 1625 | ubi_dbg_dump_stack(); | 1624 | ubi_dbg_dump_stack(); |
| 1626 | return 1; | 1625 | return -EINVAL; |
| 1627 | } | 1626 | } |
| 1628 | 1627 | ||
| 1629 | /** | 1628 | /** |
| @@ -1632,7 +1631,7 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, | |||
| 1632 | * @ubi: UBI device description object | 1631 | * @ubi: UBI device description object |
| 1633 | * @e: the wear-leveling entry to check | 1632 | * @e: the wear-leveling entry to check |
| 1634 | * | 1633 | * |
| 1635 | * This function returns zero if @e is in @ubi->pq and %1 if it is not. | 1634 | * This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not. |
| 1636 | */ | 1635 | */ |
| 1637 | static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e) | 1636 | static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e) |
| 1638 | { | 1637 | { |
| @@ -1647,6 +1646,6 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e) | |||
| 1647 | ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue", | 1646 | ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue", |
| 1648 | e->pnum, e->ec); | 1647 | e->pnum, e->ec); |
| 1649 | ubi_dbg_dump_stack(); | 1648 | ubi_dbg_dump_stack(); |
| 1650 | return 1; | 1649 | return -EINVAL; |
| 1651 | } | 1650 | } |
| 1652 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ | 1651 | #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6aa526ee9096..61a7b4351e78 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -998,7 +998,7 @@ static int gfar_probe(struct of_device *ofdev, | |||
| 998 | } | 998 | } |
| 999 | 999 | ||
| 1000 | /* Need to reverse the bit maps as bit_map's MSB is q0 | 1000 | /* Need to reverse the bit maps as bit_map's MSB is q0 |
| 1001 | * but, for_each_bit parses from right to left, which | 1001 | * but, for_each_set_bit parses from right to left, which |
| 1002 | * basically reverses the queue numbers */ | 1002 | * basically reverses the queue numbers */ |
| 1003 | for (i = 0; i< priv->num_grps; i++) { | 1003 | for (i = 0; i< priv->num_grps; i++) { |
| 1004 | priv->gfargrp[i].tx_bit_map = reverse_bitmap( | 1004 | priv->gfargrp[i].tx_bit_map = reverse_bitmap( |
| @@ -1011,7 +1011,7 @@ static int gfar_probe(struct of_device *ofdev, | |||
| 1011 | * also assign queues to groups */ | 1011 | * also assign queues to groups */ |
| 1012 | for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) { | 1012 | for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) { |
| 1013 | priv->gfargrp[grp_idx].num_rx_queues = 0x0; | 1013 | priv->gfargrp[grp_idx].num_rx_queues = 0x0; |
| 1014 | for_each_bit(i, &priv->gfargrp[grp_idx].rx_bit_map, | 1014 | for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map, |
| 1015 | priv->num_rx_queues) { | 1015 | priv->num_rx_queues) { |
| 1016 | priv->gfargrp[grp_idx].num_rx_queues++; | 1016 | priv->gfargrp[grp_idx].num_rx_queues++; |
| 1017 | priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx]; | 1017 | priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx]; |
| @@ -1019,7 +1019,7 @@ static int gfar_probe(struct of_device *ofdev, | |||
| 1019 | rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i); | 1019 | rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i); |
| 1020 | } | 1020 | } |
| 1021 | priv->gfargrp[grp_idx].num_tx_queues = 0x0; | 1021 | priv->gfargrp[grp_idx].num_tx_queues = 0x0; |
| 1022 | for_each_bit (i, &priv->gfargrp[grp_idx].tx_bit_map, | 1022 | for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map, |
| 1023 | priv->num_tx_queues) { | 1023 | priv->num_tx_queues) { |
| 1024 | priv->gfargrp[grp_idx].num_tx_queues++; | 1024 | priv->gfargrp[grp_idx].num_tx_queues++; |
| 1025 | priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx]; | 1025 | priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx]; |
| @@ -1709,7 +1709,7 @@ void gfar_configure_coalescing(struct gfar_private *priv, | |||
| 1709 | 1709 | ||
| 1710 | if (priv->mode == MQ_MG_MODE) { | 1710 | if (priv->mode == MQ_MG_MODE) { |
| 1711 | baddr = ®s->txic0; | 1711 | baddr = ®s->txic0; |
| 1712 | for_each_bit (i, &tx_mask, priv->num_tx_queues) { | 1712 | for_each_set_bit(i, &tx_mask, priv->num_tx_queues) { |
| 1713 | if (likely(priv->tx_queue[i]->txcoalescing)) { | 1713 | if (likely(priv->tx_queue[i]->txcoalescing)) { |
| 1714 | gfar_write(baddr + i, 0); | 1714 | gfar_write(baddr + i, 0); |
| 1715 | gfar_write(baddr + i, priv->tx_queue[i]->txic); | 1715 | gfar_write(baddr + i, priv->tx_queue[i]->txic); |
| @@ -1717,7 +1717,7 @@ void gfar_configure_coalescing(struct gfar_private *priv, | |||
| 1717 | } | 1717 | } |
| 1718 | 1718 | ||
| 1719 | baddr = ®s->rxic0; | 1719 | baddr = ®s->rxic0; |
| 1720 | for_each_bit (i, &rx_mask, priv->num_rx_queues) { | 1720 | for_each_set_bit(i, &rx_mask, priv->num_rx_queues) { |
| 1721 | if (likely(priv->rx_queue[i]->rxcoalescing)) { | 1721 | if (likely(priv->rx_queue[i]->rxcoalescing)) { |
| 1722 | gfar_write(baddr + i, 0); | 1722 | gfar_write(baddr + i, 0); |
| 1723 | gfar_write(baddr + i, priv->rx_queue[i]->rxic); | 1723 | gfar_write(baddr + i, priv->rx_queue[i]->rxic); |
| @@ -2607,7 +2607,7 @@ static int gfar_poll(struct napi_struct *napi, int budget) | |||
| 2607 | budget_per_queue = left_over_budget/num_queues; | 2607 | budget_per_queue = left_over_budget/num_queues; |
| 2608 | left_over_budget = 0; | 2608 | left_over_budget = 0; |
| 2609 | 2609 | ||
| 2610 | for_each_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { | 2610 | for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) { |
| 2611 | if (test_bit(i, &serviced_queues)) | 2611 | if (test_bit(i, &serviced_queues)) |
| 2612 | continue; | 2612 | continue; |
| 2613 | rx_queue = priv->rx_queue[i]; | 2613 | rx_queue = priv->rx_queue[i]; |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 45e3532b166f..684af371462d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
| @@ -1050,7 +1050,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) | |||
| 1050 | */ | 1050 | */ |
| 1051 | for (v_idx = 0; v_idx < q_vectors; v_idx++) { | 1051 | for (v_idx = 0; v_idx < q_vectors; v_idx++) { |
| 1052 | q_vector = adapter->q_vector[v_idx]; | 1052 | q_vector = adapter->q_vector[v_idx]; |
| 1053 | /* XXX for_each_bit(...) */ | 1053 | /* XXX for_each_set_bit(...) */ |
| 1054 | r_idx = find_first_bit(q_vector->rxr_idx, | 1054 | r_idx = find_first_bit(q_vector->rxr_idx, |
| 1055 | adapter->num_rx_queues); | 1055 | adapter->num_rx_queues); |
| 1056 | 1056 | ||
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 235b5fd4b8d4..ca653c49b765 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c | |||
| @@ -751,7 +751,7 @@ static void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter) | |||
| 751 | */ | 751 | */ |
| 752 | for (v_idx = 0; v_idx < q_vectors; v_idx++) { | 752 | for (v_idx = 0; v_idx < q_vectors; v_idx++) { |
| 753 | q_vector = adapter->q_vector[v_idx]; | 753 | q_vector = adapter->q_vector[v_idx]; |
| 754 | /* XXX for_each_bit(...) */ | 754 | /* XXX for_each_set_bit(...) */ |
| 755 | r_idx = find_first_bit(q_vector->rxr_idx, | 755 | r_idx = find_first_bit(q_vector->rxr_idx, |
| 756 | adapter->num_rx_queues); | 756 | adapter->num_rx_queues); |
| 757 | 757 | ||
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 8a964f130367..a6452af9c6c5 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
| @@ -394,7 +394,7 @@ static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) | |||
| 394 | ieee80211_tx_status_irqsafe(ar->hw, skb); | 394 | ieee80211_tx_status_irqsafe(ar->hw, skb); |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { | 397 | for_each_set_bit(i, &queue_bitmap, BITS_PER_BYTE) { |
| 398 | #ifdef AR9170_QUEUE_STOP_DEBUG | 398 | #ifdef AR9170_QUEUE_STOP_DEBUG |
| 399 | printk(KERN_DEBUG "%s: wake queue %d\n", | 399 | printk(KERN_DEBUG "%s: wake queue %d\n", |
| 400 | wiphy_name(ar->hw->wiphy), i); | 400 | wiphy_name(ar->hw->wiphy), i); |
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index be992ca41cf1..c29c994de0e2 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c | |||
| @@ -89,7 +89,7 @@ static int iwm_debugfs_dbg_modules_write(void *data, u64 val) | |||
| 89 | for (i = 0; i < __IWM_DM_NR; i++) | 89 | for (i = 0; i < __IWM_DM_NR; i++) |
| 90 | iwm->dbg.dbg_module[i] = 0; | 90 | iwm->dbg.dbg_module[i] = 0; |
| 91 | 91 | ||
| 92 | for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR) | 92 | for_each_set_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR) |
| 93 | iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level; | 93 | iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level; |
| 94 | 94 | ||
| 95 | return 0; | 95 | return 0; |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index ad8f7eabb5aa..8456b4dbd146 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
| @@ -1116,7 +1116,7 @@ static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf, | |||
| 1116 | return -EINVAL; | 1116 | return -EINVAL; |
| 1117 | } | 1117 | } |
| 1118 | 1118 | ||
| 1119 | for_each_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) { | 1119 | for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) { |
| 1120 | tid_info = &sta_info->tid_info[bit]; | 1120 | tid_info = &sta_info->tid_info[bit]; |
| 1121 | 1121 | ||
| 1122 | mutex_lock(&tid_info->mutex); | 1122 | mutex_lock(&tid_info->mutex); |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 039e87b71442..81d19d5683ac 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
| @@ -2533,6 +2533,91 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); | |||
| 2533 | 2533 | ||
| 2534 | #endif /* CONFIG_PCI_IOV */ | 2534 | #endif /* CONFIG_PCI_IOV */ |
| 2535 | 2535 | ||
| 2536 | /* | ||
| 2537 | * This is a quirk for the Ricoh MMC controller found as a part of | ||
| 2538 | * some mulifunction chips. | ||
| 2539 | |||
| 2540 | * This is very similiar and based on the ricoh_mmc driver written by | ||
| 2541 | * Philip Langdale. Thank you for these magic sequences. | ||
| 2542 | * | ||
| 2543 | * These chips implement the four main memory card controllers (SD, MMC, MS, xD) | ||
| 2544 | * and one or both of cardbus or firewire. | ||
| 2545 | * | ||
| 2546 | * It happens that they implement SD and MMC | ||
| 2547 | * support as separate controllers (and PCI functions). The linux SDHCI | ||
| 2548 | * driver supports MMC cards but the chip detects MMC cards in hardware | ||
| 2549 | * and directs them to the MMC controller - so the SDHCI driver never sees | ||
| 2550 | * them. | ||
| 2551 | * | ||
| 2552 | * To get around this, we must disable the useless MMC controller. | ||
| 2553 | * At that point, the SDHCI controller will start seeing them | ||
| 2554 | * It seems to be the case that the relevant PCI registers to deactivate the | ||
| 2555 | * MMC controller live on PCI function 0, which might be the cardbus controller | ||
| 2556 | * or the firewire controller, depending on the particular chip in question | ||
| 2557 | * | ||
| 2558 | * This has to be done early, because as soon as we disable the MMC controller | ||
| 2559 | * other pci functions shift up one level, e.g. function #2 becomes function | ||
| 2560 | * #1, and this will confuse the pci core. | ||
| 2561 | */ | ||
| 2562 | |||
| 2563 | #ifdef CONFIG_MMC_RICOH_MMC | ||
| 2564 | static void ricoh_mmc_fixup_rl5c476(struct pci_dev *dev) | ||
| 2565 | { | ||
| 2566 | /* disable via cardbus interface */ | ||
| 2567 | u8 write_enable; | ||
| 2568 | u8 write_target; | ||
| 2569 | u8 disable; | ||
| 2570 | |||
| 2571 | /* disable must be done via function #0 */ | ||
| 2572 | if (PCI_FUNC(dev->devfn)) | ||
| 2573 | return; | ||
| 2574 | |||
| 2575 | pci_read_config_byte(dev, 0xB7, &disable); | ||
| 2576 | if (disable & 0x02) | ||
| 2577 | return; | ||
| 2578 | |||
| 2579 | pci_read_config_byte(dev, 0x8E, &write_enable); | ||
| 2580 | pci_write_config_byte(dev, 0x8E, 0xAA); | ||
| 2581 | pci_read_config_byte(dev, 0x8D, &write_target); | ||
| 2582 | pci_write_config_byte(dev, 0x8D, 0xB7); | ||
| 2583 | pci_write_config_byte(dev, 0xB7, disable | 0x02); | ||
| 2584 | pci_write_config_byte(dev, 0x8E, write_enable); | ||
| 2585 | pci_write_config_byte(dev, 0x8D, write_target); | ||
| 2586 | |||
| 2587 | dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via cardbus function)\n"); | ||
| 2588 | dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); | ||
| 2589 | } | ||
| 2590 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476); | ||
| 2591 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476); | ||
| 2592 | |||
| 2593 | static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) | ||
| 2594 | { | ||
| 2595 | /* disable via firewire interface */ | ||
| 2596 | u8 write_enable; | ||
| 2597 | u8 disable; | ||
| 2598 | |||
| 2599 | /* disable must be done via function #0 */ | ||
| 2600 | if (PCI_FUNC(dev->devfn)) | ||
| 2601 | return; | ||
| 2602 | |||
| 2603 | pci_read_config_byte(dev, 0xCB, &disable); | ||
| 2604 | |||
| 2605 | if (disable & 0x02) | ||
| 2606 | return; | ||
| 2607 | |||
| 2608 | pci_read_config_byte(dev, 0xCA, &write_enable); | ||
| 2609 | pci_write_config_byte(dev, 0xCA, 0x57); | ||
| 2610 | pci_write_config_byte(dev, 0xCB, disable | 0x02); | ||
| 2611 | pci_write_config_byte(dev, 0xCA, write_enable); | ||
| 2612 | |||
| 2613 | dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n"); | ||
| 2614 | dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n"); | ||
| 2615 | } | ||
| 2616 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); | ||
| 2617 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); | ||
| 2618 | #endif /*CONFIG_MMC_RICOH_MMC*/ | ||
| 2619 | |||
| 2620 | |||
| 2536 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | 2621 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, |
| 2537 | struct pci_fixup *end) | 2622 | struct pci_fixup *end) |
| 2538 | { | 2623 | { |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index be5a6b73e601..40845c7e9322 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
| @@ -226,6 +226,7 @@ static void __exit rtc_exit(void) | |||
| 226 | { | 226 | { |
| 227 | rtc_dev_exit(); | 227 | rtc_dev_exit(); |
| 228 | class_destroy(rtc_class); | 228 | class_destroy(rtc_class); |
| 229 | idr_destroy(&rtc_idr); | ||
| 229 | } | 230 | } |
| 230 | 231 | ||
| 231 | subsys_initcall(rtc_init); | 232 | subsys_initcall(rtc_init); |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 86c61f143515..78a018b5c941 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
| @@ -161,7 +161,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
| 161 | if (offset == 0) | 161 | if (offset == 0) |
| 162 | return -EILSEQ; | 162 | return -EILSEQ; |
| 163 | 163 | ||
| 164 | memset(alrm, 0, sizeof(alrm)); | 164 | memset(alrm, 0, sizeof(*alrm)); |
| 165 | if (alarm != ALARM_DISABLED && offset != 0) { | 165 | if (alarm != ALARM_DISABLED && offset != 0) { |
| 166 | rtc_time_to_tm(offset + alarm, tm); | 166 | rtc_time_to_tm(offset + alarm, tm); |
| 167 | 167 | ||
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 03ea530981d1..44c4399ee714 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c | |||
| @@ -271,12 +271,13 @@ static int coh901331_resume(struct platform_device *pdev) | |||
| 271 | { | 271 | { |
| 272 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); | 272 | struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); |
| 273 | 273 | ||
| 274 | if (device_may_wakeup(&pdev->dev)) | 274 | if (device_may_wakeup(&pdev->dev)) { |
| 275 | disable_irq_wake(rtap->irq); | 275 | disable_irq_wake(rtap->irq); |
| 276 | else | 276 | } else { |
| 277 | clk_enable(rtap->clk); | 277 | clk_enable(rtap->clk); |
| 278 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); | 278 | writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); |
| 279 | clk_disable(rtap->clk); | 279 | clk_disable(rtap->clk); |
| 280 | } | ||
| 280 | return 0; | 281 | return 0; |
| 281 | } | 282 | } |
| 282 | #else | 283 | #else |
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 9da02d108b73..91bde976bc0f 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c | |||
| @@ -115,6 +115,15 @@ static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev, | |||
| 115 | } | 115 | } |
| 116 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); | 116 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL); |
| 117 | 117 | ||
| 118 | static struct attribute *ep93xx_rtc_attrs[] = { | ||
| 119 | &dev_attr_comp_preload.attr, | ||
| 120 | &dev_attr_comp_delete.attr, | ||
| 121 | NULL | ||
| 122 | }; | ||
| 123 | |||
| 124 | static const struct attribute_group ep93xx_rtc_sysfs_files = { | ||
| 125 | .attrs = ep93xx_rtc_attrs, | ||
| 126 | }; | ||
| 118 | 127 | ||
| 119 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) | 128 | static int __init ep93xx_rtc_probe(struct platform_device *pdev) |
| 120 | { | 129 | { |
| @@ -123,27 +132,22 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
| 123 | struct rtc_device *rtc; | 132 | struct rtc_device *rtc; |
| 124 | int err; | 133 | int err; |
| 125 | 134 | ||
| 126 | ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL); | 135 | ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); |
| 127 | if (ep93xx_rtc == NULL) | 136 | if (!ep93xx_rtc) |
| 128 | return -ENOMEM; | 137 | return -ENOMEM; |
| 129 | 138 | ||
| 130 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 139 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 131 | if (res == NULL) { | 140 | if (!res) |
| 132 | err = -ENXIO; | 141 | return -ENXIO; |
| 133 | goto fail_free; | ||
| 134 | } | ||
| 135 | 142 | ||
| 136 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 143 | if (!devm_request_mem_region(&pdev->dev, res->start, |
| 137 | if (res == NULL) { | 144 | resource_size(res), pdev->name)) |
| 138 | err = -EBUSY; | 145 | return -EBUSY; |
| 139 | goto fail_free; | ||
| 140 | } | ||
| 141 | 146 | ||
| 142 | ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); | 147 | ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start, |
| 143 | if (ep93xx_rtc->mmio_base == NULL) { | 148 | resource_size(res)); |
| 144 | err = -ENXIO; | 149 | if (!ep93xx_rtc->mmio_base) |
| 145 | goto fail; | 150 | return -ENXIO; |
| 146 | } | ||
| 147 | 151 | ||
| 148 | pdev->dev.platform_data = ep93xx_rtc; | 152 | pdev->dev.platform_data = ep93xx_rtc; |
| 149 | 153 | ||
| @@ -151,53 +155,34 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) | |||
| 151 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); | 155 | &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); |
| 152 | if (IS_ERR(rtc)) { | 156 | if (IS_ERR(rtc)) { |
| 153 | err = PTR_ERR(rtc); | 157 | err = PTR_ERR(rtc); |
| 154 | goto fail; | 158 | goto exit; |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | platform_set_drvdata(pdev, rtc); | 161 | platform_set_drvdata(pdev, rtc); |
| 158 | 162 | ||
| 159 | err = device_create_file(&pdev->dev, &dev_attr_comp_preload); | 163 | err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); |
| 160 | if (err) | 164 | if (err) |
| 161 | goto fail; | 165 | goto fail; |
| 162 | err = device_create_file(&pdev->dev, &dev_attr_comp_delete); | ||
| 163 | if (err) { | ||
| 164 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
| 165 | goto fail; | ||
| 166 | } | ||
| 167 | 166 | ||
| 168 | return 0; | 167 | return 0; |
| 169 | 168 | ||
| 170 | fail: | 169 | fail: |
| 171 | if (ep93xx_rtc->mmio_base) { | 170 | platform_set_drvdata(pdev, NULL); |
| 172 | iounmap(ep93xx_rtc->mmio_base); | 171 | rtc_device_unregister(rtc); |
| 173 | pdev->dev.platform_data = NULL; | 172 | exit: |
| 174 | } | 173 | pdev->dev.platform_data = NULL; |
| 175 | release_mem_region(res->start, resource_size(res)); | ||
| 176 | fail_free: | ||
| 177 | kfree(ep93xx_rtc); | ||
| 178 | return err; | 174 | return err; |
| 179 | } | 175 | } |
| 180 | 176 | ||
| 181 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) | 177 | static int __exit ep93xx_rtc_remove(struct platform_device *pdev) |
| 182 | { | 178 | { |
| 183 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 179 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
| 184 | struct ep93xx_rtc *ep93xx_rtc = pdev->dev.platform_data; | ||
| 185 | struct resource *res; | ||
| 186 | |||
| 187 | /* cleanup sysfs */ | ||
| 188 | device_remove_file(&pdev->dev, &dev_attr_comp_delete); | ||
| 189 | device_remove_file(&pdev->dev, &dev_attr_comp_preload); | ||
| 190 | 180 | ||
| 181 | sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); | ||
| 182 | platform_set_drvdata(pdev, NULL); | ||
| 191 | rtc_device_unregister(rtc); | 183 | rtc_device_unregister(rtc); |
| 192 | |||
| 193 | iounmap(ep93xx_rtc->mmio_base); | ||
| 194 | pdev->dev.platform_data = NULL; | 184 | pdev->dev.platform_data = NULL; |
| 195 | 185 | ||
| 196 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 197 | release_mem_region(res->start, resource_size(res)); | ||
| 198 | |||
| 199 | platform_set_drvdata(pdev, NULL); | ||
| 200 | |||
| 201 | return 0; | 186 | return 0; |
| 202 | } | 187 | } |
| 203 | 188 | ||
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c index 850f983c039c..d60c81b7b693 100644 --- a/drivers/rtc/rtc-mc13783.c +++ b/drivers/rtc/rtc-mc13783.c | |||
| @@ -28,6 +28,34 @@ struct mc13783_rtc { | |||
| 28 | int valid; | 28 | int valid; |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | static int mc13783_rtc_irq_enable_unlocked(struct device *dev, | ||
| 32 | unsigned int enabled, int irq) | ||
| 33 | { | ||
| 34 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
| 35 | int (*func)(struct mc13783 *mc13783, int irq); | ||
| 36 | |||
| 37 | if (!priv->valid) | ||
| 38 | return -ENODATA; | ||
| 39 | |||
| 40 | func = enabled ? mc13783_irq_unmask : mc13783_irq_mask; | ||
| 41 | return func(priv->mc13783, irq); | ||
| 42 | } | ||
| 43 | |||
| 44 | static int mc13783_rtc_irq_enable(struct device *dev, | ||
| 45 | unsigned int enabled, int irq) | ||
| 46 | { | ||
| 47 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | ||
| 48 | int ret; | ||
| 49 | |||
| 50 | mc13783_lock(priv->mc13783); | ||
| 51 | |||
| 52 | ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq); | ||
| 53 | |||
| 54 | mc13783_unlock(priv->mc13783); | ||
| 55 | |||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 31 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) | 59 | static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 32 | { | 60 | { |
| 33 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 61 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| @@ -78,6 +106,7 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 78 | { | 106 | { |
| 79 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 107 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| 80 | unsigned int seconds, days; | 108 | unsigned int seconds, days; |
| 109 | unsigned int alarmseconds; | ||
| 81 | int ret; | 110 | int ret; |
| 82 | 111 | ||
| 83 | seconds = secs % 86400; | 112 | seconds = secs % 86400; |
| @@ -86,7 +115,22 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 86 | mc13783_lock(priv->mc13783); | 115 | mc13783_lock(priv->mc13783); |
| 87 | 116 | ||
| 88 | /* | 117 | /* |
| 89 | * first write seconds=0 to prevent a day switch between writing days | 118 | * temporarily invalidate alarm to prevent triggering it when the day is |
| 119 | * already updated while the time isn't yet. | ||
| 120 | */ | ||
| 121 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds); | ||
| 122 | if (unlikely(ret)) | ||
| 123 | goto out; | ||
| 124 | |||
| 125 | if (alarmseconds < 86400) { | ||
| 126 | ret = mc13783_reg_write(priv->mc13783, | ||
| 127 | MC13783_RTCTODA, 0x1ffff); | ||
| 128 | if (unlikely(ret)) | ||
| 129 | goto out; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* | ||
| 133 | * write seconds=0 to prevent a day switch between writing days | ||
| 90 | * and seconds below | 134 | * and seconds below |
| 91 | */ | 135 | */ |
| 92 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); | 136 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0); |
| @@ -101,11 +145,19 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
| 101 | if (unlikely(ret)) | 145 | if (unlikely(ret)) |
| 102 | goto out; | 146 | goto out; |
| 103 | 147 | ||
| 104 | ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST); | 148 | /* restore alarm */ |
| 149 | if (alarmseconds < 86400) { | ||
| 150 | ret = mc13783_reg_write(priv->mc13783, | ||
| 151 | MC13783_RTCTODA, alarmseconds); | ||
| 152 | if (unlikely(ret)) | ||
| 153 | goto out; | ||
| 154 | } | ||
| 155 | |||
| 156 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST); | ||
| 105 | if (unlikely(ret)) | 157 | if (unlikely(ret)) |
| 106 | goto out; | 158 | goto out; |
| 107 | 159 | ||
| 108 | ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST); | 160 | ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST); |
| 109 | out: | 161 | out: |
| 110 | priv->valid = !ret; | 162 | priv->valid = !ret; |
| 111 | 163 | ||
| @@ -114,41 +166,139 @@ out: | |||
| 114 | return ret; | 166 | return ret; |
| 115 | } | 167 | } |
| 116 | 168 | ||
| 117 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | 169 | static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 118 | { | 170 | { |
| 119 | struct mc13783_rtc *priv = dev; | 171 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| 120 | struct mc13783 *mc13783 = priv->mc13783; | 172 | unsigned seconds, days; |
| 173 | unsigned long s1970; | ||
| 174 | int enabled, pending; | ||
| 175 | int ret; | ||
| 121 | 176 | ||
| 122 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | 177 | mc13783_lock(priv->mc13783); |
| 123 | 178 | ||
| 124 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | 179 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds); |
| 180 | if (unlikely(ret)) | ||
| 181 | goto out; | ||
| 182 | if (seconds >= 86400) { | ||
| 183 | ret = -ENODATA; | ||
| 184 | goto out; | ||
| 185 | } | ||
| 186 | |||
| 187 | ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days); | ||
| 188 | if (unlikely(ret)) | ||
| 189 | goto out; | ||
| 125 | 190 | ||
| 126 | mc13783_ackirq(mc13783, irq); | 191 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA, |
| 192 | &enabled, &pending); | ||
| 127 | 193 | ||
| 128 | return IRQ_HANDLED; | 194 | out: |
| 195 | mc13783_unlock(priv->mc13783); | ||
| 196 | |||
| 197 | if (ret) | ||
| 198 | return ret; | ||
| 199 | |||
| 200 | alarm->enabled = enabled; | ||
| 201 | alarm->pending = pending; | ||
| 202 | |||
| 203 | s1970 = days * 86400 + seconds; | ||
| 204 | |||
| 205 | rtc_time_to_tm(s1970, &alarm->time); | ||
| 206 | dev_dbg(dev, "%s: %lu\n", __func__, s1970); | ||
| 207 | |||
| 208 | return 0; | ||
| 129 | } | 209 | } |
| 130 | 210 | ||
| 131 | static int mc13783_rtc_update_irq_enable(struct device *dev, | 211 | static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
| 132 | unsigned int enabled) | ||
| 133 | { | 212 | { |
| 134 | struct mc13783_rtc *priv = dev_get_drvdata(dev); | 213 | struct mc13783_rtc *priv = dev_get_drvdata(dev); |
| 135 | int ret = -ENODATA; | 214 | unsigned long s1970; |
| 215 | unsigned seconds, days; | ||
| 216 | int ret; | ||
| 136 | 217 | ||
| 137 | mc13783_lock(priv->mc13783); | 218 | mc13783_lock(priv->mc13783); |
| 138 | if (!priv->valid) | 219 | |
| 220 | /* disable alarm to prevent false triggering */ | ||
| 221 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff); | ||
| 222 | if (unlikely(ret)) | ||
| 139 | goto out; | 223 | goto out; |
| 140 | 224 | ||
| 141 | ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783, | 225 | ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA); |
| 142 | MC13783_IRQ_1HZ); | 226 | if (unlikely(ret)) |
| 227 | goto out; | ||
| 228 | |||
| 229 | ret = rtc_tm_to_time(&alarm->time, &s1970); | ||
| 230 | if (unlikely(ret)) | ||
| 231 | goto out; | ||
| 232 | |||
| 233 | dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff", | ||
| 234 | s1970); | ||
| 235 | |||
| 236 | ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled, | ||
| 237 | MC13783_IRQ_TODA); | ||
| 238 | if (unlikely(ret)) | ||
| 239 | goto out; | ||
| 240 | |||
| 241 | seconds = s1970 % 86400; | ||
| 242 | days = s1970 / 86400; | ||
| 243 | |||
| 244 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days); | ||
| 245 | if (unlikely(ret)) | ||
| 246 | goto out; | ||
| 247 | |||
| 248 | ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds); | ||
| 249 | |||
| 143 | out: | 250 | out: |
| 144 | mc13783_unlock(priv->mc13783); | 251 | mc13783_unlock(priv->mc13783); |
| 145 | 252 | ||
| 146 | return ret; | 253 | return ret; |
| 147 | } | 254 | } |
| 148 | 255 | ||
| 256 | static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev) | ||
| 257 | { | ||
| 258 | struct mc13783_rtc *priv = dev; | ||
| 259 | struct mc13783 *mc13783 = priv->mc13783; | ||
| 260 | |||
| 261 | dev_dbg(&priv->rtc->dev, "Alarm\n"); | ||
| 262 | |||
| 263 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF); | ||
| 264 | |||
| 265 | mc13783_irq_ack(mc13783, irq); | ||
| 266 | |||
| 267 | return IRQ_HANDLED; | ||
| 268 | } | ||
| 269 | |||
| 270 | static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev) | ||
| 271 | { | ||
| 272 | struct mc13783_rtc *priv = dev; | ||
| 273 | struct mc13783 *mc13783 = priv->mc13783; | ||
| 274 | |||
| 275 | dev_dbg(&priv->rtc->dev, "1HZ\n"); | ||
| 276 | |||
| 277 | rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF); | ||
| 278 | |||
| 279 | mc13783_irq_ack(mc13783, irq); | ||
| 280 | |||
| 281 | return IRQ_HANDLED; | ||
| 282 | } | ||
| 283 | |||
| 284 | static int mc13783_rtc_update_irq_enable(struct device *dev, | ||
| 285 | unsigned int enabled) | ||
| 286 | { | ||
| 287 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ); | ||
| 288 | } | ||
| 289 | |||
| 290 | static int mc13783_rtc_alarm_irq_enable(struct device *dev, | ||
| 291 | unsigned int enabled) | ||
| 292 | { | ||
| 293 | return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA); | ||
| 294 | } | ||
| 295 | |||
| 149 | static const struct rtc_class_ops mc13783_rtc_ops = { | 296 | static const struct rtc_class_ops mc13783_rtc_ops = { |
| 150 | .read_time = mc13783_rtc_read_time, | 297 | .read_time = mc13783_rtc_read_time, |
| 151 | .set_mmss = mc13783_rtc_set_mmss, | 298 | .set_mmss = mc13783_rtc_set_mmss, |
| 299 | .read_alarm = mc13783_rtc_read_alarm, | ||
| 300 | .set_alarm = mc13783_rtc_set_alarm, | ||
| 301 | .alarm_irq_enable = mc13783_rtc_alarm_irq_enable, | ||
| 152 | .update_irq_enable = mc13783_rtc_update_irq_enable, | 302 | .update_irq_enable = mc13783_rtc_update_irq_enable, |
| 153 | }; | 303 | }; |
| 154 | 304 | ||
| @@ -160,7 +310,7 @@ static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev) | |||
| 160 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); | 310 | dev_dbg(&priv->rtc->dev, "RTCRST\n"); |
| 161 | priv->valid = 0; | 311 | priv->valid = 0; |
| 162 | 312 | ||
| 163 | mc13783_mask(mc13783, irq); | 313 | mc13783_irq_mask(mc13783, irq); |
| 164 | 314 | ||
| 165 | return IRQ_HANDLED; | 315 | return IRQ_HANDLED; |
| 166 | } | 316 | } |
| @@ -169,6 +319,7 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
| 169 | { | 319 | { |
| 170 | int ret; | 320 | int ret; |
| 171 | struct mc13783_rtc *priv; | 321 | struct mc13783_rtc *priv; |
| 322 | int rtcrst_pending; | ||
| 172 | 323 | ||
| 173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 324 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 174 | if (!priv) | 325 | if (!priv) |
| @@ -177,8 +328,6 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
| 177 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | 328 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); |
| 178 | platform_set_drvdata(pdev, priv); | 329 | platform_set_drvdata(pdev, priv); |
| 179 | 330 | ||
| 180 | priv->valid = 1; | ||
| 181 | |||
| 182 | mc13783_lock(priv->mc13783); | 331 | mc13783_lock(priv->mc13783); |
| 183 | 332 | ||
| 184 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, | 333 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, |
| @@ -186,33 +335,45 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
| 186 | if (ret) | 335 | if (ret) |
| 187 | goto err_reset_irq_request; | 336 | goto err_reset_irq_request; |
| 188 | 337 | ||
| 338 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST, | ||
| 339 | NULL, &rtcrst_pending); | ||
| 340 | if (ret) | ||
| 341 | goto err_reset_irq_status; | ||
| 342 | |||
| 343 | priv->valid = !rtcrst_pending; | ||
| 344 | |||
| 189 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, | 345 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, |
| 190 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | 346 | mc13783_rtc_update_handler, DRIVER_NAME, priv); |
| 191 | if (ret) | 347 | if (ret) |
| 192 | goto err_update_irq_request; | 348 | goto err_update_irq_request; |
| 193 | 349 | ||
| 194 | mc13783_unlock(priv->mc13783); | 350 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_TODA, |
| 351 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); | ||
| 352 | if (ret) | ||
| 353 | goto err_alarm_irq_request; | ||
| 195 | 354 | ||
| 196 | priv->rtc = rtc_device_register(pdev->name, | 355 | priv->rtc = rtc_device_register(pdev->name, |
| 197 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); | 356 | &pdev->dev, &mc13783_rtc_ops, THIS_MODULE); |
| 198 | |||
| 199 | if (IS_ERR(priv->rtc)) { | 357 | if (IS_ERR(priv->rtc)) { |
| 200 | ret = PTR_ERR(priv->rtc); | 358 | ret = PTR_ERR(priv->rtc); |
| 201 | 359 | ||
| 202 | mc13783_lock(priv->mc13783); | 360 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); |
| 361 | err_alarm_irq_request: | ||
| 203 | 362 | ||
| 204 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 363 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); |
| 205 | err_update_irq_request: | 364 | err_update_irq_request: |
| 206 | 365 | ||
| 366 | err_reset_irq_status: | ||
| 367 | |||
| 207 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 368 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); |
| 208 | err_reset_irq_request: | 369 | err_reset_irq_request: |
| 209 | 370 | ||
| 210 | mc13783_unlock(priv->mc13783); | ||
| 211 | |||
| 212 | platform_set_drvdata(pdev, NULL); | 371 | platform_set_drvdata(pdev, NULL); |
| 213 | kfree(priv); | 372 | kfree(priv); |
| 214 | } | 373 | } |
| 215 | 374 | ||
| 375 | mc13783_unlock(priv->mc13783); | ||
| 376 | |||
| 216 | return ret; | 377 | return ret; |
| 217 | } | 378 | } |
| 218 | 379 | ||
| @@ -220,10 +381,11 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev) | |||
| 220 | { | 381 | { |
| 221 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); | 382 | struct mc13783_rtc *priv = platform_get_drvdata(pdev); |
| 222 | 383 | ||
| 223 | rtc_device_unregister(priv->rtc); | ||
| 224 | |||
| 225 | mc13783_lock(priv->mc13783); | 384 | mc13783_lock(priv->mc13783); |
| 226 | 385 | ||
| 386 | rtc_device_unregister(priv->rtc); | ||
| 387 | |||
| 388 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | ||
| 227 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 389 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); |
| 228 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 390 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); |
| 229 | 391 | ||
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 6bd5072d4eb7..8710f9415d98 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
| @@ -396,8 +396,11 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
| 396 | pdata->ioaddr = ioremap(res->start, resource_size(res)); | 396 | pdata->ioaddr = ioremap(res->start, resource_size(res)); |
| 397 | 397 | ||
| 398 | clk = clk_get(&pdev->dev, "ckil"); | 398 | clk = clk_get(&pdev->dev, "ckil"); |
| 399 | if (IS_ERR(clk)) | 399 | if (IS_ERR(clk)) { |
| 400 | return PTR_ERR(clk); | 400 | iounmap(pdata->ioaddr); |
| 401 | ret = PTR_ERR(clk); | ||
| 402 | goto exit_free_pdata; | ||
| 403 | } | ||
| 401 | 404 | ||
| 402 | rate = clk_get_rate(clk); | 405 | rate = clk_get_rate(clk); |
| 403 | clk_put(clk); | 406 | clk_put(clk); |
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index e75df9d50e27..2ceb365533b2 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c | |||
| @@ -315,7 +315,7 @@ kfree_exit: | |||
| 315 | return ret; | 315 | return ret; |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | static int pcf2123_remove(struct spi_device *spi) | 318 | static int __devexit pcf2123_remove(struct spi_device *spi) |
| 319 | { | 319 | { |
| 320 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; | 320 | struct pcf2123_plat_data *pdata = spi->dev.platform_data; |
| 321 | int i; | 321 | int i; |
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index c6a83a2a722c..ed1b86828124 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c | |||
| @@ -57,7 +57,7 @@ enum { | |||
| 57 | REG_RTC_COMP_LSB_REG, | 57 | REG_RTC_COMP_LSB_REG, |
| 58 | REG_RTC_COMP_MSB_REG, | 58 | REG_RTC_COMP_MSB_REG, |
| 59 | }; | 59 | }; |
| 60 | const static u8 twl4030_rtc_reg_map[] = { | 60 | static const u8 twl4030_rtc_reg_map[] = { |
| 61 | [REG_SECONDS_REG] = 0x00, | 61 | [REG_SECONDS_REG] = 0x00, |
| 62 | [REG_MINUTES_REG] = 0x01, | 62 | [REG_MINUTES_REG] = 0x01, |
| 63 | [REG_HOURS_REG] = 0x02, | 63 | [REG_HOURS_REG] = 0x02, |
| @@ -80,7 +80,7 @@ const static u8 twl4030_rtc_reg_map[] = { | |||
| 80 | [REG_RTC_COMP_LSB_REG] = 0x10, | 80 | [REG_RTC_COMP_LSB_REG] = 0x10, |
| 81 | [REG_RTC_COMP_MSB_REG] = 0x11, | 81 | [REG_RTC_COMP_MSB_REG] = 0x11, |
| 82 | }; | 82 | }; |
| 83 | const static u8 twl6030_rtc_reg_map[] = { | 83 | static const u8 twl6030_rtc_reg_map[] = { |
| 84 | [REG_SECONDS_REG] = 0x00, | 84 | [REG_SECONDS_REG] = 0x00, |
| 85 | [REG_MINUTES_REG] = 0x01, | 85 | [REG_MINUTES_REG] = 0x01, |
| 86 | [REG_HOURS_REG] = 0x02, | 86 | [REG_HOURS_REG] = 0x02, |
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index f69b7783027f..11fc4d5c43e1 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c | |||
| @@ -969,7 +969,7 @@ int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) | |||
| 969 | 969 | ||
| 970 | if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | 970 | if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || |
| 971 | (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | 971 | (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { |
| 972 | err = vfs_dq_transfer(inode, attr) ? -EDQUOT : 0; | 972 | err = dquot_transfer(inode, attr); |
| 973 | if (err) | 973 | if (err) |
| 974 | goto err_out_exit; | 974 | goto err_out_exit; |
| 975 | } | 975 | } |
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index fc7d9bbb548c..8e8f18d29d7a 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig | |||
| @@ -37,6 +37,7 @@ config VGACON_SOFT_SCROLLBACK | |||
| 37 | config VGACON_SOFT_SCROLLBACK_SIZE | 37 | config VGACON_SOFT_SCROLLBACK_SIZE |
| 38 | int "Scrollback Buffer Size (in KB)" | 38 | int "Scrollback Buffer Size (in KB)" |
| 39 | depends on VGACON_SOFT_SCROLLBACK | 39 | depends on VGACON_SOFT_SCROLLBACK |
| 40 | range 1 1024 | ||
| 40 | default "64" | 41 | default "64" |
| 41 | help | 42 | help |
| 42 | Enter the amount of System RAM to allocate for the scrollback | 43 | Enter the amount of System RAM to allocate for the scrollback |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index cc4bbbe44aca..182dd6f8aadd 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
| @@ -112,7 +112,7 @@ static int vga_video_font_height; | |||
| 112 | static int vga_scan_lines __read_mostly; | 112 | static int vga_scan_lines __read_mostly; |
| 113 | static unsigned int vga_rolled_over; | 113 | static unsigned int vga_rolled_over; |
| 114 | 114 | ||
| 115 | int vgacon_text_mode_force = 0; | 115 | static int vgacon_text_mode_force; |
| 116 | 116 | ||
| 117 | bool vgacon_text_force(void) | 117 | bool vgacon_text_force(void) |
| 118 | { | 118 | { |
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index cab100acf983..fad3df2c1276 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | menu "Xen driver support" | ||
| 2 | depends on XEN | ||
| 3 | |||
| 1 | config XEN_BALLOON | 4 | config XEN_BALLOON |
| 2 | bool "Xen memory balloon driver" | 5 | bool "Xen memory balloon driver" |
| 3 | depends on XEN | ||
| 4 | default y | 6 | default y |
| 5 | help | 7 | help |
| 6 | The balloon driver allows the Xen domain to request more memory from | 8 | The balloon driver allows the Xen domain to request more memory from |
| @@ -20,7 +22,6 @@ config XEN_SCRUB_PAGES | |||
| 20 | 22 | ||
| 21 | config XEN_DEV_EVTCHN | 23 | config XEN_DEV_EVTCHN |
| 22 | tristate "Xen /dev/xen/evtchn device" | 24 | tristate "Xen /dev/xen/evtchn device" |
| 23 | depends on XEN | ||
| 24 | default y | 25 | default y |
| 25 | help | 26 | help |
| 26 | The evtchn driver allows a userspace process to triger event | 27 | The evtchn driver allows a userspace process to triger event |
| @@ -30,7 +31,6 @@ config XEN_DEV_EVTCHN | |||
| 30 | 31 | ||
| 31 | config XENFS | 32 | config XENFS |
| 32 | tristate "Xen filesystem" | 33 | tristate "Xen filesystem" |
| 33 | depends on XEN | ||
| 34 | default y | 34 | default y |
| 35 | help | 35 | help |
| 36 | The xen filesystem provides a way for domains to share | 36 | The xen filesystem provides a way for domains to share |
| @@ -53,11 +53,13 @@ config XEN_COMPAT_XENFS | |||
| 53 | 53 | ||
| 54 | config XEN_SYS_HYPERVISOR | 54 | config XEN_SYS_HYPERVISOR |
| 55 | bool "Create xen entries under /sys/hypervisor" | 55 | bool "Create xen entries under /sys/hypervisor" |
| 56 | depends on XEN && SYSFS | 56 | depends on SYSFS |
| 57 | select SYS_HYPERVISOR | 57 | select SYS_HYPERVISOR |
| 58 | default y | 58 | default y |
| 59 | help | 59 | help |
| 60 | Create entries under /sys/hypervisor describing the Xen | 60 | Create entries under /sys/hypervisor describing the Xen |
| 61 | hypervisor environment. When running native or in another | 61 | hypervisor environment. When running native or in another |
| 62 | virtual environment, /sys/hypervisor will still be present, | 62 | virtual environment, /sys/hypervisor will still be present, |
| 63 | but will have no xen contents. \ No newline at end of file | 63 | but will have no xen contents. |
| 64 | |||
| 65 | endmenu | ||
