diff options
Diffstat (limited to 'drivers')
356 files changed, 11804 insertions, 4115 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 3d93b3a3d630..dd0a5b5e9bf3 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -88,6 +88,8 @@ source "drivers/memstick/Kconfig" | |||
88 | 88 | ||
89 | source "drivers/leds/Kconfig" | 89 | source "drivers/leds/Kconfig" |
90 | 90 | ||
91 | source "drivers/nfc/Kconfig" | ||
92 | |||
91 | source "drivers/accessibility/Kconfig" | 93 | source "drivers/accessibility/Kconfig" |
92 | 94 | ||
93 | source "drivers/infiniband/Kconfig" | 95 | source "drivers/infiniband/Kconfig" |
diff --git a/drivers/Makefile b/drivers/Makefile index bf15ce7493d2..ef5132469f58 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -40,7 +40,7 @@ obj-$(CONFIG_FB_INTEL) += video/intelfb/ | |||
40 | 40 | ||
41 | obj-y += serial/ | 41 | obj-y += serial/ |
42 | obj-$(CONFIG_PARPORT) += parport/ | 42 | obj-$(CONFIG_PARPORT) += parport/ |
43 | obj-y += base/ block/ misc/ mfd/ | 43 | obj-y += base/ block/ misc/ mfd/ nfc/ |
44 | obj-$(CONFIG_NUBUS) += nubus/ | 44 | obj-$(CONFIG_NUBUS) += nubus/ |
45 | obj-y += macintosh/ | 45 | obj-y += macintosh/ |
46 | obj-$(CONFIG_IDE) += ide/ | 46 | obj-$(CONFIG_IDE) += ide/ |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index bdbfaf22bd14..962a3ccff6fd 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
@@ -93,7 +93,7 @@ | |||
93 | 93 | ||
94 | #define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ | 94 | #define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */ |
95 | #define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ | 95 | #define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */ |
96 | #define AOPOBJ_DATA_VALID 0x04 /* Object is intialized and data is valid */ | 96 | #define AOPOBJ_DATA_VALID 0x04 /* Object is initialized and data is valid */ |
97 | #define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ | 97 | #define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */ |
98 | #define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ | 98 | #define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */ |
99 | #define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ | 99 | #define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */ |
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index cf29df69380b..096aebfe7f32 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #define EINJ_PFX "EINJ: " | 39 | #define EINJ_PFX "EINJ: " |
40 | 40 | ||
41 | #define SPIN_UNIT 100 /* 100ns */ | 41 | #define SPIN_UNIT 100 /* 100ns */ |
42 | /* Firmware should respond within 1 miliseconds */ | 42 | /* Firmware should respond within 1 milliseconds */ |
43 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) | 43 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) |
44 | 44 | ||
45 | /* | 45 | /* |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 5850d320404c..cf6db6b7662a 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -53,7 +53,7 @@ | |||
53 | sizeof(struct acpi_table_erst))) | 53 | sizeof(struct acpi_table_erst))) |
54 | 54 | ||
55 | #define SPIN_UNIT 100 /* 100ns */ | 55 | #define SPIN_UNIT 100 /* 100ns */ |
56 | /* Firmware should respond within 1 miliseconds */ | 56 | /* Firmware should respond within 1 milliseconds */ |
57 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) | 57 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) |
58 | #define FIRMWARE_MAX_STALL 50 /* 50us */ | 58 | #define FIRMWARE_MAX_STALL 50 /* 50us */ |
59 | 59 | ||
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index febb153b5a68..c423231b952b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -319,7 +319,7 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state) | |||
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
322 | static struct platform_suspend_ops acpi_suspend_ops = { | 322 | static const struct platform_suspend_ops acpi_suspend_ops = { |
323 | .valid = acpi_suspend_state_valid, | 323 | .valid = acpi_suspend_state_valid, |
324 | .begin = acpi_suspend_begin, | 324 | .begin = acpi_suspend_begin, |
325 | .prepare_late = acpi_pm_prepare, | 325 | .prepare_late = acpi_pm_prepare, |
@@ -347,7 +347,7 @@ static int acpi_suspend_begin_old(suspend_state_t pm_state) | |||
347 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 347 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
348 | * been requested. | 348 | * been requested. |
349 | */ | 349 | */ |
350 | static struct platform_suspend_ops acpi_suspend_ops_old = { | 350 | static const struct platform_suspend_ops acpi_suspend_ops_old = { |
351 | .valid = acpi_suspend_state_valid, | 351 | .valid = acpi_suspend_state_valid, |
352 | .begin = acpi_suspend_begin_old, | 352 | .begin = acpi_suspend_begin_old, |
353 | .prepare_late = acpi_pm_pre_suspend, | 353 | .prepare_late = acpi_pm_pre_suspend, |
@@ -506,7 +506,7 @@ static void acpi_pm_thaw(void) | |||
506 | acpi_enable_all_runtime_gpes(); | 506 | acpi_enable_all_runtime_gpes(); |
507 | } | 507 | } |
508 | 508 | ||
509 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 509 | static const struct platform_hibernation_ops acpi_hibernation_ops = { |
510 | .begin = acpi_hibernation_begin, | 510 | .begin = acpi_hibernation_begin, |
511 | .end = acpi_pm_end, | 511 | .end = acpi_pm_end, |
512 | .pre_snapshot = acpi_pm_prepare, | 512 | .pre_snapshot = acpi_pm_prepare, |
@@ -549,7 +549,7 @@ static int acpi_hibernation_begin_old(void) | |||
549 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has | 549 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
550 | * been requested. | 550 | * been requested. |
551 | */ | 551 | */ |
552 | static struct platform_hibernation_ops acpi_hibernation_ops_old = { | 552 | static const struct platform_hibernation_ops acpi_hibernation_ops_old = { |
553 | .begin = acpi_hibernation_begin_old, | 553 | .begin = acpi_hibernation_begin_old, |
554 | .end = acpi_pm_end, | 554 | .end = acpi_pm_end, |
555 | .pre_snapshot = acpi_pm_pre_suspend, | 555 | .pre_snapshot = acpi_pm_pre_suspend, |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5cd0228d2daa..15a0fde4b32a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -260,7 +260,7 @@ static int acpi_video_set_brightness(struct backlight_device *bd) | |||
260 | vd->brightness->levels[request_level]); | 260 | vd->brightness->levels[request_level]); |
261 | } | 261 | } |
262 | 262 | ||
263 | static struct backlight_ops acpi_backlight_ops = { | 263 | static const struct backlight_ops acpi_backlight_ops = { |
264 | .get_brightness = acpi_video_get_brightness, | 264 | .get_brightness = acpi_video_get_brightness, |
265 | .update_status = acpi_video_set_brightness, | 265 | .update_status = acpi_video_set_brightness, |
266 | }; | 266 | }; |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0a6a943b3779..a31fe96f7de6 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -2240,7 +2240,7 @@ int ata_dev_configure(struct ata_device *dev) | |||
2240 | if (id[ATA_ID_CFA_KEY_MGMT] & 1) | 2240 | if (id[ATA_ID_CFA_KEY_MGMT] & 1) |
2241 | ata_dev_printk(dev, KERN_WARNING, | 2241 | ata_dev_printk(dev, KERN_WARNING, |
2242 | "supports DRM functions and may " | 2242 | "supports DRM functions and may " |
2243 | "not be fully accessable.\n"); | 2243 | "not be fully accessible.\n"); |
2244 | snprintf(revbuf, 7, "CFA"); | 2244 | snprintf(revbuf, 7, "CFA"); |
2245 | } else { | 2245 | } else { |
2246 | snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); | 2246 | snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); |
@@ -2248,7 +2248,7 @@ int ata_dev_configure(struct ata_device *dev) | |||
2248 | if (ata_id_has_tpm(id)) | 2248 | if (ata_id_has_tpm(id)) |
2249 | ata_dev_printk(dev, KERN_WARNING, | 2249 | ata_dev_printk(dev, KERN_WARNING, |
2250 | "supports DRM functions and may " | 2250 | "supports DRM functions and may " |
2251 | "not be fully accessable.\n"); | 2251 | "not be fully accessible.\n"); |
2252 | } | 2252 | } |
2253 | 2253 | ||
2254 | dev->n_sectors = ata_id_n_sectors(id); | 2254 | dev->n_sectors = ata_id_n_sectors(id); |
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index b777176ff494..e079cf29ed5d 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c | |||
@@ -370,7 +370,7 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev, | |||
370 | if (pci_resource_len(pdev, 0) == 0) | 370 | if (pci_resource_len(pdev, 0) == 0) |
371 | return -ENODEV; | 371 | return -ENODEV; |
372 | 372 | ||
373 | /* map IO regions and intialize host accordingly */ | 373 | /* map IO regions and initialize host accordingly */ |
374 | rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME); | 374 | rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME); |
375 | if (rc == -EBUSY) | 375 | if (rc == -EBUSY) |
376 | pcim_pin_device(pdev); | 376 | pcim_pin_device(pdev); |
diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h index 5042bb2dab15..f53a43ae2bbe 100644 --- a/drivers/atm/idt77252.h +++ b/drivers/atm/idt77252.h | |||
@@ -572,7 +572,7 @@ struct idt77252_dev | |||
572 | #define SAR_STAT_TSQF 0x00001000 /* Transmit Status Queue full */ | 572 | #define SAR_STAT_TSQF 0x00001000 /* Transmit Status Queue full */ |
573 | #define SAR_STAT_TMROF 0x00000800 /* Timer overflow */ | 573 | #define SAR_STAT_TMROF 0x00000800 /* Timer overflow */ |
574 | #define SAR_STAT_PHYI 0x00000400 /* PHY device Interrupt flag */ | 574 | #define SAR_STAT_PHYI 0x00000400 /* PHY device Interrupt flag */ |
575 | #define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Comand Busy Flag */ | 575 | #define SAR_STAT_CMDBZ 0x00000200 /* ABR SAR Command Busy Flag */ |
576 | #define SAR_STAT_FBQ3A 0x00000100 /* Free Buffer Queue 3 Attention */ | 576 | #define SAR_STAT_FBQ3A 0x00000100 /* Free Buffer Queue 3 Attention */ |
577 | #define SAR_STAT_FBQ2A 0x00000080 /* Free Buffer Queue 2 Attention */ | 577 | #define SAR_STAT_FBQ2A 0x00000080 /* Free Buffer Queue 2 Attention */ |
578 | #define SAR_STAT_RSQF 0x00000040 /* Receive Status Queue full */ | 578 | #define SAR_STAT_RSQF 0x00000040 /* Receive Status Queue full */ |
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 729254053758..d80d51b62a1a 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c | |||
@@ -2063,7 +2063,7 @@ static int tx_init(struct atm_dev *dev) | |||
2063 | - UBR Table size is 4K | 2063 | - UBR Table size is 4K |
2064 | - UBR wait queue is 4K | 2064 | - UBR wait queue is 4K |
2065 | since the table and wait queues are contiguous, all the bytes | 2065 | since the table and wait queues are contiguous, all the bytes |
2066 | can be initialized by one memeset. | 2066 | can be initialized by one memeset. |
2067 | */ | 2067 | */ |
2068 | 2068 | ||
2069 | vcsize_sel = 0; | 2069 | vcsize_sel = 0; |
@@ -2089,7 +2089,7 @@ static int tx_init(struct atm_dev *dev) | |||
2089 | - ABR Table size is 2K | 2089 | - ABR Table size is 2K |
2090 | - ABR wait queue is 2K | 2090 | - ABR wait queue is 2K |
2091 | since the table and wait queues are contiguous, all the bytes | 2091 | since the table and wait queues are contiguous, all the bytes |
2092 | can be intialized by one memeset. | 2092 | can be initialized by one memeset. |
2093 | */ | 2093 | */ |
2094 | i = ABR_SCHED_TABLE * iadev->memSize; | 2094 | i = ABR_SCHED_TABLE * iadev->memSize; |
2095 | writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE); | 2095 | writew((i >> 11) & 0xffff, iadev->seg_reg+ABR_SBPTR_BASE); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index e243bd49764b..000e7b2006f8 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -975,7 +975,7 @@ struct klist *bus_get_device_klist(struct bus_type *bus) | |||
975 | EXPORT_SYMBOL_GPL(bus_get_device_klist); | 975 | EXPORT_SYMBOL_GPL(bus_get_device_klist); |
976 | 976 | ||
977 | /* | 977 | /* |
978 | * Yes, this forcably breaks the klist abstraction temporarily. It | 978 | * Yes, this forcibly breaks the klist abstraction temporarily. It |
979 | * just wants to sort the klist, not change reference counts and | 979 | * just wants to sort the klist, not change reference counts and |
980 | * take/drop locks rapidly in the process. It does all this while | 980 | * take/drop locks rapidly in the process. It does all this while |
981 | * holding the lock for the list, so objects can't otherwise be | 981 | * holding the lock for the list, so objects can't otherwise be |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 2a52270aeb30..83404973f97a 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * | 9 | * |
10 | * The driver model core calls device_pm_add() when a device is registered. | 10 | * The driver model core calls device_pm_add() when a device is registered. |
11 | * This will intialize the embedded device_pm_info object in the device | 11 | * This will initialize the embedded device_pm_info object in the device |
12 | * and add it to the list of power-controlled devices. sysfs entries for | 12 | * and add it to the list of power-controlled devices. sysfs entries for |
13 | * controlling device power management will also be added. | 13 | * controlling device power management will also be added. |
14 | * | 14 | * |
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 008d4a00b50d..e1e38b11f48a 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1790,18 +1790,29 @@ static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count) | |||
1790 | 1790 | ||
1791 | rc = rbd_bus_add_dev(rbd_dev); | 1791 | rc = rbd_bus_add_dev(rbd_dev); |
1792 | if (rc) | 1792 | if (rc) |
1793 | goto err_out_disk; | 1793 | goto err_out_blkdev; |
1794 | |||
1794 | /* set up and announce blkdev mapping */ | 1795 | /* set up and announce blkdev mapping */ |
1795 | rc = rbd_init_disk(rbd_dev); | 1796 | rc = rbd_init_disk(rbd_dev); |
1796 | if (rc) | 1797 | if (rc) |
1797 | goto err_out_blkdev; | 1798 | goto err_out_bus; |
1798 | 1799 | ||
1799 | return count; | 1800 | return count; |
1800 | 1801 | ||
1802 | err_out_bus: | ||
1803 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
1804 | list_del_init(&rbd_dev->node); | ||
1805 | mutex_unlock(&ctl_mutex); | ||
1806 | |||
1807 | /* this will also clean up rest of rbd_dev stuff */ | ||
1808 | |||
1809 | rbd_bus_del_dev(rbd_dev); | ||
1810 | kfree(options); | ||
1811 | kfree(mon_dev_name); | ||
1812 | return rc; | ||
1813 | |||
1801 | err_out_blkdev: | 1814 | err_out_blkdev: |
1802 | unregister_blkdev(rbd_dev->major, rbd_dev->name); | 1815 | unregister_blkdev(rbd_dev->major, rbd_dev->name); |
1803 | err_out_disk: | ||
1804 | rbd_free_disk(rbd_dev); | ||
1805 | err_out_client: | 1816 | err_out_client: |
1806 | rbd_put_client(rbd_dev); | 1817 | rbd_put_client(rbd_dev); |
1807 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 1818 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d4a7776f4b77..0f175a866ef0 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1047,15 +1047,6 @@ config NSC_GPIO | |||
1047 | pc8736x_gpio drivers. If those drivers are built as | 1047 | pc8736x_gpio drivers. If those drivers are built as |
1048 | modules, this one will be too, named nsc_gpio | 1048 | modules, this one will be too, named nsc_gpio |
1049 | 1049 | ||
1050 | config CS5535_GPIO | ||
1051 | tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)" | ||
1052 | depends on X86_32 | ||
1053 | help | ||
1054 | Give userspace access to the GPIO pins on the AMD CS5535 and | ||
1055 | CS5536 Geode companion devices. | ||
1056 | |||
1057 | If compiled as a module, it will be called cs5535_gpio. | ||
1058 | |||
1059 | config RAW_DRIVER | 1050 | config RAW_DRIVER |
1060 | tristate "RAW driver (/dev/raw/rawN)" | 1051 | tristate "RAW driver (/dev/raw/rawN)" |
1061 | depends on BLOCK | 1052 | depends on BLOCK |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index fa0b824b7a65..1e9dffb33778 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -82,7 +82,6 @@ obj-$(CONFIG_NWFLASH) += nwflash.o | |||
82 | obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o | 82 | obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o |
83 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o | 83 | obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o |
84 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o | 84 | obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o |
85 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o | ||
86 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o | 85 | obj-$(CONFIG_GPIO_TB0219) += tb0219.o |
87 | obj-$(CONFIG_TELCLOCK) += tlclk.o | 86 | obj-$(CONFIG_TELCLOCK) += tlclk.o |
88 | 87 | ||
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 794aacb715c1..d0387a84eec1 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * warranty of any kind, whether express or implied. | 24 | * warranty of any kind, whether express or implied. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <crypto/padlock.h> | ||
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
29 | #include <linux/hw_random.h> | 30 | #include <linux/hw_random.h> |
@@ -34,7 +35,6 @@ | |||
34 | #include <asm/i387.h> | 35 | #include <asm/i387.h> |
35 | 36 | ||
36 | 37 | ||
37 | #define PFX KBUILD_MODNAME ": " | ||
38 | 38 | ||
39 | 39 | ||
40 | enum { | 40 | enum { |
@@ -81,8 +81,7 @@ static inline u32 xstore(u32 *addr, u32 edx_in) | |||
81 | ts_state = irq_ts_save(); | 81 | ts_state = irq_ts_save(); |
82 | 82 | ||
83 | asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" | 83 | asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" |
84 | :"=m"(*addr), "=a"(eax_out) | 84 | : "=m" (*addr), "=a" (eax_out), "+d" (edx_in), "+D" (addr)); |
85 | :"D"(addr), "d"(edx_in)); | ||
86 | 85 | ||
87 | irq_ts_restore(ts_state); | 86 | irq_ts_restore(ts_state); |
88 | return eax_out; | 87 | return eax_out; |
@@ -90,8 +89,10 @@ static inline u32 xstore(u32 *addr, u32 edx_in) | |||
90 | 89 | ||
91 | static int via_rng_data_present(struct hwrng *rng, int wait) | 90 | static int via_rng_data_present(struct hwrng *rng, int wait) |
92 | { | 91 | { |
92 | char buf[16 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__ | ||
93 | ((aligned(STACK_ALIGN))); | ||
94 | u32 *via_rng_datum = (u32 *)PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); | ||
93 | u32 bytes_out; | 95 | u32 bytes_out; |
94 | u32 *via_rng_datum = (u32 *)(&rng->priv); | ||
95 | int i; | 96 | int i; |
96 | 97 | ||
97 | /* We choose the recommended 1-byte-per-instruction RNG rate, | 98 | /* We choose the recommended 1-byte-per-instruction RNG rate, |
@@ -115,6 +116,7 @@ static int via_rng_data_present(struct hwrng *rng, int wait) | |||
115 | break; | 116 | break; |
116 | udelay(10); | 117 | udelay(10); |
117 | } | 118 | } |
119 | rng->priv = *via_rng_datum; | ||
118 | return bytes_out ? 1 : 0; | 120 | return bytes_out ? 1 : 0; |
119 | } | 121 | } |
120 | 122 | ||
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index d3d63be2cd37..1a9f5f6d6ac5 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #define RAMOOPS_KERNMSG_HDR "====" | 31 | #define RAMOOPS_KERNMSG_HDR "====" |
32 | 32 | ||
33 | #define RECORD_SIZE 4096 | 33 | #define RECORD_SIZE 4096UL |
34 | 34 | ||
35 | static ulong mem_address; | 35 | static ulong mem_address; |
36 | module_param(mem_address, ulong, 0400); | 36 | module_param(mem_address, ulong, 0400); |
@@ -68,11 +68,16 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, | |||
68 | char *buf, *buf_orig; | 68 | char *buf, *buf_orig; |
69 | struct timeval timestamp; | 69 | struct timeval timestamp; |
70 | 70 | ||
71 | if (reason != KMSG_DUMP_OOPS && | ||
72 | reason != KMSG_DUMP_PANIC && | ||
73 | reason != KMSG_DUMP_KEXEC) | ||
74 | return; | ||
75 | |||
71 | /* Only dump oopses if dump_oops is set */ | 76 | /* Only dump oopses if dump_oops is set */ |
72 | if (reason == KMSG_DUMP_OOPS && !dump_oops) | 77 | if (reason == KMSG_DUMP_OOPS && !dump_oops) |
73 | return; | 78 | return; |
74 | 79 | ||
75 | buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE)); | 80 | buf = cxt->virt_addr + (cxt->count * RECORD_SIZE); |
76 | buf_orig = buf; | 81 | buf_orig = buf; |
77 | 82 | ||
78 | memset(buf, '\0', RECORD_SIZE); | 83 | memset(buf, '\0', RECORD_SIZE); |
@@ -83,8 +88,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, | |||
83 | buf += res; | 88 | buf += res; |
84 | 89 | ||
85 | hdr_size = buf - buf_orig; | 90 | hdr_size = buf - buf_orig; |
86 | l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - hdr_size)); | 91 | l2_cpy = min(l2, RECORD_SIZE - hdr_size); |
87 | l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - hdr_size) - l2_cpy); | 92 | l1_cpy = min(l1, RECORD_SIZE - hdr_size - l2_cpy); |
88 | 93 | ||
89 | s2_start = l2 - l2_cpy; | 94 | s2_start = l2 - l2_cpy; |
90 | s1_start = l1 - l1_cpy; | 95 | s1_start = l1 - l1_cpy; |
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index 7d279e578df5..c99305afa58a 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c | |||
@@ -857,7 +857,7 @@ static int mv_cra_hash_init(struct crypto_tfm *tfm, const char *base_hash_name, | |||
857 | printk(KERN_WARNING MV_CESA | 857 | printk(KERN_WARNING MV_CESA |
858 | "Base driver '%s' could not be loaded!\n", | 858 | "Base driver '%s' could not be loaded!\n", |
859 | base_hash_name); | 859 | base_hash_name); |
860 | err = PTR_ERR(fallback_tfm); | 860 | err = PTR_ERR(base_hash); |
861 | goto err_bad_base; | 861 | goto err_bad_base; |
862 | } | 862 | } |
863 | } | 863 | } |
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 76141262ea1d..80dc094e78c6 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c | |||
@@ -1542,7 +1542,7 @@ out: | |||
1542 | return err; | 1542 | return err; |
1543 | } | 1543 | } |
1544 | 1544 | ||
1545 | static void __exit n2_unregister_algs(void) | 1545 | static void __devexit n2_unregister_algs(void) |
1546 | { | 1546 | { |
1547 | mutex_lock(&spu_lock); | 1547 | mutex_lock(&spu_lock); |
1548 | if (!--algs_registered) | 1548 | if (!--algs_registered) |
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 799ca517c121..add2a1a72ba4 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c | |||
@@ -74,11 +74,9 @@ | |||
74 | #define FLAGS_CBC BIT(1) | 74 | #define FLAGS_CBC BIT(1) |
75 | #define FLAGS_GIV BIT(2) | 75 | #define FLAGS_GIV BIT(2) |
76 | 76 | ||
77 | #define FLAGS_NEW_KEY BIT(4) | 77 | #define FLAGS_INIT BIT(4) |
78 | #define FLAGS_NEW_IV BIT(5) | 78 | #define FLAGS_FAST BIT(5) |
79 | #define FLAGS_INIT BIT(6) | 79 | #define FLAGS_BUSY BIT(6) |
80 | #define FLAGS_FAST BIT(7) | ||
81 | #define FLAGS_BUSY 8 | ||
82 | 80 | ||
83 | struct omap_aes_ctx { | 81 | struct omap_aes_ctx { |
84 | struct omap_aes_dev *dd; | 82 | struct omap_aes_dev *dd; |
@@ -98,19 +96,18 @@ struct omap_aes_reqctx { | |||
98 | struct omap_aes_dev { | 96 | struct omap_aes_dev { |
99 | struct list_head list; | 97 | struct list_head list; |
100 | unsigned long phys_base; | 98 | unsigned long phys_base; |
101 | void __iomem *io_base; | 99 | void __iomem *io_base; |
102 | struct clk *iclk; | 100 | struct clk *iclk; |
103 | struct omap_aes_ctx *ctx; | 101 | struct omap_aes_ctx *ctx; |
104 | struct device *dev; | 102 | struct device *dev; |
105 | unsigned long flags; | 103 | unsigned long flags; |
104 | int err; | ||
106 | 105 | ||
107 | u32 *iv; | 106 | spinlock_t lock; |
108 | u32 ctrl; | 107 | struct crypto_queue queue; |
109 | 108 | ||
110 | spinlock_t lock; | 109 | struct tasklet_struct done_task; |
111 | struct crypto_queue queue; | 110 | struct tasklet_struct queue_task; |
112 | |||
113 | struct tasklet_struct task; | ||
114 | 111 | ||
115 | struct ablkcipher_request *req; | 112 | struct ablkcipher_request *req; |
116 | size_t total; | 113 | size_t total; |
@@ -179,9 +176,13 @@ static int omap_aes_wait(struct omap_aes_dev *dd, u32 offset, u32 bit) | |||
179 | 176 | ||
180 | static int omap_aes_hw_init(struct omap_aes_dev *dd) | 177 | static int omap_aes_hw_init(struct omap_aes_dev *dd) |
181 | { | 178 | { |
182 | int err = 0; | 179 | /* |
183 | 180 | * clocks are enabled when request starts and disabled when finished. | |
181 | * It may be long delays between requests. | ||
182 | * Device might go to off mode to save power. | ||
183 | */ | ||
184 | clk_enable(dd->iclk); | 184 | clk_enable(dd->iclk); |
185 | |||
185 | if (!(dd->flags & FLAGS_INIT)) { | 186 | if (!(dd->flags & FLAGS_INIT)) { |
186 | /* is it necessary to reset before every operation? */ | 187 | /* is it necessary to reset before every operation? */ |
187 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, | 188 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_SOFTRESET, |
@@ -193,39 +194,26 @@ static int omap_aes_hw_init(struct omap_aes_dev *dd) | |||
193 | __asm__ __volatile__("nop"); | 194 | __asm__ __volatile__("nop"); |
194 | __asm__ __volatile__("nop"); | 195 | __asm__ __volatile__("nop"); |
195 | 196 | ||
196 | err = omap_aes_wait(dd, AES_REG_SYSSTATUS, | 197 | if (omap_aes_wait(dd, AES_REG_SYSSTATUS, |
197 | AES_REG_SYSSTATUS_RESETDONE); | 198 | AES_REG_SYSSTATUS_RESETDONE)) |
198 | if (!err) | 199 | return -ETIMEDOUT; |
199 | dd->flags |= FLAGS_INIT; | ||
200 | } | ||
201 | 200 | ||
202 | return err; | 201 | dd->flags |= FLAGS_INIT; |
203 | } | 202 | dd->err = 0; |
203 | } | ||
204 | 204 | ||
205 | static void omap_aes_hw_cleanup(struct omap_aes_dev *dd) | 205 | return 0; |
206 | { | ||
207 | clk_disable(dd->iclk); | ||
208 | } | 206 | } |
209 | 207 | ||
210 | static void omap_aes_write_ctrl(struct omap_aes_dev *dd) | 208 | static int omap_aes_write_ctrl(struct omap_aes_dev *dd) |
211 | { | 209 | { |
212 | unsigned int key32; | 210 | unsigned int key32; |
213 | int i; | 211 | int i, err; |
214 | u32 val, mask; | 212 | u32 val, mask; |
215 | 213 | ||
216 | val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); | 214 | err = omap_aes_hw_init(dd); |
217 | if (dd->flags & FLAGS_CBC) | 215 | if (err) |
218 | val |= AES_REG_CTRL_CBC; | 216 | return err; |
219 | if (dd->flags & FLAGS_ENCRYPT) | ||
220 | val |= AES_REG_CTRL_DIRECTION; | ||
221 | |||
222 | if (dd->ctrl == val && !(dd->flags & FLAGS_NEW_IV) && | ||
223 | !(dd->ctx->flags & FLAGS_NEW_KEY)) | ||
224 | goto out; | ||
225 | |||
226 | /* only need to write control registers for new settings */ | ||
227 | |||
228 | dd->ctrl = val; | ||
229 | 217 | ||
230 | val = 0; | 218 | val = 0; |
231 | if (dd->dma_lch_out >= 0) | 219 | if (dd->dma_lch_out >= 0) |
@@ -237,30 +225,43 @@ static void omap_aes_write_ctrl(struct omap_aes_dev *dd) | |||
237 | 225 | ||
238 | omap_aes_write_mask(dd, AES_REG_MASK, val, mask); | 226 | omap_aes_write_mask(dd, AES_REG_MASK, val, mask); |
239 | 227 | ||
240 | pr_debug("Set key\n"); | ||
241 | key32 = dd->ctx->keylen / sizeof(u32); | 228 | key32 = dd->ctx->keylen / sizeof(u32); |
242 | /* set a key */ | 229 | |
230 | /* it seems a key should always be set even if it has not changed */ | ||
243 | for (i = 0; i < key32; i++) { | 231 | for (i = 0; i < key32; i++) { |
244 | omap_aes_write(dd, AES_REG_KEY(i), | 232 | omap_aes_write(dd, AES_REG_KEY(i), |
245 | __le32_to_cpu(dd->ctx->key[i])); | 233 | __le32_to_cpu(dd->ctx->key[i])); |
246 | } | 234 | } |
247 | dd->ctx->flags &= ~FLAGS_NEW_KEY; | ||
248 | 235 | ||
249 | if (dd->flags & FLAGS_NEW_IV) { | 236 | if ((dd->flags & FLAGS_CBC) && dd->req->info) |
250 | pr_debug("Set IV\n"); | 237 | omap_aes_write_n(dd, AES_REG_IV(0), dd->req->info, 4); |
251 | omap_aes_write_n(dd, AES_REG_IV(0), dd->iv, 4); | 238 | |
252 | dd->flags &= ~FLAGS_NEW_IV; | 239 | val = FLD_VAL(((dd->ctx->keylen >> 3) - 1), 4, 3); |
253 | } | 240 | if (dd->flags & FLAGS_CBC) |
241 | val |= AES_REG_CTRL_CBC; | ||
242 | if (dd->flags & FLAGS_ENCRYPT) | ||
243 | val |= AES_REG_CTRL_DIRECTION; | ||
254 | 244 | ||
255 | mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | | 245 | mask = AES_REG_CTRL_CBC | AES_REG_CTRL_DIRECTION | |
256 | AES_REG_CTRL_KEY_SIZE; | 246 | AES_REG_CTRL_KEY_SIZE; |
257 | 247 | ||
258 | omap_aes_write_mask(dd, AES_REG_CTRL, dd->ctrl, mask); | 248 | omap_aes_write_mask(dd, AES_REG_CTRL, val, mask); |
259 | 249 | ||
260 | out: | 250 | /* IN */ |
261 | /* start DMA or disable idle mode */ | 251 | omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT, |
262 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, | 252 | dd->phys_base + AES_REG_DATA, 0, 4); |
263 | AES_REG_MASK_START); | 253 | |
254 | omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
255 | omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
256 | |||
257 | /* OUT */ | ||
258 | omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT, | ||
259 | dd->phys_base + AES_REG_DATA, 0, 4); | ||
260 | |||
261 | omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
262 | omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
263 | |||
264 | return 0; | ||
264 | } | 265 | } |
265 | 266 | ||
266 | static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx) | 267 | static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx) |
@@ -288,8 +289,16 @@ static void omap_aes_dma_callback(int lch, u16 ch_status, void *data) | |||
288 | { | 289 | { |
289 | struct omap_aes_dev *dd = data; | 290 | struct omap_aes_dev *dd = data; |
290 | 291 | ||
291 | if (lch == dd->dma_lch_out) | 292 | if (ch_status != OMAP_DMA_BLOCK_IRQ) { |
292 | tasklet_schedule(&dd->task); | 293 | pr_err("omap-aes DMA error status: 0x%hx\n", ch_status); |
294 | dd->err = -EIO; | ||
295 | dd->flags &= ~FLAGS_INIT; /* request to re-initialize */ | ||
296 | } else if (lch == dd->dma_lch_in) { | ||
297 | return; | ||
298 | } | ||
299 | |||
300 | /* dma_lch_out - completed */ | ||
301 | tasklet_schedule(&dd->done_task); | ||
293 | } | 302 | } |
294 | 303 | ||
295 | static int omap_aes_dma_init(struct omap_aes_dev *dd) | 304 | static int omap_aes_dma_init(struct omap_aes_dev *dd) |
@@ -339,18 +348,6 @@ static int omap_aes_dma_init(struct omap_aes_dev *dd) | |||
339 | goto err_dma_out; | 348 | goto err_dma_out; |
340 | } | 349 | } |
341 | 350 | ||
342 | omap_set_dma_dest_params(dd->dma_lch_in, 0, OMAP_DMA_AMODE_CONSTANT, | ||
343 | dd->phys_base + AES_REG_DATA, 0, 4); | ||
344 | |||
345 | omap_set_dma_dest_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
346 | omap_set_dma_src_burst_mode(dd->dma_lch_in, OMAP_DMA_DATA_BURST_4); | ||
347 | |||
348 | omap_set_dma_src_params(dd->dma_lch_out, 0, OMAP_DMA_AMODE_CONSTANT, | ||
349 | dd->phys_base + AES_REG_DATA, 0, 4); | ||
350 | |||
351 | omap_set_dma_src_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
352 | omap_set_dma_dest_burst_mode(dd->dma_lch_out, OMAP_DMA_DATA_BURST_4); | ||
353 | |||
354 | return 0; | 351 | return 0; |
355 | 352 | ||
356 | err_dma_out: | 353 | err_dma_out: |
@@ -406,6 +403,11 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf, | |||
406 | if (!count) | 403 | if (!count) |
407 | return off; | 404 | return off; |
408 | 405 | ||
406 | /* | ||
407 | * buflen and total are AES_BLOCK_SIZE size aligned, | ||
408 | * so count should be also aligned | ||
409 | */ | ||
410 | |||
409 | sg_copy_buf(buf + off, *sg, *offset, count, out); | 411 | sg_copy_buf(buf + off, *sg, *offset, count, out); |
410 | 412 | ||
411 | off += count; | 413 | off += count; |
@@ -461,7 +463,9 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm, dma_addr_t dma_addr_in, | |||
461 | omap_start_dma(dd->dma_lch_in); | 463 | omap_start_dma(dd->dma_lch_in); |
462 | omap_start_dma(dd->dma_lch_out); | 464 | omap_start_dma(dd->dma_lch_out); |
463 | 465 | ||
464 | omap_aes_write_ctrl(dd); | 466 | /* start DMA or disable idle mode */ |
467 | omap_aes_write_mask(dd, AES_REG_MASK, AES_REG_MASK_START, | ||
468 | AES_REG_MASK_START); | ||
465 | 469 | ||
466 | return 0; | 470 | return 0; |
467 | } | 471 | } |
@@ -488,8 +492,10 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) | |||
488 | count = min(dd->total, sg_dma_len(dd->in_sg)); | 492 | count = min(dd->total, sg_dma_len(dd->in_sg)); |
489 | count = min(count, sg_dma_len(dd->out_sg)); | 493 | count = min(count, sg_dma_len(dd->out_sg)); |
490 | 494 | ||
491 | if (count != dd->total) | 495 | if (count != dd->total) { |
496 | pr_err("request length != buffer length\n"); | ||
492 | return -EINVAL; | 497 | return -EINVAL; |
498 | } | ||
493 | 499 | ||
494 | pr_debug("fast\n"); | 500 | pr_debug("fast\n"); |
495 | 501 | ||
@@ -525,23 +531,25 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) | |||
525 | 531 | ||
526 | dd->total -= count; | 532 | dd->total -= count; |
527 | 533 | ||
528 | err = omap_aes_hw_init(dd); | ||
529 | |||
530 | err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count); | 534 | err = omap_aes_crypt_dma(tfm, addr_in, addr_out, count); |
535 | if (err) { | ||
536 | dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE); | ||
537 | dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE); | ||
538 | } | ||
531 | 539 | ||
532 | return err; | 540 | return err; |
533 | } | 541 | } |
534 | 542 | ||
535 | static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) | 543 | static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) |
536 | { | 544 | { |
537 | struct omap_aes_ctx *ctx; | 545 | struct ablkcipher_request *req = dd->req; |
538 | 546 | ||
539 | pr_debug("err: %d\n", err); | 547 | pr_debug("err: %d\n", err); |
540 | 548 | ||
541 | ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(dd->req)); | 549 | clk_disable(dd->iclk); |
550 | dd->flags &= ~FLAGS_BUSY; | ||
542 | 551 | ||
543 | if (!dd->total) | 552 | req->base.complete(&req->base, err); |
544 | dd->req->base.complete(&dd->req->base, err); | ||
545 | } | 553 | } |
546 | 554 | ||
547 | static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) | 555 | static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) |
@@ -553,8 +561,6 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) | |||
553 | 561 | ||
554 | omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); | 562 | omap_aes_write_mask(dd, AES_REG_MASK, 0, AES_REG_MASK_START); |
555 | 563 | ||
556 | omap_aes_hw_cleanup(dd); | ||
557 | |||
558 | omap_stop_dma(dd->dma_lch_in); | 564 | omap_stop_dma(dd->dma_lch_in); |
559 | omap_stop_dma(dd->dma_lch_out); | 565 | omap_stop_dma(dd->dma_lch_out); |
560 | 566 | ||
@@ -574,40 +580,39 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) | |||
574 | } | 580 | } |
575 | } | 581 | } |
576 | 582 | ||
577 | if (err || !dd->total) | ||
578 | omap_aes_finish_req(dd, err); | ||
579 | |||
580 | return err; | 583 | return err; |
581 | } | 584 | } |
582 | 585 | ||
583 | static int omap_aes_handle_req(struct omap_aes_dev *dd) | 586 | static int omap_aes_handle_queue(struct omap_aes_dev *dd, |
587 | struct ablkcipher_request *req) | ||
584 | { | 588 | { |
585 | struct crypto_async_request *async_req, *backlog; | 589 | struct crypto_async_request *async_req, *backlog; |
586 | struct omap_aes_ctx *ctx; | 590 | struct omap_aes_ctx *ctx; |
587 | struct omap_aes_reqctx *rctx; | 591 | struct omap_aes_reqctx *rctx; |
588 | struct ablkcipher_request *req; | ||
589 | unsigned long flags; | 592 | unsigned long flags; |
590 | 593 | int err, ret = 0; | |
591 | if (dd->total) | ||
592 | goto start; | ||
593 | 594 | ||
594 | spin_lock_irqsave(&dd->lock, flags); | 595 | spin_lock_irqsave(&dd->lock, flags); |
596 | if (req) | ||
597 | ret = ablkcipher_enqueue_request(&dd->queue, req); | ||
598 | if (dd->flags & FLAGS_BUSY) { | ||
599 | spin_unlock_irqrestore(&dd->lock, flags); | ||
600 | return ret; | ||
601 | } | ||
595 | backlog = crypto_get_backlog(&dd->queue); | 602 | backlog = crypto_get_backlog(&dd->queue); |
596 | async_req = crypto_dequeue_request(&dd->queue); | 603 | async_req = crypto_dequeue_request(&dd->queue); |
597 | if (!async_req) | 604 | if (async_req) |
598 | clear_bit(FLAGS_BUSY, &dd->flags); | 605 | dd->flags |= FLAGS_BUSY; |
599 | spin_unlock_irqrestore(&dd->lock, flags); | 606 | spin_unlock_irqrestore(&dd->lock, flags); |
600 | 607 | ||
601 | if (!async_req) | 608 | if (!async_req) |
602 | return 0; | 609 | return ret; |
603 | 610 | ||
604 | if (backlog) | 611 | if (backlog) |
605 | backlog->complete(backlog, -EINPROGRESS); | 612 | backlog->complete(backlog, -EINPROGRESS); |
606 | 613 | ||
607 | req = ablkcipher_request_cast(async_req); | 614 | req = ablkcipher_request_cast(async_req); |
608 | 615 | ||
609 | pr_debug("get new req\n"); | ||
610 | |||
611 | /* assign new request to device */ | 616 | /* assign new request to device */ |
612 | dd->req = req; | 617 | dd->req = req; |
613 | dd->total = req->nbytes; | 618 | dd->total = req->nbytes; |
@@ -621,27 +626,22 @@ static int omap_aes_handle_req(struct omap_aes_dev *dd) | |||
621 | rctx->mode &= FLAGS_MODE_MASK; | 626 | rctx->mode &= FLAGS_MODE_MASK; |
622 | dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; | 627 | dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; |
623 | 628 | ||
624 | dd->iv = req->info; | 629 | dd->ctx = ctx; |
625 | if ((dd->flags & FLAGS_CBC) && dd->iv) | ||
626 | dd->flags |= FLAGS_NEW_IV; | ||
627 | else | ||
628 | dd->flags &= ~FLAGS_NEW_IV; | ||
629 | |||
630 | ctx->dd = dd; | 630 | ctx->dd = dd; |
631 | if (dd->ctx != ctx) { | ||
632 | /* assign new context to device */ | ||
633 | dd->ctx = ctx; | ||
634 | ctx->flags |= FLAGS_NEW_KEY; | ||
635 | } | ||
636 | 631 | ||
637 | if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) | 632 | err = omap_aes_write_ctrl(dd); |
638 | pr_err("request size is not exact amount of AES blocks\n"); | 633 | if (!err) |
634 | err = omap_aes_crypt_dma_start(dd); | ||
635 | if (err) { | ||
636 | /* aes_task will not finish it, so do it here */ | ||
637 | omap_aes_finish_req(dd, err); | ||
638 | tasklet_schedule(&dd->queue_task); | ||
639 | } | ||
639 | 640 | ||
640 | start: | 641 | return ret; /* return ret, which is enqueue return value */ |
641 | return omap_aes_crypt_dma_start(dd); | ||
642 | } | 642 | } |
643 | 643 | ||
644 | static void omap_aes_task(unsigned long data) | 644 | static void omap_aes_done_task(unsigned long data) |
645 | { | 645 | { |
646 | struct omap_aes_dev *dd = (struct omap_aes_dev *)data; | 646 | struct omap_aes_dev *dd = (struct omap_aes_dev *)data; |
647 | int err; | 647 | int err; |
@@ -650,40 +650,50 @@ static void omap_aes_task(unsigned long data) | |||
650 | 650 | ||
651 | err = omap_aes_crypt_dma_stop(dd); | 651 | err = omap_aes_crypt_dma_stop(dd); |
652 | 652 | ||
653 | err = omap_aes_handle_req(dd); | 653 | err = dd->err ? : err; |
654 | |||
655 | if (dd->total && !err) { | ||
656 | err = omap_aes_crypt_dma_start(dd); | ||
657 | if (!err) | ||
658 | return; /* DMA started. Not fininishing. */ | ||
659 | } | ||
660 | |||
661 | omap_aes_finish_req(dd, err); | ||
662 | omap_aes_handle_queue(dd, NULL); | ||
654 | 663 | ||
655 | pr_debug("exit\n"); | 664 | pr_debug("exit\n"); |
656 | } | 665 | } |
657 | 666 | ||
667 | static void omap_aes_queue_task(unsigned long data) | ||
668 | { | ||
669 | struct omap_aes_dev *dd = (struct omap_aes_dev *)data; | ||
670 | |||
671 | omap_aes_handle_queue(dd, NULL); | ||
672 | } | ||
673 | |||
658 | static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) | 674 | static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) |
659 | { | 675 | { |
660 | struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( | 676 | struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( |
661 | crypto_ablkcipher_reqtfm(req)); | 677 | crypto_ablkcipher_reqtfm(req)); |
662 | struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); | 678 | struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req); |
663 | struct omap_aes_dev *dd; | 679 | struct omap_aes_dev *dd; |
664 | unsigned long flags; | ||
665 | int err; | ||
666 | 680 | ||
667 | pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, | 681 | pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes, |
668 | !!(mode & FLAGS_ENCRYPT), | 682 | !!(mode & FLAGS_ENCRYPT), |
669 | !!(mode & FLAGS_CBC)); | 683 | !!(mode & FLAGS_CBC)); |
670 | 684 | ||
685 | if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { | ||
686 | pr_err("request size is not exact amount of AES blocks\n"); | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
671 | dd = omap_aes_find_dev(ctx); | 690 | dd = omap_aes_find_dev(ctx); |
672 | if (!dd) | 691 | if (!dd) |
673 | return -ENODEV; | 692 | return -ENODEV; |
674 | 693 | ||
675 | rctx->mode = mode; | 694 | rctx->mode = mode; |
676 | 695 | ||
677 | spin_lock_irqsave(&dd->lock, flags); | 696 | return omap_aes_handle_queue(dd, req); |
678 | err = ablkcipher_enqueue_request(&dd->queue, req); | ||
679 | spin_unlock_irqrestore(&dd->lock, flags); | ||
680 | |||
681 | if (!test_and_set_bit(FLAGS_BUSY, &dd->flags)) | ||
682 | omap_aes_handle_req(dd); | ||
683 | |||
684 | pr_debug("exit\n"); | ||
685 | |||
686 | return err; | ||
687 | } | 697 | } |
688 | 698 | ||
689 | /* ********************** ALG API ************************************ */ | 699 | /* ********************** ALG API ************************************ */ |
@@ -701,7 +711,6 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, | |||
701 | 711 | ||
702 | memcpy(ctx->key, key, keylen); | 712 | memcpy(ctx->key, key, keylen); |
703 | ctx->keylen = keylen; | 713 | ctx->keylen = keylen; |
704 | ctx->flags |= FLAGS_NEW_KEY; | ||
705 | 714 | ||
706 | return 0; | 715 | return 0; |
707 | } | 716 | } |
@@ -750,7 +759,7 @@ static struct crypto_alg algs[] = { | |||
750 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | 759 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, |
751 | .cra_blocksize = AES_BLOCK_SIZE, | 760 | .cra_blocksize = AES_BLOCK_SIZE, |
752 | .cra_ctxsize = sizeof(struct omap_aes_ctx), | 761 | .cra_ctxsize = sizeof(struct omap_aes_ctx), |
753 | .cra_alignmask = 0, | 762 | .cra_alignmask = 0, |
754 | .cra_type = &crypto_ablkcipher_type, | 763 | .cra_type = &crypto_ablkcipher_type, |
755 | .cra_module = THIS_MODULE, | 764 | .cra_module = THIS_MODULE, |
756 | .cra_init = omap_aes_cra_init, | 765 | .cra_init = omap_aes_cra_init, |
@@ -770,7 +779,7 @@ static struct crypto_alg algs[] = { | |||
770 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, | 779 | .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, |
771 | .cra_blocksize = AES_BLOCK_SIZE, | 780 | .cra_blocksize = AES_BLOCK_SIZE, |
772 | .cra_ctxsize = sizeof(struct omap_aes_ctx), | 781 | .cra_ctxsize = sizeof(struct omap_aes_ctx), |
773 | .cra_alignmask = 0, | 782 | .cra_alignmask = 0, |
774 | .cra_type = &crypto_ablkcipher_type, | 783 | .cra_type = &crypto_ablkcipher_type, |
775 | .cra_module = THIS_MODULE, | 784 | .cra_module = THIS_MODULE, |
776 | .cra_init = omap_aes_cra_init, | 785 | .cra_init = omap_aes_cra_init, |
@@ -849,7 +858,8 @@ static int omap_aes_probe(struct platform_device *pdev) | |||
849 | (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR); | 858 | (reg & AES_REG_REV_MAJOR) >> 4, reg & AES_REG_REV_MINOR); |
850 | clk_disable(dd->iclk); | 859 | clk_disable(dd->iclk); |
851 | 860 | ||
852 | tasklet_init(&dd->task, omap_aes_task, (unsigned long)dd); | 861 | tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd); |
862 | tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd); | ||
853 | 863 | ||
854 | err = omap_aes_dma_init(dd); | 864 | err = omap_aes_dma_init(dd); |
855 | if (err) | 865 | if (err) |
@@ -876,7 +886,8 @@ err_algs: | |||
876 | crypto_unregister_alg(&algs[j]); | 886 | crypto_unregister_alg(&algs[j]); |
877 | omap_aes_dma_cleanup(dd); | 887 | omap_aes_dma_cleanup(dd); |
878 | err_dma: | 888 | err_dma: |
879 | tasklet_kill(&dd->task); | 889 | tasklet_kill(&dd->done_task); |
890 | tasklet_kill(&dd->queue_task); | ||
880 | iounmap(dd->io_base); | 891 | iounmap(dd->io_base); |
881 | err_io: | 892 | err_io: |
882 | clk_put(dd->iclk); | 893 | clk_put(dd->iclk); |
@@ -903,7 +914,8 @@ static int omap_aes_remove(struct platform_device *pdev) | |||
903 | for (i = 0; i < ARRAY_SIZE(algs); i++) | 914 | for (i = 0; i < ARRAY_SIZE(algs); i++) |
904 | crypto_unregister_alg(&algs[i]); | 915 | crypto_unregister_alg(&algs[i]); |
905 | 916 | ||
906 | tasklet_kill(&dd->task); | 917 | tasklet_kill(&dd->done_task); |
918 | tasklet_kill(&dd->queue_task); | ||
907 | omap_aes_dma_cleanup(dd); | 919 | omap_aes_dma_cleanup(dd); |
908 | iounmap(dd->io_base); | 920 | iounmap(dd->io_base); |
909 | clk_put(dd->iclk); | 921 | clk_put(dd->iclk); |
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index a081c7c7d03f..2e71123516e0 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c | |||
@@ -72,10 +72,9 @@ | |||
72 | 72 | ||
73 | #define DEFAULT_TIMEOUT_INTERVAL HZ | 73 | #define DEFAULT_TIMEOUT_INTERVAL HZ |
74 | 74 | ||
75 | #define FLAGS_FIRST 0x0001 | ||
76 | #define FLAGS_FINUP 0x0002 | 75 | #define FLAGS_FINUP 0x0002 |
77 | #define FLAGS_FINAL 0x0004 | 76 | #define FLAGS_FINAL 0x0004 |
78 | #define FLAGS_FAST 0x0008 | 77 | #define FLAGS_SG 0x0008 |
79 | #define FLAGS_SHA1 0x0010 | 78 | #define FLAGS_SHA1 0x0010 |
80 | #define FLAGS_DMA_ACTIVE 0x0020 | 79 | #define FLAGS_DMA_ACTIVE 0x0020 |
81 | #define FLAGS_OUTPUT_READY 0x0040 | 80 | #define FLAGS_OUTPUT_READY 0x0040 |
@@ -83,13 +82,17 @@ | |||
83 | #define FLAGS_INIT 0x0100 | 82 | #define FLAGS_INIT 0x0100 |
84 | #define FLAGS_CPU 0x0200 | 83 | #define FLAGS_CPU 0x0200 |
85 | #define FLAGS_HMAC 0x0400 | 84 | #define FLAGS_HMAC 0x0400 |
86 | 85 | #define FLAGS_ERROR 0x0800 | |
87 | /* 3rd byte */ | 86 | #define FLAGS_BUSY 0x1000 |
88 | #define FLAGS_BUSY 16 | ||
89 | 87 | ||
90 | #define OP_UPDATE 1 | 88 | #define OP_UPDATE 1 |
91 | #define OP_FINAL 2 | 89 | #define OP_FINAL 2 |
92 | 90 | ||
91 | #define OMAP_ALIGN_MASK (sizeof(u32)-1) | ||
92 | #define OMAP_ALIGNED __attribute__((aligned(sizeof(u32)))) | ||
93 | |||
94 | #define BUFLEN PAGE_SIZE | ||
95 | |||
93 | struct omap_sham_dev; | 96 | struct omap_sham_dev; |
94 | 97 | ||
95 | struct omap_sham_reqctx { | 98 | struct omap_sham_reqctx { |
@@ -97,8 +100,8 @@ struct omap_sham_reqctx { | |||
97 | unsigned long flags; | 100 | unsigned long flags; |
98 | unsigned long op; | 101 | unsigned long op; |
99 | 102 | ||
103 | u8 digest[SHA1_DIGEST_SIZE] OMAP_ALIGNED; | ||
100 | size_t digcnt; | 104 | size_t digcnt; |
101 | u8 *buffer; | ||
102 | size_t bufcnt; | 105 | size_t bufcnt; |
103 | size_t buflen; | 106 | size_t buflen; |
104 | dma_addr_t dma_addr; | 107 | dma_addr_t dma_addr; |
@@ -107,6 +110,8 @@ struct omap_sham_reqctx { | |||
107 | struct scatterlist *sg; | 110 | struct scatterlist *sg; |
108 | unsigned int offset; /* offset in current sg */ | 111 | unsigned int offset; /* offset in current sg */ |
109 | unsigned int total; /* total request */ | 112 | unsigned int total; /* total request */ |
113 | |||
114 | u8 buffer[0] OMAP_ALIGNED; | ||
110 | }; | 115 | }; |
111 | 116 | ||
112 | struct omap_sham_hmac_ctx { | 117 | struct omap_sham_hmac_ctx { |
@@ -136,6 +141,7 @@ struct omap_sham_dev { | |||
136 | int irq; | 141 | int irq; |
137 | struct clk *iclk; | 142 | struct clk *iclk; |
138 | spinlock_t lock; | 143 | spinlock_t lock; |
144 | int err; | ||
139 | int dma; | 145 | int dma; |
140 | int dma_lch; | 146 | int dma_lch; |
141 | struct tasklet_struct done_task; | 147 | struct tasklet_struct done_task; |
@@ -194,53 +200,68 @@ static inline int omap_sham_wait(struct omap_sham_dev *dd, u32 offset, u32 bit) | |||
194 | static void omap_sham_copy_hash(struct ahash_request *req, int out) | 200 | static void omap_sham_copy_hash(struct ahash_request *req, int out) |
195 | { | 201 | { |
196 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | 202 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); |
203 | u32 *hash = (u32 *)ctx->digest; | ||
204 | int i; | ||
205 | |||
206 | /* MD5 is almost unused. So copy sha1 size to reduce code */ | ||
207 | for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) { | ||
208 | if (out) | ||
209 | hash[i] = omap_sham_read(ctx->dd, | ||
210 | SHA_REG_DIGEST(i)); | ||
211 | else | ||
212 | omap_sham_write(ctx->dd, | ||
213 | SHA_REG_DIGEST(i), hash[i]); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | static void omap_sham_copy_ready_hash(struct ahash_request *req) | ||
218 | { | ||
219 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | ||
220 | u32 *in = (u32 *)ctx->digest; | ||
197 | u32 *hash = (u32 *)req->result; | 221 | u32 *hash = (u32 *)req->result; |
198 | int i; | 222 | int i; |
199 | 223 | ||
224 | if (!hash) | ||
225 | return; | ||
226 | |||
200 | if (likely(ctx->flags & FLAGS_SHA1)) { | 227 | if (likely(ctx->flags & FLAGS_SHA1)) { |
201 | /* SHA1 results are in big endian */ | 228 | /* SHA1 results are in big endian */ |
202 | for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) | 229 | for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) |
203 | if (out) | 230 | hash[i] = be32_to_cpu(in[i]); |
204 | hash[i] = be32_to_cpu(omap_sham_read(ctx->dd, | ||
205 | SHA_REG_DIGEST(i))); | ||
206 | else | ||
207 | omap_sham_write(ctx->dd, SHA_REG_DIGEST(i), | ||
208 | cpu_to_be32(hash[i])); | ||
209 | } else { | 231 | } else { |
210 | /* MD5 results are in little endian */ | 232 | /* MD5 results are in little endian */ |
211 | for (i = 0; i < MD5_DIGEST_SIZE / sizeof(u32); i++) | 233 | for (i = 0; i < MD5_DIGEST_SIZE / sizeof(u32); i++) |
212 | if (out) | 234 | hash[i] = le32_to_cpu(in[i]); |
213 | hash[i] = le32_to_cpu(omap_sham_read(ctx->dd, | ||
214 | SHA_REG_DIGEST(i))); | ||
215 | else | ||
216 | omap_sham_write(ctx->dd, SHA_REG_DIGEST(i), | ||
217 | cpu_to_le32(hash[i])); | ||
218 | } | 235 | } |
219 | } | 236 | } |
220 | 237 | ||
221 | static int omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length, | 238 | static int omap_sham_hw_init(struct omap_sham_dev *dd) |
222 | int final, int dma) | ||
223 | { | 239 | { |
224 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | 240 | clk_enable(dd->iclk); |
225 | u32 val = length << 5, mask; | ||
226 | 241 | ||
227 | if (unlikely(!ctx->digcnt)) { | 242 | if (!(dd->flags & FLAGS_INIT)) { |
243 | omap_sham_write_mask(dd, SHA_REG_MASK, | ||
244 | SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET); | ||
228 | 245 | ||
229 | clk_enable(dd->iclk); | 246 | if (omap_sham_wait(dd, SHA_REG_SYSSTATUS, |
247 | SHA_REG_SYSSTATUS_RESETDONE)) | ||
248 | return -ETIMEDOUT; | ||
230 | 249 | ||
231 | if (!(dd->flags & FLAGS_INIT)) { | 250 | dd->flags |= FLAGS_INIT; |
232 | omap_sham_write_mask(dd, SHA_REG_MASK, | 251 | dd->err = 0; |
233 | SHA_REG_MASK_SOFTRESET, SHA_REG_MASK_SOFTRESET); | 252 | } |
234 | 253 | ||
235 | if (omap_sham_wait(dd, SHA_REG_SYSSTATUS, | 254 | return 0; |
236 | SHA_REG_SYSSTATUS_RESETDONE)) | 255 | } |
237 | return -ETIMEDOUT; | ||
238 | 256 | ||
239 | dd->flags |= FLAGS_INIT; | 257 | static void omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length, |
240 | } | 258 | int final, int dma) |
241 | } else { | 259 | { |
260 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | ||
261 | u32 val = length << 5, mask; | ||
262 | |||
263 | if (likely(ctx->digcnt)) | ||
242 | omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt); | 264 | omap_sham_write(dd, SHA_REG_DIGCNT, ctx->digcnt); |
243 | } | ||
244 | 265 | ||
245 | omap_sham_write_mask(dd, SHA_REG_MASK, | 266 | omap_sham_write_mask(dd, SHA_REG_MASK, |
246 | SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0), | 267 | SHA_REG_MASK_IT_EN | (dma ? SHA_REG_MASK_DMA_EN : 0), |
@@ -260,29 +281,26 @@ static int omap_sham_write_ctrl(struct omap_sham_dev *dd, size_t length, | |||
260 | SHA_REG_CTRL_ALGO | SHA_REG_CTRL_LENGTH; | 281 | SHA_REG_CTRL_ALGO | SHA_REG_CTRL_LENGTH; |
261 | 282 | ||
262 | omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask); | 283 | omap_sham_write_mask(dd, SHA_REG_CTRL, val, mask); |
263 | |||
264 | return 0; | ||
265 | } | 284 | } |
266 | 285 | ||
267 | static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf, | 286 | static int omap_sham_xmit_cpu(struct omap_sham_dev *dd, const u8 *buf, |
268 | size_t length, int final) | 287 | size_t length, int final) |
269 | { | 288 | { |
270 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | 289 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); |
271 | int err, count, len32; | 290 | int count, len32; |
272 | const u32 *buffer = (const u32 *)buf; | 291 | const u32 *buffer = (const u32 *)buf; |
273 | 292 | ||
274 | dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n", | 293 | dev_dbg(dd->dev, "xmit_cpu: digcnt: %d, length: %d, final: %d\n", |
275 | ctx->digcnt, length, final); | 294 | ctx->digcnt, length, final); |
276 | 295 | ||
277 | err = omap_sham_write_ctrl(dd, length, final, 0); | 296 | omap_sham_write_ctrl(dd, length, final, 0); |
278 | if (err) | 297 | |
279 | return err; | 298 | /* should be non-zero before next lines to disable clocks later */ |
299 | ctx->digcnt += length; | ||
280 | 300 | ||
281 | if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY)) | 301 | if (omap_sham_wait(dd, SHA_REG_CTRL, SHA_REG_CTRL_INPUT_READY)) |
282 | return -ETIMEDOUT; | 302 | return -ETIMEDOUT; |
283 | 303 | ||
284 | ctx->digcnt += length; | ||
285 | |||
286 | if (final) | 304 | if (final) |
287 | ctx->flags |= FLAGS_FINAL; /* catch last interrupt */ | 305 | ctx->flags |= FLAGS_FINAL; /* catch last interrupt */ |
288 | 306 | ||
@@ -298,16 +316,11 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr, | |||
298 | size_t length, int final) | 316 | size_t length, int final) |
299 | { | 317 | { |
300 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | 318 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); |
301 | int err, len32; | 319 | int len32; |
302 | 320 | ||
303 | dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n", | 321 | dev_dbg(dd->dev, "xmit_dma: digcnt: %d, length: %d, final: %d\n", |
304 | ctx->digcnt, length, final); | 322 | ctx->digcnt, length, final); |
305 | 323 | ||
306 | /* flush cache entries related to our page */ | ||
307 | if (dma_addr == ctx->dma_addr) | ||
308 | dma_sync_single_for_device(dd->dev, dma_addr, length, | ||
309 | DMA_TO_DEVICE); | ||
310 | |||
311 | len32 = DIV_ROUND_UP(length, sizeof(u32)); | 324 | len32 = DIV_ROUND_UP(length, sizeof(u32)); |
312 | 325 | ||
313 | omap_set_dma_transfer_params(dd->dma_lch, OMAP_DMA_DATA_TYPE_S32, len32, | 326 | omap_set_dma_transfer_params(dd->dma_lch, OMAP_DMA_DATA_TYPE_S32, len32, |
@@ -317,9 +330,7 @@ static int omap_sham_xmit_dma(struct omap_sham_dev *dd, dma_addr_t dma_addr, | |||
317 | omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC, | 330 | omap_set_dma_src_params(dd->dma_lch, 0, OMAP_DMA_AMODE_POST_INC, |
318 | dma_addr, 0, 0); | 331 | dma_addr, 0, 0); |
319 | 332 | ||
320 | err = omap_sham_write_ctrl(dd, length, final, 1); | 333 | omap_sham_write_ctrl(dd, length, final, 1); |
321 | if (err) | ||
322 | return err; | ||
323 | 334 | ||
324 | ctx->digcnt += length; | 335 | ctx->digcnt += length; |
325 | 336 | ||
@@ -371,15 +382,29 @@ static size_t omap_sham_append_sg(struct omap_sham_reqctx *ctx) | |||
371 | return 0; | 382 | return 0; |
372 | } | 383 | } |
373 | 384 | ||
385 | static int omap_sham_xmit_dma_map(struct omap_sham_dev *dd, | ||
386 | struct omap_sham_reqctx *ctx, | ||
387 | size_t length, int final) | ||
388 | { | ||
389 | ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, ctx->buflen, | ||
390 | DMA_TO_DEVICE); | ||
391 | if (dma_mapping_error(dd->dev, ctx->dma_addr)) { | ||
392 | dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen); | ||
393 | return -EINVAL; | ||
394 | } | ||
395 | |||
396 | ctx->flags &= ~FLAGS_SG; | ||
397 | |||
398 | /* next call does not fail... so no unmap in the case of error */ | ||
399 | return omap_sham_xmit_dma(dd, ctx->dma_addr, length, final); | ||
400 | } | ||
401 | |||
374 | static int omap_sham_update_dma_slow(struct omap_sham_dev *dd) | 402 | static int omap_sham_update_dma_slow(struct omap_sham_dev *dd) |
375 | { | 403 | { |
376 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | 404 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); |
377 | unsigned int final; | 405 | unsigned int final; |
378 | size_t count; | 406 | size_t count; |
379 | 407 | ||
380 | if (!ctx->total) | ||
381 | return 0; | ||
382 | |||
383 | omap_sham_append_sg(ctx); | 408 | omap_sham_append_sg(ctx); |
384 | 409 | ||
385 | final = (ctx->flags & FLAGS_FINUP) && !ctx->total; | 410 | final = (ctx->flags & FLAGS_FINUP) && !ctx->total; |
@@ -390,30 +415,68 @@ static int omap_sham_update_dma_slow(struct omap_sham_dev *dd) | |||
390 | if (final || (ctx->bufcnt == ctx->buflen && ctx->total)) { | 415 | if (final || (ctx->bufcnt == ctx->buflen && ctx->total)) { |
391 | count = ctx->bufcnt; | 416 | count = ctx->bufcnt; |
392 | ctx->bufcnt = 0; | 417 | ctx->bufcnt = 0; |
393 | return omap_sham_xmit_dma(dd, ctx->dma_addr, count, final); | 418 | return omap_sham_xmit_dma_map(dd, ctx, count, final); |
394 | } | 419 | } |
395 | 420 | ||
396 | return 0; | 421 | return 0; |
397 | } | 422 | } |
398 | 423 | ||
399 | static int omap_sham_update_dma_fast(struct omap_sham_dev *dd) | 424 | /* Start address alignment */ |
425 | #define SG_AA(sg) (IS_ALIGNED(sg->offset, sizeof(u32))) | ||
426 | /* SHA1 block size alignment */ | ||
427 | #define SG_SA(sg) (IS_ALIGNED(sg->length, SHA1_MD5_BLOCK_SIZE)) | ||
428 | |||
429 | static int omap_sham_update_dma_start(struct omap_sham_dev *dd) | ||
400 | { | 430 | { |
401 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | 431 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); |
402 | unsigned int length; | 432 | unsigned int length, final, tail; |
433 | struct scatterlist *sg; | ||
403 | 434 | ||
404 | ctx->flags |= FLAGS_FAST; | 435 | if (!ctx->total) |
436 | return 0; | ||
437 | |||
438 | if (ctx->bufcnt || ctx->offset) | ||
439 | return omap_sham_update_dma_slow(dd); | ||
440 | |||
441 | dev_dbg(dd->dev, "fast: digcnt: %d, bufcnt: %u, total: %u\n", | ||
442 | ctx->digcnt, ctx->bufcnt, ctx->total); | ||
443 | |||
444 | sg = ctx->sg; | ||
405 | 445 | ||
406 | length = min(ctx->total, sg_dma_len(ctx->sg)); | 446 | if (!SG_AA(sg)) |
407 | ctx->total = length; | 447 | return omap_sham_update_dma_slow(dd); |
448 | |||
449 | if (!sg_is_last(sg) && !SG_SA(sg)) | ||
450 | /* size is not SHA1_BLOCK_SIZE aligned */ | ||
451 | return omap_sham_update_dma_slow(dd); | ||
452 | |||
453 | length = min(ctx->total, sg->length); | ||
454 | |||
455 | if (sg_is_last(sg)) { | ||
456 | if (!(ctx->flags & FLAGS_FINUP)) { | ||
457 | /* not last sg must be SHA1_MD5_BLOCK_SIZE aligned */ | ||
458 | tail = length & (SHA1_MD5_BLOCK_SIZE - 1); | ||
459 | /* without finup() we need one block to close hash */ | ||
460 | if (!tail) | ||
461 | tail = SHA1_MD5_BLOCK_SIZE; | ||
462 | length -= tail; | ||
463 | } | ||
464 | } | ||
408 | 465 | ||
409 | if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) { | 466 | if (!dma_map_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE)) { |
410 | dev_err(dd->dev, "dma_map_sg error\n"); | 467 | dev_err(dd->dev, "dma_map_sg error\n"); |
411 | return -EINVAL; | 468 | return -EINVAL; |
412 | } | 469 | } |
413 | 470 | ||
471 | ctx->flags |= FLAGS_SG; | ||
472 | |||
414 | ctx->total -= length; | 473 | ctx->total -= length; |
474 | ctx->offset = length; /* offset where to start slow */ | ||
415 | 475 | ||
416 | return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, 1); | 476 | final = (ctx->flags & FLAGS_FINUP) && !ctx->total; |
477 | |||
478 | /* next call does not fail... so no unmap in the case of error */ | ||
479 | return omap_sham_xmit_dma(dd, sg_dma_address(ctx->sg), length, final); | ||
417 | } | 480 | } |
418 | 481 | ||
419 | static int omap_sham_update_cpu(struct omap_sham_dev *dd) | 482 | static int omap_sham_update_cpu(struct omap_sham_dev *dd) |
@@ -433,8 +496,17 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd) | |||
433 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); | 496 | struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req); |
434 | 497 | ||
435 | omap_stop_dma(dd->dma_lch); | 498 | omap_stop_dma(dd->dma_lch); |
436 | if (ctx->flags & FLAGS_FAST) | 499 | if (ctx->flags & FLAGS_SG) { |
437 | dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE); | 500 | dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE); |
501 | if (ctx->sg->length == ctx->offset) { | ||
502 | ctx->sg = sg_next(ctx->sg); | ||
503 | if (ctx->sg) | ||
504 | ctx->offset = 0; | ||
505 | } | ||
506 | } else { | ||
507 | dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen, | ||
508 | DMA_TO_DEVICE); | ||
509 | } | ||
438 | 510 | ||
439 | return 0; | 511 | return 0; |
440 | } | 512 | } |
@@ -454,14 +526,7 @@ static void omap_sham_cleanup(struct ahash_request *req) | |||
454 | spin_unlock_irqrestore(&dd->lock, flags); | 526 | spin_unlock_irqrestore(&dd->lock, flags); |
455 | 527 | ||
456 | if (ctx->digcnt) | 528 | if (ctx->digcnt) |
457 | clk_disable(dd->iclk); | 529 | omap_sham_copy_ready_hash(req); |
458 | |||
459 | if (ctx->dma_addr) | ||
460 | dma_unmap_single(dd->dev, ctx->dma_addr, ctx->buflen, | ||
461 | DMA_TO_DEVICE); | ||
462 | |||
463 | if (ctx->buffer) | ||
464 | free_page((unsigned long)ctx->buffer); | ||
465 | 530 | ||
466 | dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, ctx->bufcnt); | 531 | dev_dbg(dd->dev, "digcnt: %d, bufcnt: %d\n", ctx->digcnt, ctx->bufcnt); |
467 | } | 532 | } |
@@ -489,8 +554,6 @@ static int omap_sham_init(struct ahash_request *req) | |||
489 | 554 | ||
490 | ctx->flags = 0; | 555 | ctx->flags = 0; |
491 | 556 | ||
492 | ctx->flags |= FLAGS_FIRST; | ||
493 | |||
494 | dev_dbg(dd->dev, "init: digest size: %d\n", | 557 | dev_dbg(dd->dev, "init: digest size: %d\n", |
495 | crypto_ahash_digestsize(tfm)); | 558 | crypto_ahash_digestsize(tfm)); |
496 | 559 | ||
@@ -499,21 +562,7 @@ static int omap_sham_init(struct ahash_request *req) | |||
499 | 562 | ||
500 | ctx->bufcnt = 0; | 563 | ctx->bufcnt = 0; |
501 | ctx->digcnt = 0; | 564 | ctx->digcnt = 0; |
502 | 565 | ctx->buflen = BUFLEN; | |
503 | ctx->buflen = PAGE_SIZE; | ||
504 | ctx->buffer = (void *)__get_free_page( | ||
505 | (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? | ||
506 | GFP_KERNEL : GFP_ATOMIC); | ||
507 | if (!ctx->buffer) | ||
508 | return -ENOMEM; | ||
509 | |||
510 | ctx->dma_addr = dma_map_single(dd->dev, ctx->buffer, ctx->buflen, | ||
511 | DMA_TO_DEVICE); | ||
512 | if (dma_mapping_error(dd->dev, ctx->dma_addr)) { | ||
513 | dev_err(dd->dev, "dma %u bytes error\n", ctx->buflen); | ||
514 | free_page((unsigned long)ctx->buffer); | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | 566 | ||
518 | if (tctx->flags & FLAGS_HMAC) { | 567 | if (tctx->flags & FLAGS_HMAC) { |
519 | struct omap_sham_hmac_ctx *bctx = tctx->base; | 568 | struct omap_sham_hmac_ctx *bctx = tctx->base; |
@@ -538,10 +587,8 @@ static int omap_sham_update_req(struct omap_sham_dev *dd) | |||
538 | 587 | ||
539 | if (ctx->flags & FLAGS_CPU) | 588 | if (ctx->flags & FLAGS_CPU) |
540 | err = omap_sham_update_cpu(dd); | 589 | err = omap_sham_update_cpu(dd); |
541 | else if (ctx->flags & FLAGS_FAST) | ||
542 | err = omap_sham_update_dma_fast(dd); | ||
543 | else | 590 | else |
544 | err = omap_sham_update_dma_slow(dd); | 591 | err = omap_sham_update_dma_start(dd); |
545 | 592 | ||
546 | /* wait for dma completion before can take more data */ | 593 | /* wait for dma completion before can take more data */ |
547 | dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n", err, ctx->digcnt); | 594 | dev_dbg(dd->dev, "update: err: %d, digcnt: %d\n", err, ctx->digcnt); |
@@ -560,15 +607,12 @@ static int omap_sham_final_req(struct omap_sham_dev *dd) | |||
560 | use_dma = 0; | 607 | use_dma = 0; |
561 | 608 | ||
562 | if (use_dma) | 609 | if (use_dma) |
563 | err = omap_sham_xmit_dma(dd, ctx->dma_addr, ctx->bufcnt, 1); | 610 | err = omap_sham_xmit_dma_map(dd, ctx, ctx->bufcnt, 1); |
564 | else | 611 | else |
565 | err = omap_sham_xmit_cpu(dd, ctx->buffer, ctx->bufcnt, 1); | 612 | err = omap_sham_xmit_cpu(dd, ctx->buffer, ctx->bufcnt, 1); |
566 | 613 | ||
567 | ctx->bufcnt = 0; | 614 | ctx->bufcnt = 0; |
568 | 615 | ||
569 | if (err != -EINPROGRESS) | ||
570 | omap_sham_cleanup(req); | ||
571 | |||
572 | dev_dbg(dd->dev, "final_req: err: %d\n", err); | 616 | dev_dbg(dd->dev, "final_req: err: %d\n", err); |
573 | 617 | ||
574 | return err; | 618 | return err; |
@@ -576,6 +620,7 @@ static int omap_sham_final_req(struct omap_sham_dev *dd) | |||
576 | 620 | ||
577 | static int omap_sham_finish_req_hmac(struct ahash_request *req) | 621 | static int omap_sham_finish_req_hmac(struct ahash_request *req) |
578 | { | 622 | { |
623 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | ||
579 | struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); | 624 | struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); |
580 | struct omap_sham_hmac_ctx *bctx = tctx->base; | 625 | struct omap_sham_hmac_ctx *bctx = tctx->base; |
581 | int bs = crypto_shash_blocksize(bctx->shash); | 626 | int bs = crypto_shash_blocksize(bctx->shash); |
@@ -590,48 +635,56 @@ static int omap_sham_finish_req_hmac(struct ahash_request *req) | |||
590 | 635 | ||
591 | return crypto_shash_init(&desc.shash) ?: | 636 | return crypto_shash_init(&desc.shash) ?: |
592 | crypto_shash_update(&desc.shash, bctx->opad, bs) ?: | 637 | crypto_shash_update(&desc.shash, bctx->opad, bs) ?: |
593 | crypto_shash_finup(&desc.shash, req->result, ds, req->result); | 638 | crypto_shash_finup(&desc.shash, ctx->digest, ds, ctx->digest); |
594 | } | 639 | } |
595 | 640 | ||
596 | static void omap_sham_finish_req(struct ahash_request *req, int err) | 641 | static void omap_sham_finish_req(struct ahash_request *req, int err) |
597 | { | 642 | { |
598 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | 643 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); |
644 | struct omap_sham_dev *dd = ctx->dd; | ||
599 | 645 | ||
600 | if (!err) { | 646 | if (!err) { |
601 | omap_sham_copy_hash(ctx->dd->req, 1); | 647 | omap_sham_copy_hash(ctx->dd->req, 1); |
602 | if (ctx->flags & FLAGS_HMAC) | 648 | if (ctx->flags & FLAGS_HMAC) |
603 | err = omap_sham_finish_req_hmac(req); | 649 | err = omap_sham_finish_req_hmac(req); |
650 | } else { | ||
651 | ctx->flags |= FLAGS_ERROR; | ||
604 | } | 652 | } |
605 | 653 | ||
606 | if (ctx->flags & FLAGS_FINAL) | 654 | if ((ctx->flags & FLAGS_FINAL) || err) |
607 | omap_sham_cleanup(req); | 655 | omap_sham_cleanup(req); |
608 | 656 | ||
609 | clear_bit(FLAGS_BUSY, &ctx->dd->flags); | 657 | clk_disable(dd->iclk); |
658 | dd->flags &= ~FLAGS_BUSY; | ||
610 | 659 | ||
611 | if (req->base.complete) | 660 | if (req->base.complete) |
612 | req->base.complete(&req->base, err); | 661 | req->base.complete(&req->base, err); |
613 | } | 662 | } |
614 | 663 | ||
615 | static int omap_sham_handle_queue(struct omap_sham_dev *dd) | 664 | static int omap_sham_handle_queue(struct omap_sham_dev *dd, |
665 | struct ahash_request *req) | ||
616 | { | 666 | { |
617 | struct crypto_async_request *async_req, *backlog; | 667 | struct crypto_async_request *async_req, *backlog; |
618 | struct omap_sham_reqctx *ctx; | 668 | struct omap_sham_reqctx *ctx; |
619 | struct ahash_request *req, *prev_req; | 669 | struct ahash_request *prev_req; |
620 | unsigned long flags; | 670 | unsigned long flags; |
621 | int err = 0; | 671 | int err = 0, ret = 0; |
622 | |||
623 | if (test_and_set_bit(FLAGS_BUSY, &dd->flags)) | ||
624 | return 0; | ||
625 | 672 | ||
626 | spin_lock_irqsave(&dd->lock, flags); | 673 | spin_lock_irqsave(&dd->lock, flags); |
674 | if (req) | ||
675 | ret = ahash_enqueue_request(&dd->queue, req); | ||
676 | if (dd->flags & FLAGS_BUSY) { | ||
677 | spin_unlock_irqrestore(&dd->lock, flags); | ||
678 | return ret; | ||
679 | } | ||
627 | backlog = crypto_get_backlog(&dd->queue); | 680 | backlog = crypto_get_backlog(&dd->queue); |
628 | async_req = crypto_dequeue_request(&dd->queue); | 681 | async_req = crypto_dequeue_request(&dd->queue); |
629 | if (!async_req) | 682 | if (async_req) |
630 | clear_bit(FLAGS_BUSY, &dd->flags); | 683 | dd->flags |= FLAGS_BUSY; |
631 | spin_unlock_irqrestore(&dd->lock, flags); | 684 | spin_unlock_irqrestore(&dd->lock, flags); |
632 | 685 | ||
633 | if (!async_req) | 686 | if (!async_req) |
634 | return 0; | 687 | return ret; |
635 | 688 | ||
636 | if (backlog) | 689 | if (backlog) |
637 | backlog->complete(backlog, -EINPROGRESS); | 690 | backlog->complete(backlog, -EINPROGRESS); |
@@ -646,7 +699,22 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd) | |||
646 | dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n", | 699 | dev_dbg(dd->dev, "handling new req, op: %lu, nbytes: %d\n", |
647 | ctx->op, req->nbytes); | 700 | ctx->op, req->nbytes); |
648 | 701 | ||
649 | if (req != prev_req && ctx->digcnt) | 702 | |
703 | err = omap_sham_hw_init(dd); | ||
704 | if (err) | ||
705 | goto err1; | ||
706 | |||
707 | omap_set_dma_dest_params(dd->dma_lch, 0, | ||
708 | OMAP_DMA_AMODE_CONSTANT, | ||
709 | dd->phys_base + SHA_REG_DIN(0), 0, 16); | ||
710 | |||
711 | omap_set_dma_dest_burst_mode(dd->dma_lch, | ||
712 | OMAP_DMA_DATA_BURST_16); | ||
713 | |||
714 | omap_set_dma_src_burst_mode(dd->dma_lch, | ||
715 | OMAP_DMA_DATA_BURST_4); | ||
716 | |||
717 | if (ctx->digcnt) | ||
650 | /* request has changed - restore hash */ | 718 | /* request has changed - restore hash */ |
651 | omap_sham_copy_hash(req, 0); | 719 | omap_sham_copy_hash(req, 0); |
652 | 720 | ||
@@ -658,7 +726,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd) | |||
658 | } else if (ctx->op == OP_FINAL) { | 726 | } else if (ctx->op == OP_FINAL) { |
659 | err = omap_sham_final_req(dd); | 727 | err = omap_sham_final_req(dd); |
660 | } | 728 | } |
661 | 729 | err1: | |
662 | if (err != -EINPROGRESS) { | 730 | if (err != -EINPROGRESS) { |
663 | /* done_task will not finish it, so do it here */ | 731 | /* done_task will not finish it, so do it here */ |
664 | omap_sham_finish_req(req, err); | 732 | omap_sham_finish_req(req, err); |
@@ -667,7 +735,7 @@ static int omap_sham_handle_queue(struct omap_sham_dev *dd) | |||
667 | 735 | ||
668 | dev_dbg(dd->dev, "exit, err: %d\n", err); | 736 | dev_dbg(dd->dev, "exit, err: %d\n", err); |
669 | 737 | ||
670 | return err; | 738 | return ret; |
671 | } | 739 | } |
672 | 740 | ||
673 | static int omap_sham_enqueue(struct ahash_request *req, unsigned int op) | 741 | static int omap_sham_enqueue(struct ahash_request *req, unsigned int op) |
@@ -675,18 +743,10 @@ static int omap_sham_enqueue(struct ahash_request *req, unsigned int op) | |||
675 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | 743 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); |
676 | struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); | 744 | struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm); |
677 | struct omap_sham_dev *dd = tctx->dd; | 745 | struct omap_sham_dev *dd = tctx->dd; |
678 | unsigned long flags; | ||
679 | int err; | ||
680 | 746 | ||
681 | ctx->op = op; | 747 | ctx->op = op; |
682 | 748 | ||
683 | spin_lock_irqsave(&dd->lock, flags); | 749 | return omap_sham_handle_queue(dd, req); |
684 | err = ahash_enqueue_request(&dd->queue, req); | ||
685 | spin_unlock_irqrestore(&dd->lock, flags); | ||
686 | |||
687 | omap_sham_handle_queue(dd); | ||
688 | |||
689 | return err; | ||
690 | } | 750 | } |
691 | 751 | ||
692 | static int omap_sham_update(struct ahash_request *req) | 752 | static int omap_sham_update(struct ahash_request *req) |
@@ -709,21 +769,13 @@ static int omap_sham_update(struct ahash_request *req) | |||
709 | */ | 769 | */ |
710 | omap_sham_append_sg(ctx); | 770 | omap_sham_append_sg(ctx); |
711 | return 0; | 771 | return 0; |
712 | } else if (ctx->bufcnt + ctx->total <= 64) { | 772 | } else if (ctx->bufcnt + ctx->total <= SHA1_MD5_BLOCK_SIZE) { |
773 | /* | ||
774 | * faster to use CPU for short transfers | ||
775 | */ | ||
713 | ctx->flags |= FLAGS_CPU; | 776 | ctx->flags |= FLAGS_CPU; |
714 | } else if (!ctx->bufcnt && sg_is_last(ctx->sg)) { | ||
715 | /* may be can use faster functions */ | ||
716 | int aligned = IS_ALIGNED((u32)ctx->sg->offset, | ||
717 | sizeof(u32)); | ||
718 | |||
719 | if (aligned && (ctx->flags & FLAGS_FIRST)) | ||
720 | /* digest: first and final */ | ||
721 | ctx->flags |= FLAGS_FAST; | ||
722 | |||
723 | ctx->flags &= ~FLAGS_FIRST; | ||
724 | } | 777 | } |
725 | } else if (ctx->bufcnt + ctx->total <= ctx->buflen) { | 778 | } else if (ctx->bufcnt + ctx->total < ctx->buflen) { |
726 | /* if not finaup -> not fast */ | ||
727 | omap_sham_append_sg(ctx); | 779 | omap_sham_append_sg(ctx); |
728 | return 0; | 780 | return 0; |
729 | } | 781 | } |
@@ -761,12 +813,14 @@ static int omap_sham_final(struct ahash_request *req) | |||
761 | 813 | ||
762 | ctx->flags |= FLAGS_FINUP; | 814 | ctx->flags |= FLAGS_FINUP; |
763 | 815 | ||
764 | /* OMAP HW accel works only with buffers >= 9 */ | 816 | if (!(ctx->flags & FLAGS_ERROR)) { |
765 | /* HMAC is always >= 9 because of ipad */ | 817 | /* OMAP HW accel works only with buffers >= 9 */ |
766 | if ((ctx->digcnt + ctx->bufcnt) < 9) | 818 | /* HMAC is always >= 9 because of ipad */ |
767 | err = omap_sham_final_shash(req); | 819 | if ((ctx->digcnt + ctx->bufcnt) < 9) |
768 | else if (ctx->bufcnt) | 820 | err = omap_sham_final_shash(req); |
769 | return omap_sham_enqueue(req, OP_FINAL); | 821 | else if (ctx->bufcnt) |
822 | return omap_sham_enqueue(req, OP_FINAL); | ||
823 | } | ||
770 | 824 | ||
771 | omap_sham_cleanup(req); | 825 | omap_sham_cleanup(req); |
772 | 826 | ||
@@ -836,6 +890,8 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) | |||
836 | struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm); | 890 | struct omap_sham_ctx *tctx = crypto_tfm_ctx(tfm); |
837 | const char *alg_name = crypto_tfm_alg_name(tfm); | 891 | const char *alg_name = crypto_tfm_alg_name(tfm); |
838 | 892 | ||
893 | pr_info("enter\n"); | ||
894 | |||
839 | /* Allocate a fallback and abort if it failed. */ | 895 | /* Allocate a fallback and abort if it failed. */ |
840 | tctx->fallback = crypto_alloc_shash(alg_name, 0, | 896 | tctx->fallback = crypto_alloc_shash(alg_name, 0, |
841 | CRYPTO_ALG_NEED_FALLBACK); | 897 | CRYPTO_ALG_NEED_FALLBACK); |
@@ -846,7 +902,7 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) | |||
846 | } | 902 | } |
847 | 903 | ||
848 | crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), | 904 | crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), |
849 | sizeof(struct omap_sham_reqctx)); | 905 | sizeof(struct omap_sham_reqctx) + BUFLEN); |
850 | 906 | ||
851 | if (alg_base) { | 907 | if (alg_base) { |
852 | struct omap_sham_hmac_ctx *bctx = tctx->base; | 908 | struct omap_sham_hmac_ctx *bctx = tctx->base; |
@@ -932,7 +988,7 @@ static struct ahash_alg algs[] = { | |||
932 | CRYPTO_ALG_NEED_FALLBACK, | 988 | CRYPTO_ALG_NEED_FALLBACK, |
933 | .cra_blocksize = SHA1_BLOCK_SIZE, | 989 | .cra_blocksize = SHA1_BLOCK_SIZE, |
934 | .cra_ctxsize = sizeof(struct omap_sham_ctx), | 990 | .cra_ctxsize = sizeof(struct omap_sham_ctx), |
935 | .cra_alignmask = 0, | 991 | .cra_alignmask = OMAP_ALIGN_MASK, |
936 | .cra_module = THIS_MODULE, | 992 | .cra_module = THIS_MODULE, |
937 | .cra_init = omap_sham_cra_init, | 993 | .cra_init = omap_sham_cra_init, |
938 | .cra_exit = omap_sham_cra_exit, | 994 | .cra_exit = omap_sham_cra_exit, |
@@ -956,7 +1012,7 @@ static struct ahash_alg algs[] = { | |||
956 | .cra_blocksize = SHA1_BLOCK_SIZE, | 1012 | .cra_blocksize = SHA1_BLOCK_SIZE, |
957 | .cra_ctxsize = sizeof(struct omap_sham_ctx) + | 1013 | .cra_ctxsize = sizeof(struct omap_sham_ctx) + |
958 | sizeof(struct omap_sham_hmac_ctx), | 1014 | sizeof(struct omap_sham_hmac_ctx), |
959 | .cra_alignmask = 0, | 1015 | .cra_alignmask = OMAP_ALIGN_MASK, |
960 | .cra_module = THIS_MODULE, | 1016 | .cra_module = THIS_MODULE, |
961 | .cra_init = omap_sham_cra_sha1_init, | 1017 | .cra_init = omap_sham_cra_sha1_init, |
962 | .cra_exit = omap_sham_cra_exit, | 1018 | .cra_exit = omap_sham_cra_exit, |
@@ -980,7 +1036,7 @@ static struct ahash_alg algs[] = { | |||
980 | .cra_blocksize = SHA1_BLOCK_SIZE, | 1036 | .cra_blocksize = SHA1_BLOCK_SIZE, |
981 | .cra_ctxsize = sizeof(struct omap_sham_ctx) + | 1037 | .cra_ctxsize = sizeof(struct omap_sham_ctx) + |
982 | sizeof(struct omap_sham_hmac_ctx), | 1038 | sizeof(struct omap_sham_hmac_ctx), |
983 | .cra_alignmask = 0, | 1039 | .cra_alignmask = OMAP_ALIGN_MASK, |
984 | .cra_module = THIS_MODULE, | 1040 | .cra_module = THIS_MODULE, |
985 | .cra_init = omap_sham_cra_md5_init, | 1041 | .cra_init = omap_sham_cra_md5_init, |
986 | .cra_exit = omap_sham_cra_exit, | 1042 | .cra_exit = omap_sham_cra_exit, |
@@ -993,7 +1049,7 @@ static void omap_sham_done_task(unsigned long data) | |||
993 | struct omap_sham_dev *dd = (struct omap_sham_dev *)data; | 1049 | struct omap_sham_dev *dd = (struct omap_sham_dev *)data; |
994 | struct ahash_request *req = dd->req; | 1050 | struct ahash_request *req = dd->req; |
995 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); | 1051 | struct omap_sham_reqctx *ctx = ahash_request_ctx(req); |
996 | int ready = 1; | 1052 | int ready = 0, err = 0; |
997 | 1053 | ||
998 | if (ctx->flags & FLAGS_OUTPUT_READY) { | 1054 | if (ctx->flags & FLAGS_OUTPUT_READY) { |
999 | ctx->flags &= ~FLAGS_OUTPUT_READY; | 1055 | ctx->flags &= ~FLAGS_OUTPUT_READY; |
@@ -1003,15 +1059,18 @@ static void omap_sham_done_task(unsigned long data) | |||
1003 | if (dd->flags & FLAGS_DMA_ACTIVE) { | 1059 | if (dd->flags & FLAGS_DMA_ACTIVE) { |
1004 | dd->flags &= ~FLAGS_DMA_ACTIVE; | 1060 | dd->flags &= ~FLAGS_DMA_ACTIVE; |
1005 | omap_sham_update_dma_stop(dd); | 1061 | omap_sham_update_dma_stop(dd); |
1006 | omap_sham_update_dma_slow(dd); | 1062 | if (!dd->err) |
1063 | err = omap_sham_update_dma_start(dd); | ||
1007 | } | 1064 | } |
1008 | 1065 | ||
1009 | if (ready && !(dd->flags & FLAGS_DMA_ACTIVE)) { | 1066 | err = dd->err ? : err; |
1010 | dev_dbg(dd->dev, "update done\n"); | 1067 | |
1068 | if (err != -EINPROGRESS && (ready || err)) { | ||
1069 | dev_dbg(dd->dev, "update done: err: %d\n", err); | ||
1011 | /* finish curent request */ | 1070 | /* finish curent request */ |
1012 | omap_sham_finish_req(req, 0); | 1071 | omap_sham_finish_req(req, err); |
1013 | /* start new request */ | 1072 | /* start new request */ |
1014 | omap_sham_handle_queue(dd); | 1073 | omap_sham_handle_queue(dd, NULL); |
1015 | } | 1074 | } |
1016 | } | 1075 | } |
1017 | 1076 | ||
@@ -1019,7 +1078,7 @@ static void omap_sham_queue_task(unsigned long data) | |||
1019 | { | 1078 | { |
1020 | struct omap_sham_dev *dd = (struct omap_sham_dev *)data; | 1079 | struct omap_sham_dev *dd = (struct omap_sham_dev *)data; |
1021 | 1080 | ||
1022 | omap_sham_handle_queue(dd); | 1081 | omap_sham_handle_queue(dd, NULL); |
1023 | } | 1082 | } |
1024 | 1083 | ||
1025 | static irqreturn_t omap_sham_irq(int irq, void *dev_id) | 1084 | static irqreturn_t omap_sham_irq(int irq, void *dev_id) |
@@ -1041,6 +1100,7 @@ static irqreturn_t omap_sham_irq(int irq, void *dev_id) | |||
1041 | omap_sham_read(dd, SHA_REG_CTRL); | 1100 | omap_sham_read(dd, SHA_REG_CTRL); |
1042 | 1101 | ||
1043 | ctx->flags |= FLAGS_OUTPUT_READY; | 1102 | ctx->flags |= FLAGS_OUTPUT_READY; |
1103 | dd->err = 0; | ||
1044 | tasklet_schedule(&dd->done_task); | 1104 | tasklet_schedule(&dd->done_task); |
1045 | 1105 | ||
1046 | return IRQ_HANDLED; | 1106 | return IRQ_HANDLED; |
@@ -1050,8 +1110,13 @@ static void omap_sham_dma_callback(int lch, u16 ch_status, void *data) | |||
1050 | { | 1110 | { |
1051 | struct omap_sham_dev *dd = data; | 1111 | struct omap_sham_dev *dd = data; |
1052 | 1112 | ||
1053 | if (likely(lch == dd->dma_lch)) | 1113 | if (ch_status != OMAP_DMA_BLOCK_IRQ) { |
1054 | tasklet_schedule(&dd->done_task); | 1114 | pr_err("omap-sham DMA error status: 0x%hx\n", ch_status); |
1115 | dd->err = -EIO; | ||
1116 | dd->flags &= ~FLAGS_INIT; /* request to re-initialize */ | ||
1117 | } | ||
1118 | |||
1119 | tasklet_schedule(&dd->done_task); | ||
1055 | } | 1120 | } |
1056 | 1121 | ||
1057 | static int omap_sham_dma_init(struct omap_sham_dev *dd) | 1122 | static int omap_sham_dma_init(struct omap_sham_dev *dd) |
@@ -1066,15 +1131,6 @@ static int omap_sham_dma_init(struct omap_sham_dev *dd) | |||
1066 | dev_err(dd->dev, "Unable to request DMA channel\n"); | 1131 | dev_err(dd->dev, "Unable to request DMA channel\n"); |
1067 | return err; | 1132 | return err; |
1068 | } | 1133 | } |
1069 | omap_set_dma_dest_params(dd->dma_lch, 0, | ||
1070 | OMAP_DMA_AMODE_CONSTANT, | ||
1071 | dd->phys_base + SHA_REG_DIN(0), 0, 16); | ||
1072 | |||
1073 | omap_set_dma_dest_burst_mode(dd->dma_lch, | ||
1074 | OMAP_DMA_DATA_BURST_16); | ||
1075 | |||
1076 | omap_set_dma_src_burst_mode(dd->dma_lch, | ||
1077 | OMAP_DMA_DATA_BURST_4); | ||
1078 | 1134 | ||
1079 | return 0; | 1135 | return 0; |
1080 | } | 1136 | } |
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 8a515baa38f7..db33d300aa23 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <crypto/algapi.h> | 10 | #include <crypto/algapi.h> |
11 | #include <crypto/aes.h> | 11 | #include <crypto/aes.h> |
12 | #include <crypto/padlock.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include <linux/types.h> | 15 | #include <linux/types.h> |
@@ -21,7 +22,6 @@ | |||
21 | #include <asm/byteorder.h> | 22 | #include <asm/byteorder.h> |
22 | #include <asm/processor.h> | 23 | #include <asm/processor.h> |
23 | #include <asm/i387.h> | 24 | #include <asm/i387.h> |
24 | #include "padlock.h" | ||
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Number of data blocks actually fetched for each xcrypt insn. | 27 | * Number of data blocks actually fetched for each xcrypt insn. |
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index d3a27e0119bc..adf075b6b9a8 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <crypto/internal/hash.h> | 15 | #include <crypto/internal/hash.h> |
16 | #include <crypto/padlock.h> | ||
16 | #include <crypto/sha.h> | 17 | #include <crypto/sha.h> |
17 | #include <linux/err.h> | 18 | #include <linux/err.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -22,13 +23,6 @@ | |||
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/scatterlist.h> | 24 | #include <linux/scatterlist.h> |
24 | #include <asm/i387.h> | 25 | #include <asm/i387.h> |
25 | #include "padlock.h" | ||
26 | |||
27 | #ifdef CONFIG_64BIT | ||
28 | #define STACK_ALIGN 16 | ||
29 | #else | ||
30 | #define STACK_ALIGN 4 | ||
31 | #endif | ||
32 | 26 | ||
33 | struct padlock_sha_desc { | 27 | struct padlock_sha_desc { |
34 | struct shash_desc fallback; | 28 | struct shash_desc fallback; |
diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h deleted file mode 100644 index b728e4518bd1..000000000000 --- a/drivers/crypto/padlock.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for VIA PadLock | ||
3 | * | ||
4 | * Copyright (c) 2004 Michal Ludvig <michal@logix.cz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #ifndef _CRYPTO_PADLOCK_H | ||
14 | #define _CRYPTO_PADLOCK_H | ||
15 | |||
16 | #define PADLOCK_ALIGNMENT 16 | ||
17 | |||
18 | #define PFX "padlock: " | ||
19 | |||
20 | #define PADLOCK_CRA_PRIORITY 300 | ||
21 | #define PADLOCK_COMPOSITE_PRIORITY 400 | ||
22 | |||
23 | #endif /* _CRYPTO_PADLOCK_H */ | ||
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index b98c67664ae7..c461eda62411 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c | |||
@@ -110,8 +110,6 @@ static void unregister_dca_providers(void) | |||
110 | 110 | ||
111 | /* at this point only one domain in the list is expected */ | 111 | /* at this point only one domain in the list is expected */ |
112 | domain = list_first_entry(&dca_domains, struct dca_domain, node); | 112 | domain = list_first_entry(&dca_domains, struct dca_domain, node); |
113 | if (!domain) | ||
114 | return; | ||
115 | 113 | ||
116 | list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) { | 114 | list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) { |
117 | list_del(&dca->node); | 115 | list_del(&dca->node); |
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c index 3109bd94bc4f..78266382797e 100644 --- a/drivers/dma/intel_mid_dma.c +++ b/drivers/dma/intel_mid_dma.c | |||
@@ -1060,8 +1060,8 @@ static irqreturn_t intel_mid_dma_interrupt2(int irq, void *data) | |||
1060 | * mid_setup_dma - Setup the DMA controller | 1060 | * mid_setup_dma - Setup the DMA controller |
1061 | * @pdev: Controller PCI device structure | 1061 | * @pdev: Controller PCI device structure |
1062 | * | 1062 | * |
1063 | * Initilize the DMA controller, channels, registers with DMA engine, | 1063 | * Initialize the DMA controller, channels, registers with DMA engine, |
1064 | * ISR. Initilize DMA controller channels. | 1064 | * ISR. Initialize DMA controller channels. |
1065 | */ | 1065 | */ |
1066 | static int mid_setup_dma(struct pci_dev *pdev) | 1066 | static int mid_setup_dma(struct pci_dev *pdev) |
1067 | { | 1067 | { |
@@ -1217,7 +1217,7 @@ static void middma_shutdown(struct pci_dev *pdev) | |||
1217 | * @pdev: Controller PCI device structure | 1217 | * @pdev: Controller PCI device structure |
1218 | * @id: pci device id structure | 1218 | * @id: pci device id structure |
1219 | * | 1219 | * |
1220 | * Initilize the PCI device, map BARs, query driver data. | 1220 | * Initialize the PCI device, map BARs, query driver data. |
1221 | * Call setup_dma to complete contoller and chan initilzation | 1221 | * Call setup_dma to complete contoller and chan initilzation |
1222 | */ | 1222 | */ |
1223 | static int __devinit intel_mid_dma_probe(struct pci_dev *pdev, | 1223 | static int __devinit intel_mid_dma_probe(struct pci_dev *pdev, |
diff --git a/drivers/edac/amd8131_edac.h b/drivers/edac/amd8131_edac.h index 60e0d1c72dee..6f8b07131ec4 100644 --- a/drivers/edac/amd8131_edac.h +++ b/drivers/edac/amd8131_edac.h | |||
@@ -99,7 +99,7 @@ struct amd8131_dev_info { | |||
99 | 99 | ||
100 | /* | 100 | /* |
101 | * AMD8131 chipset has two pairs of PCIX Bridge and related IOAPIC | 101 | * AMD8131 chipset has two pairs of PCIX Bridge and related IOAPIC |
102 | * Controler, and ATCA-6101 has two AMD8131 chipsets, so there are | 102 | * Controller, and ATCA-6101 has two AMD8131 chipsets, so there are |
103 | * four PCIX Bridges on ATCA-6101 altogether. | 103 | * four PCIX Bridges on ATCA-6101 altogether. |
104 | * | 104 | * |
105 | * These PCIX Bridges share the same PCI Device ID and are all of | 105 | * These PCIX Bridges share the same PCI Device ID and are all of |
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index c973004c002c..db1df59ae2b6 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c | |||
@@ -47,7 +47,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) | |||
47 | offset = address & ~PAGE_MASK; | 47 | offset = address & ~PAGE_MASK; |
48 | syndrome = (ar & 0x000000001fe00000ul) >> 21; | 48 | syndrome = (ar & 0x000000001fe00000ul) >> 21; |
49 | 49 | ||
50 | /* TODO: Decoding of the error addresss */ | 50 | /* TODO: Decoding of the error address */ |
51 | edac_mc_handle_ce(mci, csrow->first_page + pfn, offset, | 51 | edac_mc_handle_ce(mci, csrow->first_page + pfn, offset, |
52 | syndrome, 0, chan, ""); | 52 | syndrome, 0, chan, ""); |
53 | } | 53 | } |
@@ -68,7 +68,7 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) | |||
68 | pfn = address >> PAGE_SHIFT; | 68 | pfn = address >> PAGE_SHIFT; |
69 | offset = address & ~PAGE_MASK; | 69 | offset = address & ~PAGE_MASK; |
70 | 70 | ||
71 | /* TODO: Decoding of the error addresss */ | 71 | /* TODO: Decoding of the error address */ |
72 | edac_mc_handle_ue(mci, csrow->first_page + pfn, offset, 0, ""); | 72 | edac_mc_handle_ue(mci, csrow->first_page + pfn, offset, 0, ""); |
73 | } | 73 | } |
74 | 74 | ||
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index ff1eb7bb26c6..3d965347a673 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -259,7 +259,7 @@ enum scrub_type { | |||
259 | * for single channel are 64 bits, for dual channel 128 | 259 | * for single channel are 64 bits, for dual channel 128 |
260 | * bits. | 260 | * bits. |
261 | * | 261 | * |
262 | * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memmory. | 262 | * Single-Ranked stick: A Single-ranked stick has 1 chip-select row of memory. |
263 | * Motherboards commonly drive two chip-select pins to | 263 | * Motherboards commonly drive two chip-select pins to |
264 | * a memory stick. A single-ranked stick, will occupy | 264 | * a memory stick. A single-ranked stick, will occupy |
265 | * only one of those rows. The other will be unused. | 265 | * only one of those rows. The other will be unused. |
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 362861c15779..81154ab296b6 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Intel i7 core/Nehalem Memory Controller kernel module | 1 | /* Intel i7 core/Nehalem Memory Controller kernel module |
2 | * | 2 | * |
3 | * This driver supports yhe memory controllers found on the Intel | 3 | * This driver supports the memory controllers found on the Intel |
4 | * processor families i7core, i7core 7xx/8xx, i5core, Xeon 35xx, | 4 | * processor families i7core, i7core 7xx/8xx, i5core, Xeon 35xx, |
5 | * Xeon 55xx and Xeon 56xx also known as Nehalem, Nehalem-EP, Lynnfield | 5 | * Xeon 55xx and Xeon 56xx also known as Nehalem, Nehalem-EP, Lynnfield |
6 | * and Westmere-EP. | 6 | * and Westmere-EP. |
@@ -1271,7 +1271,7 @@ static void __init i7core_xeon_pci_fixup(const struct pci_id_table *table) | |||
1271 | int i; | 1271 | int i; |
1272 | 1272 | ||
1273 | /* | 1273 | /* |
1274 | * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses | 1274 | * On Xeon 55xx, the Intel Quick Path Arch Generic Non-core pci buses |
1275 | * aren't announced by acpi. So, we need to use a legacy scan probing | 1275 | * aren't announced by acpi. So, we need to use a legacy scan probing |
1276 | * to detect them | 1276 | * to detect them |
1277 | */ | 1277 | */ |
@@ -1864,7 +1864,7 @@ static int i7core_mce_check_error(void *priv, struct mce *mce) | |||
1864 | if (mce->mcgstatus & 1) | 1864 | if (mce->mcgstatus & 1) |
1865 | i7core_check_error(mci); | 1865 | i7core_check_error(mci); |
1866 | 1866 | ||
1867 | /* Advice mcelog that the error were handled */ | 1867 | /* Advise mcelog that the errors were handled */ |
1868 | return 1; | 1868 | return 1; |
1869 | } | 1869 | } |
1870 | 1870 | ||
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index 070cea41b661..b9f0c20df1aa 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c | |||
@@ -873,7 +873,7 @@ ppc4xx_edac_get_mtype(u32 mcopt1) | |||
873 | } | 873 | } |
874 | 874 | ||
875 | /** | 875 | /** |
876 | * ppc4xx_edac_init_csrows - intialize driver instance rows | 876 | * ppc4xx_edac_init_csrows - initialize driver instance rows |
877 | * @mci: A pointer to the EDAC memory controller instance | 877 | * @mci: A pointer to the EDAC memory controller instance |
878 | * associated with the ibm,sdram-4xx-ddr2 controller for which | 878 | * associated with the ibm,sdram-4xx-ddr2 controller for which |
879 | * the csrows (i.e. banks/ranks) are being initialized. | 879 | * the csrows (i.e. banks/ranks) are being initialized. |
@@ -881,7 +881,7 @@ ppc4xx_edac_get_mtype(u32 mcopt1) | |||
881 | * currently set for the controller, from which bank width | 881 | * currently set for the controller, from which bank width |
882 | * and memory typ information is derived. | 882 | * and memory typ information is derived. |
883 | * | 883 | * |
884 | * This routine intializes the virtual "chip select rows" associated | 884 | * This routine initializes the virtual "chip select rows" associated |
885 | * with the EDAC memory controller instance. An ibm,sdram-4xx-ddr2 | 885 | * with the EDAC memory controller instance. An ibm,sdram-4xx-ddr2 |
886 | * controller bank/rank is mapped to a row. | 886 | * controller bank/rank is mapped to a row. |
887 | * | 887 | * |
@@ -992,7 +992,7 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1) | |||
992 | } | 992 | } |
993 | 993 | ||
994 | /** | 994 | /** |
995 | * ppc4xx_edac_mc_init - intialize driver instance | 995 | * ppc4xx_edac_mc_init - initialize driver instance |
996 | * @mci: A pointer to the EDAC memory controller instance being | 996 | * @mci: A pointer to the EDAC memory controller instance being |
997 | * initialized. | 997 | * initialized. |
998 | * @op: A pointer to the OpenFirmware device tree node associated | 998 | * @op: A pointer to the OpenFirmware device tree node associated |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 082495bb08a7..664660e56335 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -118,7 +118,7 @@ config GPIO_SCH | |||
118 | 118 | ||
119 | config GPIO_VX855 | 119 | config GPIO_VX855 |
120 | tristate "VIA VX855/VX875 GPIO" | 120 | tristate "VIA VX855/VX875 GPIO" |
121 | depends on GPIOLIB | 121 | depends on GPIOLIB && MFD_SUPPORT && PCI |
122 | select MFD_CORE | 122 | select MFD_CORE |
123 | select MFD_VX855 | 123 | select MFD_VX855 |
124 | help | 124 | help |
@@ -295,7 +295,7 @@ comment "PCI GPIO expanders:" | |||
295 | 295 | ||
296 | config GPIO_CS5535 | 296 | config GPIO_CS5535 |
297 | tristate "AMD CS5535/CS5536 GPIO support" | 297 | tristate "AMD CS5535/CS5536 GPIO support" |
298 | depends on PCI && !CS5535_GPIO | 298 | depends on PCI && X86 && !CS5535_GPIO |
299 | help | 299 | help |
300 | The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that | 300 | The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that |
301 | can be used for quite a number of things. The CS5535/6 is found on | 301 | can be used for quite a number of things. The CS5535/6 is found on |
@@ -333,6 +333,15 @@ config GPIO_PCH | |||
333 | which is an IOH(Input/Output Hub) for x86 embedded processor. | 333 | which is an IOH(Input/Output Hub) for x86 embedded processor. |
334 | This driver can access PCH GPIO device. | 334 | This driver can access PCH GPIO device. |
335 | 335 | ||
336 | config GPIO_ML_IOH | ||
337 | tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support" | ||
338 | depends on PCI | ||
339 | help | ||
340 | ML7213 is companion chip for Intel Atom E6xx series. | ||
341 | This driver can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/Output | ||
342 | Hub) which is for IVI(In-Vehicle Infotainment) use. | ||
343 | This driver can access the IOH's GPIO device. | ||
344 | |||
336 | config GPIO_TIMBERDALE | 345 | config GPIO_TIMBERDALE |
337 | bool "Support for timberdale GPIO IP" | 346 | bool "Support for timberdale GPIO IP" |
338 | depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM | 347 | depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM |
@@ -342,6 +351,7 @@ config GPIO_TIMBERDALE | |||
342 | config GPIO_RDC321X | 351 | config GPIO_RDC321X |
343 | tristate "RDC R-321x GPIO support" | 352 | tristate "RDC R-321x GPIO support" |
344 | depends on PCI && GPIOLIB | 353 | depends on PCI && GPIOLIB |
354 | select MFD_SUPPORT | ||
345 | select MFD_CORE | 355 | select MFD_CORE |
346 | select MFD_RDC321X | 356 | select MFD_RDC321X |
347 | help | 357 | help |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 39bfd7a37650..3351cf87b0ed 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -41,3 +41,4 @@ obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o | |||
41 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o | 41 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o |
42 | obj-$(CONFIG_GPIO_SX150X) += sx150x.o | 42 | obj-$(CONFIG_GPIO_SX150X) += sx150x.o |
43 | obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o | 43 | obj-$(CONFIG_GPIO_VX855) += vx855_gpio.o |
44 | obj-$(CONFIG_GPIO_ML_IOH) += ml_ioh_gpio.o | ||
diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/adp5588-gpio.c index 0871f78af593..33fc685cb385 100644 --- a/drivers/gpio/adp5588-gpio.c +++ b/drivers/gpio/adp5588-gpio.c | |||
@@ -146,9 +146,10 @@ static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off) | |||
146 | return dev->irq_base + off; | 146 | return dev->irq_base + off; |
147 | } | 147 | } |
148 | 148 | ||
149 | static void adp5588_irq_bus_lock(unsigned int irq) | 149 | static void adp5588_irq_bus_lock(struct irq_data *d) |
150 | { | 150 | { |
151 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | 151 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); |
152 | |||
152 | mutex_lock(&dev->irq_lock); | 153 | mutex_lock(&dev->irq_lock); |
153 | } | 154 | } |
154 | 155 | ||
@@ -160,9 +161,9 @@ static void adp5588_irq_bus_lock(unsigned int irq) | |||
160 | * and unlocks the bus. | 161 | * and unlocks the bus. |
161 | */ | 162 | */ |
162 | 163 | ||
163 | static void adp5588_irq_bus_sync_unlock(unsigned int irq) | 164 | static void adp5588_irq_bus_sync_unlock(struct irq_data *d) |
164 | { | 165 | { |
165 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | 166 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); |
166 | int i; | 167 | int i; |
167 | 168 | ||
168 | for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) | 169 | for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) |
@@ -175,31 +176,31 @@ static void adp5588_irq_bus_sync_unlock(unsigned int irq) | |||
175 | mutex_unlock(&dev->irq_lock); | 176 | mutex_unlock(&dev->irq_lock); |
176 | } | 177 | } |
177 | 178 | ||
178 | static void adp5588_irq_mask(unsigned int irq) | 179 | static void adp5588_irq_mask(struct irq_data *d) |
179 | { | 180 | { |
180 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | 181 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); |
181 | unsigned gpio = irq - dev->irq_base; | 182 | unsigned gpio = d->irq - dev->irq_base; |
182 | 183 | ||
183 | dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio); | 184 | dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio); |
184 | } | 185 | } |
185 | 186 | ||
186 | static void adp5588_irq_unmask(unsigned int irq) | 187 | static void adp5588_irq_unmask(struct irq_data *d) |
187 | { | 188 | { |
188 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | 189 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); |
189 | unsigned gpio = irq - dev->irq_base; | 190 | unsigned gpio = d->irq - dev->irq_base; |
190 | 191 | ||
191 | dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio); | 192 | dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio); |
192 | } | 193 | } |
193 | 194 | ||
194 | static int adp5588_irq_set_type(unsigned int irq, unsigned int type) | 195 | static int adp5588_irq_set_type(struct irq_data *d, unsigned int type) |
195 | { | 196 | { |
196 | struct adp5588_gpio *dev = get_irq_chip_data(irq); | 197 | struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); |
197 | uint16_t gpio = irq - dev->irq_base; | 198 | uint16_t gpio = d->irq - dev->irq_base; |
198 | unsigned bank, bit; | 199 | unsigned bank, bit; |
199 | 200 | ||
200 | if ((type & IRQ_TYPE_EDGE_BOTH)) { | 201 | if ((type & IRQ_TYPE_EDGE_BOTH)) { |
201 | dev_err(&dev->client->dev, "irq %d: unsupported type %d\n", | 202 | dev_err(&dev->client->dev, "irq %d: unsupported type %d\n", |
202 | irq, type); | 203 | d->irq, type); |
203 | return -EINVAL; | 204 | return -EINVAL; |
204 | } | 205 | } |
205 | 206 | ||
@@ -222,11 +223,11 @@ static int adp5588_irq_set_type(unsigned int irq, unsigned int type) | |||
222 | 223 | ||
223 | static struct irq_chip adp5588_irq_chip = { | 224 | static struct irq_chip adp5588_irq_chip = { |
224 | .name = "adp5588", | 225 | .name = "adp5588", |
225 | .mask = adp5588_irq_mask, | 226 | .irq_mask = adp5588_irq_mask, |
226 | .unmask = adp5588_irq_unmask, | 227 | .irq_unmask = adp5588_irq_unmask, |
227 | .bus_lock = adp5588_irq_bus_lock, | 228 | .irq_bus_lock = adp5588_irq_bus_lock, |
228 | .bus_sync_unlock = adp5588_irq_bus_sync_unlock, | 229 | .irq_bus_sync_unlock = adp5588_irq_bus_sync_unlock, |
229 | .set_type = adp5588_irq_set_type, | 230 | .irq_set_type = adp5588_irq_set_type, |
230 | }; | 231 | }; |
231 | 232 | ||
232 | static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf) | 233 | static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf) |
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index d3e55a0ae92b..815d98b2c1ba 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/gpio.h> | 15 | #include <linux/gpio.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/cs5535.h> | 17 | #include <linux/cs5535.h> |
18 | #include <asm/msr.h> | ||
18 | 19 | ||
19 | #define DRV_NAME "cs5535-gpio" | 20 | #define DRV_NAME "cs5535-gpio" |
20 | #define GPIO_BAR 1 | 21 | #define GPIO_BAR 1 |
@@ -144,6 +145,57 @@ int cs5535_gpio_isset(unsigned offset, unsigned int reg) | |||
144 | } | 145 | } |
145 | EXPORT_SYMBOL_GPL(cs5535_gpio_isset); | 146 | EXPORT_SYMBOL_GPL(cs5535_gpio_isset); |
146 | 147 | ||
148 | int cs5535_gpio_set_irq(unsigned group, unsigned irq) | ||
149 | { | ||
150 | uint32_t lo, hi; | ||
151 | |||
152 | if (group > 7 || irq > 15) | ||
153 | return -EINVAL; | ||
154 | |||
155 | rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi); | ||
156 | |||
157 | lo &= ~(0xF << (group * 4)); | ||
158 | lo |= (irq & 0xF) << (group * 4); | ||
159 | |||
160 | wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi); | ||
161 | return 0; | ||
162 | } | ||
163 | EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq); | ||
164 | |||
165 | void cs5535_gpio_setup_event(unsigned offset, int pair, int pme) | ||
166 | { | ||
167 | struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; | ||
168 | uint32_t shift = (offset % 8) * 4; | ||
169 | unsigned long flags; | ||
170 | uint32_t val; | ||
171 | |||
172 | if (offset >= 24) | ||
173 | offset = GPIO_MAP_W; | ||
174 | else if (offset >= 16) | ||
175 | offset = GPIO_MAP_Z; | ||
176 | else if (offset >= 8) | ||
177 | offset = GPIO_MAP_Y; | ||
178 | else | ||
179 | offset = GPIO_MAP_X; | ||
180 | |||
181 | spin_lock_irqsave(&chip->lock, flags); | ||
182 | val = inl(chip->base + offset); | ||
183 | |||
184 | /* Clear whatever was there before */ | ||
185 | val &= ~(0xF << shift); | ||
186 | |||
187 | /* Set the new value */ | ||
188 | val |= ((pair & 7) << shift); | ||
189 | |||
190 | /* Set the PME bit if this is a PME event */ | ||
191 | if (pme) | ||
192 | val |= (1 << (shift + 3)); | ||
193 | |||
194 | outl(val, chip->base + offset); | ||
195 | spin_unlock_irqrestore(&chip->lock, flags); | ||
196 | } | ||
197 | EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event); | ||
198 | |||
147 | /* | 199 | /* |
148 | * Generic gpio_chip API support. | 200 | * Generic gpio_chip API support. |
149 | */ | 201 | */ |
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 64db9dc3a275..d81cc748e77f 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
@@ -134,10 +134,10 @@ static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
134 | return lnw->irq_base + offset; | 134 | return lnw->irq_base + offset; |
135 | } | 135 | } |
136 | 136 | ||
137 | static int lnw_irq_type(unsigned irq, unsigned type) | 137 | static int lnw_irq_type(struct irq_data *d, unsigned type) |
138 | { | 138 | { |
139 | struct lnw_gpio *lnw = get_irq_chip_data(irq); | 139 | struct lnw_gpio *lnw = irq_data_get_irq_chip_data(d); |
140 | u32 gpio = irq - lnw->irq_base; | 140 | u32 gpio = d->irq - lnw->irq_base; |
141 | unsigned long flags; | 141 | unsigned long flags; |
142 | u32 value; | 142 | u32 value; |
143 | void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); | 143 | void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); |
@@ -162,19 +162,19 @@ static int lnw_irq_type(unsigned irq, unsigned type) | |||
162 | return 0; | 162 | return 0; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void lnw_irq_unmask(unsigned irq) | 165 | static void lnw_irq_unmask(struct irq_data *d) |
166 | { | 166 | { |
167 | } | 167 | } |
168 | 168 | ||
169 | static void lnw_irq_mask(unsigned irq) | 169 | static void lnw_irq_mask(struct irq_data *d) |
170 | { | 170 | { |
171 | } | 171 | } |
172 | 172 | ||
173 | static struct irq_chip lnw_irqchip = { | 173 | static struct irq_chip lnw_irqchip = { |
174 | .name = "LNW-GPIO", | 174 | .name = "LNW-GPIO", |
175 | .mask = lnw_irq_mask, | 175 | .irq_mask = lnw_irq_mask, |
176 | .unmask = lnw_irq_unmask, | 176 | .irq_unmask = lnw_irq_unmask, |
177 | .set_type = lnw_irq_type, | 177 | .irq_set_type = lnw_irq_type, |
178 | }; | 178 | }; |
179 | 179 | ||
180 | static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ | 180 | static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ |
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c index 9cad60f9e962..9e1d01f0071a 100644 --- a/drivers/gpio/max732x.c +++ b/drivers/gpio/max732x.c | |||
@@ -327,40 +327,40 @@ static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) | |||
327 | return chip->irq_base + off; | 327 | return chip->irq_base + off; |
328 | } | 328 | } |
329 | 329 | ||
330 | static void max732x_irq_mask(unsigned int irq) | 330 | static void max732x_irq_mask(struct irq_data *d) |
331 | { | 331 | { |
332 | struct max732x_chip *chip = get_irq_chip_data(irq); | 332 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
333 | 333 | ||
334 | chip->irq_mask_cur &= ~(1 << (irq - chip->irq_base)); | 334 | chip->irq_mask_cur &= ~(1 << (d->irq - chip->irq_base)); |
335 | } | 335 | } |
336 | 336 | ||
337 | static void max732x_irq_unmask(unsigned int irq) | 337 | static void max732x_irq_unmask(struct irq_data *d) |
338 | { | 338 | { |
339 | struct max732x_chip *chip = get_irq_chip_data(irq); | 339 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
340 | 340 | ||
341 | chip->irq_mask_cur |= 1 << (irq - chip->irq_base); | 341 | chip->irq_mask_cur |= 1 << (d->irq - chip->irq_base); |
342 | } | 342 | } |
343 | 343 | ||
344 | static void max732x_irq_bus_lock(unsigned int irq) | 344 | static void max732x_irq_bus_lock(struct irq_data *d) |
345 | { | 345 | { |
346 | struct max732x_chip *chip = get_irq_chip_data(irq); | 346 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
347 | 347 | ||
348 | mutex_lock(&chip->irq_lock); | 348 | mutex_lock(&chip->irq_lock); |
349 | chip->irq_mask_cur = chip->irq_mask; | 349 | chip->irq_mask_cur = chip->irq_mask; |
350 | } | 350 | } |
351 | 351 | ||
352 | static void max732x_irq_bus_sync_unlock(unsigned int irq) | 352 | static void max732x_irq_bus_sync_unlock(struct irq_data *d) |
353 | { | 353 | { |
354 | struct max732x_chip *chip = get_irq_chip_data(irq); | 354 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
355 | 355 | ||
356 | max732x_irq_update_mask(chip); | 356 | max732x_irq_update_mask(chip); |
357 | mutex_unlock(&chip->irq_lock); | 357 | mutex_unlock(&chip->irq_lock); |
358 | } | 358 | } |
359 | 359 | ||
360 | static int max732x_irq_set_type(unsigned int irq, unsigned int type) | 360 | static int max732x_irq_set_type(struct irq_data *d, unsigned int type) |
361 | { | 361 | { |
362 | struct max732x_chip *chip = get_irq_chip_data(irq); | 362 | struct max732x_chip *chip = irq_data_get_irq_chip_data(d); |
363 | uint16_t off = irq - chip->irq_base; | 363 | uint16_t off = d->irq - chip->irq_base; |
364 | uint16_t mask = 1 << off; | 364 | uint16_t mask = 1 << off; |
365 | 365 | ||
366 | if (!(mask & chip->dir_input)) { | 366 | if (!(mask & chip->dir_input)) { |
@@ -371,7 +371,7 @@ static int max732x_irq_set_type(unsigned int irq, unsigned int type) | |||
371 | 371 | ||
372 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { | 372 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { |
373 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", | 373 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", |
374 | irq, type); | 374 | d->irq, type); |
375 | return -EINVAL; | 375 | return -EINVAL; |
376 | } | 376 | } |
377 | 377 | ||
@@ -390,11 +390,11 @@ static int max732x_irq_set_type(unsigned int irq, unsigned int type) | |||
390 | 390 | ||
391 | static struct irq_chip max732x_irq_chip = { | 391 | static struct irq_chip max732x_irq_chip = { |
392 | .name = "max732x", | 392 | .name = "max732x", |
393 | .mask = max732x_irq_mask, | 393 | .irq_mask = max732x_irq_mask, |
394 | .unmask = max732x_irq_unmask, | 394 | .irq_unmask = max732x_irq_unmask, |
395 | .bus_lock = max732x_irq_bus_lock, | 395 | .irq_bus_lock = max732x_irq_bus_lock, |
396 | .bus_sync_unlock = max732x_irq_bus_sync_unlock, | 396 | .irq_bus_sync_unlock = max732x_irq_bus_sync_unlock, |
397 | .set_type = max732x_irq_set_type, | 397 | .irq_set_type = max732x_irq_set_type, |
398 | }; | 398 | }; |
399 | 399 | ||
400 | static uint8_t max732x_irq_pending(struct max732x_chip *chip) | 400 | static uint8_t max732x_irq_pending(struct max732x_chip *chip) |
diff --git a/drivers/gpio/ml_ioh_gpio.c b/drivers/gpio/ml_ioh_gpio.c new file mode 100644 index 000000000000..cead8e6ff345 --- /dev/null +++ b/drivers/gpio/ml_ioh_gpio.c | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; version 2 of the License. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | ||
16 | */ | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/gpio.h> | ||
20 | |||
21 | #define PCI_VENDOR_ID_ROHM 0x10DB | ||
22 | |||
23 | struct ioh_reg_comn { | ||
24 | u32 ien; | ||
25 | u32 istatus; | ||
26 | u32 idisp; | ||
27 | u32 iclr; | ||
28 | u32 imask; | ||
29 | u32 imaskclr; | ||
30 | u32 po; | ||
31 | u32 pi; | ||
32 | u32 pm; | ||
33 | u32 im_0; | ||
34 | u32 im_1; | ||
35 | u32 reserved; | ||
36 | }; | ||
37 | |||
38 | struct ioh_regs { | ||
39 | struct ioh_reg_comn regs[8]; | ||
40 | u32 reserve1[16]; | ||
41 | u32 ioh_sel_reg[4]; | ||
42 | u32 reserve2[11]; | ||
43 | u32 srst; | ||
44 | }; | ||
45 | |||
46 | /** | ||
47 | * struct ioh_gpio_reg_data - The register store data. | ||
48 | * @po_reg: To store contents of PO register. | ||
49 | * @pm_reg: To store contents of PM register. | ||
50 | */ | ||
51 | struct ioh_gpio_reg_data { | ||
52 | u32 po_reg; | ||
53 | u32 pm_reg; | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * struct ioh_gpio - GPIO private data structure. | ||
58 | * @base: PCI base address of Memory mapped I/O register. | ||
59 | * @reg: Memory mapped IOH GPIO register list. | ||
60 | * @dev: Pointer to device structure. | ||
61 | * @gpio: Data for GPIO infrastructure. | ||
62 | * @ioh_gpio_reg: Memory mapped Register data is saved here | ||
63 | * when suspend. | ||
64 | * @ch: Indicate GPIO channel | ||
65 | */ | ||
66 | struct ioh_gpio { | ||
67 | void __iomem *base; | ||
68 | struct ioh_regs __iomem *reg; | ||
69 | struct device *dev; | ||
70 | struct gpio_chip gpio; | ||
71 | struct ioh_gpio_reg_data ioh_gpio_reg; | ||
72 | struct mutex lock; | ||
73 | int ch; | ||
74 | }; | ||
75 | |||
76 | static const int num_ports[] = {6, 12, 16, 16, 15, 16, 16, 12}; | ||
77 | |||
78 | static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val) | ||
79 | { | ||
80 | u32 reg_val; | ||
81 | struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); | ||
82 | |||
83 | mutex_lock(&chip->lock); | ||
84 | reg_val = ioread32(&chip->reg->regs[chip->ch].po); | ||
85 | if (val) | ||
86 | reg_val |= (1 << nr); | ||
87 | else | ||
88 | reg_val &= ~(1 << nr); | ||
89 | |||
90 | iowrite32(reg_val, &chip->reg->regs[chip->ch].po); | ||
91 | mutex_unlock(&chip->lock); | ||
92 | } | ||
93 | |||
94 | static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr) | ||
95 | { | ||
96 | struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); | ||
97 | |||
98 | return ioread32(&chip->reg->regs[chip->ch].pi) & (1 << nr); | ||
99 | } | ||
100 | |||
101 | static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, | ||
102 | int val) | ||
103 | { | ||
104 | struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); | ||
105 | u32 pm; | ||
106 | u32 reg_val; | ||
107 | |||
108 | mutex_lock(&chip->lock); | ||
109 | pm = ioread32(&chip->reg->regs[chip->ch].pm) & | ||
110 | ((1 << num_ports[chip->ch]) - 1); | ||
111 | pm |= (1 << nr); | ||
112 | iowrite32(pm, &chip->reg->regs[chip->ch].pm); | ||
113 | |||
114 | reg_val = ioread32(&chip->reg->regs[chip->ch].po); | ||
115 | if (val) | ||
116 | reg_val |= (1 << nr); | ||
117 | else | ||
118 | reg_val &= ~(1 << nr); | ||
119 | |||
120 | mutex_unlock(&chip->lock); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | ||
126 | { | ||
127 | struct ioh_gpio *chip = container_of(gpio, struct ioh_gpio, gpio); | ||
128 | u32 pm; | ||
129 | |||
130 | mutex_lock(&chip->lock); | ||
131 | pm = ioread32(&chip->reg->regs[chip->ch].pm) & | ||
132 | ((1 << num_ports[chip->ch]) - 1); | ||
133 | pm &= ~(1 << nr); | ||
134 | iowrite32(pm, &chip->reg->regs[chip->ch].pm); | ||
135 | mutex_unlock(&chip->lock); | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Save register configuration and disable interrupts. | ||
142 | */ | ||
143 | static void ioh_gpio_save_reg_conf(struct ioh_gpio *chip) | ||
144 | { | ||
145 | chip->ioh_gpio_reg.po_reg = ioread32(&chip->reg->regs[chip->ch].po); | ||
146 | chip->ioh_gpio_reg.pm_reg = ioread32(&chip->reg->regs[chip->ch].pm); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * This function restores the register configuration of the GPIO device. | ||
151 | */ | ||
152 | static void ioh_gpio_restore_reg_conf(struct ioh_gpio *chip) | ||
153 | { | ||
154 | /* to store contents of PO register */ | ||
155 | iowrite32(chip->ioh_gpio_reg.po_reg, &chip->reg->regs[chip->ch].po); | ||
156 | /* to store contents of PM register */ | ||
157 | iowrite32(chip->ioh_gpio_reg.pm_reg, &chip->reg->regs[chip->ch].pm); | ||
158 | } | ||
159 | |||
160 | static void ioh_gpio_setup(struct ioh_gpio *chip, int num_port) | ||
161 | { | ||
162 | struct gpio_chip *gpio = &chip->gpio; | ||
163 | |||
164 | gpio->label = dev_name(chip->dev); | ||
165 | gpio->owner = THIS_MODULE; | ||
166 | gpio->direction_input = ioh_gpio_direction_input; | ||
167 | gpio->get = ioh_gpio_get; | ||
168 | gpio->direction_output = ioh_gpio_direction_output; | ||
169 | gpio->set = ioh_gpio_set; | ||
170 | gpio->dbg_show = NULL; | ||
171 | gpio->base = -1; | ||
172 | gpio->ngpio = num_port; | ||
173 | gpio->can_sleep = 0; | ||
174 | } | ||
175 | |||
176 | static int __devinit ioh_gpio_probe(struct pci_dev *pdev, | ||
177 | const struct pci_device_id *id) | ||
178 | { | ||
179 | int ret; | ||
180 | int i; | ||
181 | struct ioh_gpio *chip; | ||
182 | void __iomem *base; | ||
183 | void __iomem *chip_save; | ||
184 | |||
185 | ret = pci_enable_device(pdev); | ||
186 | if (ret) { | ||
187 | dev_err(&pdev->dev, "%s : pci_enable_device failed", __func__); | ||
188 | goto err_pci_enable; | ||
189 | } | ||
190 | |||
191 | ret = pci_request_regions(pdev, KBUILD_MODNAME); | ||
192 | if (ret) { | ||
193 | dev_err(&pdev->dev, "pci_request_regions failed-%d", ret); | ||
194 | goto err_request_regions; | ||
195 | } | ||
196 | |||
197 | base = pci_iomap(pdev, 1, 0); | ||
198 | if (base == 0) { | ||
199 | dev_err(&pdev->dev, "%s : pci_iomap failed", __func__); | ||
200 | ret = -ENOMEM; | ||
201 | goto err_iomap; | ||
202 | } | ||
203 | |||
204 | chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL); | ||
205 | if (chip_save == NULL) { | ||
206 | dev_err(&pdev->dev, "%s : kzalloc failed", __func__); | ||
207 | ret = -ENOMEM; | ||
208 | goto err_kzalloc; | ||
209 | } | ||
210 | |||
211 | chip = chip_save; | ||
212 | for (i = 0; i < 8; i++, chip++) { | ||
213 | chip->dev = &pdev->dev; | ||
214 | chip->base = base; | ||
215 | chip->reg = chip->base; | ||
216 | chip->ch = i; | ||
217 | mutex_init(&chip->lock); | ||
218 | ioh_gpio_setup(chip, num_ports[i]); | ||
219 | ret = gpiochip_add(&chip->gpio); | ||
220 | if (ret) { | ||
221 | dev_err(&pdev->dev, "IOH gpio: Failed to register GPIO\n"); | ||
222 | goto err_gpiochip_add; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | chip = chip_save; | ||
227 | pci_set_drvdata(pdev, chip); | ||
228 | |||
229 | return 0; | ||
230 | |||
231 | err_gpiochip_add: | ||
232 | for (; i != 0; i--) { | ||
233 | chip--; | ||
234 | ret = gpiochip_remove(&chip->gpio); | ||
235 | if (ret) | ||
236 | dev_err(&pdev->dev, "Failed gpiochip_remove(%d)\n", i); | ||
237 | } | ||
238 | kfree(chip_save); | ||
239 | |||
240 | err_kzalloc: | ||
241 | pci_iounmap(pdev, base); | ||
242 | |||
243 | err_iomap: | ||
244 | pci_release_regions(pdev); | ||
245 | |||
246 | err_request_regions: | ||
247 | pci_disable_device(pdev); | ||
248 | |||
249 | err_pci_enable: | ||
250 | |||
251 | dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret); | ||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | static void __devexit ioh_gpio_remove(struct pci_dev *pdev) | ||
256 | { | ||
257 | int err; | ||
258 | int i; | ||
259 | struct ioh_gpio *chip = pci_get_drvdata(pdev); | ||
260 | void __iomem *chip_save; | ||
261 | |||
262 | chip_save = chip; | ||
263 | for (i = 0; i < 8; i++, chip++) { | ||
264 | err = gpiochip_remove(&chip->gpio); | ||
265 | if (err) | ||
266 | dev_err(&pdev->dev, "Failed gpiochip_remove\n"); | ||
267 | } | ||
268 | |||
269 | chip = chip_save; | ||
270 | pci_iounmap(pdev, chip->base); | ||
271 | pci_release_regions(pdev); | ||
272 | pci_disable_device(pdev); | ||
273 | kfree(chip); | ||
274 | } | ||
275 | |||
276 | #ifdef CONFIG_PM | ||
277 | static int ioh_gpio_suspend(struct pci_dev *pdev, pm_message_t state) | ||
278 | { | ||
279 | s32 ret; | ||
280 | struct ioh_gpio *chip = pci_get_drvdata(pdev); | ||
281 | |||
282 | ioh_gpio_save_reg_conf(chip); | ||
283 | ioh_gpio_restore_reg_conf(chip); | ||
284 | |||
285 | ret = pci_save_state(pdev); | ||
286 | if (ret) { | ||
287 | dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret); | ||
288 | return ret; | ||
289 | } | ||
290 | pci_disable_device(pdev); | ||
291 | pci_set_power_state(pdev, PCI_D0); | ||
292 | ret = pci_enable_wake(pdev, PCI_D0, 1); | ||
293 | if (ret) | ||
294 | dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int ioh_gpio_resume(struct pci_dev *pdev) | ||
300 | { | ||
301 | s32 ret; | ||
302 | struct ioh_gpio *chip = pci_get_drvdata(pdev); | ||
303 | |||
304 | ret = pci_enable_wake(pdev, PCI_D0, 0); | ||
305 | |||
306 | pci_set_power_state(pdev, PCI_D0); | ||
307 | ret = pci_enable_device(pdev); | ||
308 | if (ret) { | ||
309 | dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret); | ||
310 | return ret; | ||
311 | } | ||
312 | pci_restore_state(pdev); | ||
313 | |||
314 | iowrite32(0x01, &chip->reg->srst); | ||
315 | iowrite32(0x00, &chip->reg->srst); | ||
316 | ioh_gpio_restore_reg_conf(chip); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | #else | ||
321 | #define ioh_gpio_suspend NULL | ||
322 | #define ioh_gpio_resume NULL | ||
323 | #endif | ||
324 | |||
325 | static DEFINE_PCI_DEVICE_TABLE(ioh_gpio_pcidev_id) = { | ||
326 | { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x802E) }, | ||
327 | { 0, } | ||
328 | }; | ||
329 | |||
330 | static struct pci_driver ioh_gpio_driver = { | ||
331 | .name = "ml_ioh_gpio", | ||
332 | .id_table = ioh_gpio_pcidev_id, | ||
333 | .probe = ioh_gpio_probe, | ||
334 | .remove = __devexit_p(ioh_gpio_remove), | ||
335 | .suspend = ioh_gpio_suspend, | ||
336 | .resume = ioh_gpio_resume | ||
337 | }; | ||
338 | |||
339 | static int __init ioh_gpio_pci_init(void) | ||
340 | { | ||
341 | return pci_register_driver(&ioh_gpio_driver); | ||
342 | } | ||
343 | module_init(ioh_gpio_pci_init); | ||
344 | |||
345 | static void __exit ioh_gpio_pci_exit(void) | ||
346 | { | ||
347 | pci_unregister_driver(&ioh_gpio_driver); | ||
348 | } | ||
349 | module_exit(ioh_gpio_pci_exit); | ||
350 | |||
351 | MODULE_DESCRIPTION("OKI SEMICONDUCTOR ML-IOH series GPIO Driver"); | ||
352 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 501866662e05..a261972f603d 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
@@ -228,30 +228,30 @@ static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off) | |||
228 | return chip->irq_base + off; | 228 | return chip->irq_base + off; |
229 | } | 229 | } |
230 | 230 | ||
231 | static void pca953x_irq_mask(unsigned int irq) | 231 | static void pca953x_irq_mask(struct irq_data *d) |
232 | { | 232 | { |
233 | struct pca953x_chip *chip = get_irq_chip_data(irq); | 233 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
234 | 234 | ||
235 | chip->irq_mask &= ~(1 << (irq - chip->irq_base)); | 235 | chip->irq_mask &= ~(1 << (d->irq - chip->irq_base)); |
236 | } | 236 | } |
237 | 237 | ||
238 | static void pca953x_irq_unmask(unsigned int irq) | 238 | static void pca953x_irq_unmask(struct irq_data *d) |
239 | { | 239 | { |
240 | struct pca953x_chip *chip = get_irq_chip_data(irq); | 240 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
241 | 241 | ||
242 | chip->irq_mask |= 1 << (irq - chip->irq_base); | 242 | chip->irq_mask |= 1 << (d->irq - chip->irq_base); |
243 | } | 243 | } |
244 | 244 | ||
245 | static void pca953x_irq_bus_lock(unsigned int irq) | 245 | static void pca953x_irq_bus_lock(struct irq_data *d) |
246 | { | 246 | { |
247 | struct pca953x_chip *chip = get_irq_chip_data(irq); | 247 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
248 | 248 | ||
249 | mutex_lock(&chip->irq_lock); | 249 | mutex_lock(&chip->irq_lock); |
250 | } | 250 | } |
251 | 251 | ||
252 | static void pca953x_irq_bus_sync_unlock(unsigned int irq) | 252 | static void pca953x_irq_bus_sync_unlock(struct irq_data *d) |
253 | { | 253 | { |
254 | struct pca953x_chip *chip = get_irq_chip_data(irq); | 254 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
255 | uint16_t new_irqs; | 255 | uint16_t new_irqs; |
256 | uint16_t level; | 256 | uint16_t level; |
257 | 257 | ||
@@ -268,15 +268,15 @@ static void pca953x_irq_bus_sync_unlock(unsigned int irq) | |||
268 | mutex_unlock(&chip->irq_lock); | 268 | mutex_unlock(&chip->irq_lock); |
269 | } | 269 | } |
270 | 270 | ||
271 | static int pca953x_irq_set_type(unsigned int irq, unsigned int type) | 271 | static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) |
272 | { | 272 | { |
273 | struct pca953x_chip *chip = get_irq_chip_data(irq); | 273 | struct pca953x_chip *chip = irq_data_get_irq_chip_data(d); |
274 | uint16_t level = irq - chip->irq_base; | 274 | uint16_t level = d->irq - chip->irq_base; |
275 | uint16_t mask = 1 << level; | 275 | uint16_t mask = 1 << level; |
276 | 276 | ||
277 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { | 277 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { |
278 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", | 278 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", |
279 | irq, type); | 279 | d->irq, type); |
280 | return -EINVAL; | 280 | return -EINVAL; |
281 | } | 281 | } |
282 | 282 | ||
@@ -295,11 +295,11 @@ static int pca953x_irq_set_type(unsigned int irq, unsigned int type) | |||
295 | 295 | ||
296 | static struct irq_chip pca953x_irq_chip = { | 296 | static struct irq_chip pca953x_irq_chip = { |
297 | .name = "pca953x", | 297 | .name = "pca953x", |
298 | .mask = pca953x_irq_mask, | 298 | .irq_mask = pca953x_irq_mask, |
299 | .unmask = pca953x_irq_unmask, | 299 | .irq_unmask = pca953x_irq_unmask, |
300 | .bus_lock = pca953x_irq_bus_lock, | 300 | .irq_bus_lock = pca953x_irq_bus_lock, |
301 | .bus_sync_unlock = pca953x_irq_bus_sync_unlock, | 301 | .irq_bus_sync_unlock = pca953x_irq_bus_sync_unlock, |
302 | .set_type = pca953x_irq_set_type, | 302 | .irq_set_type = pca953x_irq_set_type, |
303 | }; | 303 | }; |
304 | 304 | ||
305 | static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) | 305 | static uint16_t pca953x_irq_pending(struct pca953x_chip *chip) |
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 5005990f751f..2975d22daffe 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c | |||
@@ -129,10 +129,10 @@ static int pl061_to_irq(struct gpio_chip *gc, unsigned offset) | |||
129 | /* | 129 | /* |
130 | * PL061 GPIO IRQ | 130 | * PL061 GPIO IRQ |
131 | */ | 131 | */ |
132 | static void pl061_irq_disable(unsigned irq) | 132 | static void pl061_irq_disable(struct irq_data *d) |
133 | { | 133 | { |
134 | struct pl061_gpio *chip = get_irq_chip_data(irq); | 134 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); |
135 | int offset = irq - chip->irq_base; | 135 | int offset = d->irq - chip->irq_base; |
136 | unsigned long flags; | 136 | unsigned long flags; |
137 | u8 gpioie; | 137 | u8 gpioie; |
138 | 138 | ||
@@ -143,10 +143,10 @@ static void pl061_irq_disable(unsigned irq) | |||
143 | spin_unlock_irqrestore(&chip->irq_lock, flags); | 143 | spin_unlock_irqrestore(&chip->irq_lock, flags); |
144 | } | 144 | } |
145 | 145 | ||
146 | static void pl061_irq_enable(unsigned irq) | 146 | static void pl061_irq_enable(struct irq_data *d) |
147 | { | 147 | { |
148 | struct pl061_gpio *chip = get_irq_chip_data(irq); | 148 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); |
149 | int offset = irq - chip->irq_base; | 149 | int offset = d->irq - chip->irq_base; |
150 | unsigned long flags; | 150 | unsigned long flags; |
151 | u8 gpioie; | 151 | u8 gpioie; |
152 | 152 | ||
@@ -157,10 +157,10 @@ static void pl061_irq_enable(unsigned irq) | |||
157 | spin_unlock_irqrestore(&chip->irq_lock, flags); | 157 | spin_unlock_irqrestore(&chip->irq_lock, flags); |
158 | } | 158 | } |
159 | 159 | ||
160 | static int pl061_irq_type(unsigned irq, unsigned trigger) | 160 | static int pl061_irq_type(struct irq_data *d, unsigned trigger) |
161 | { | 161 | { |
162 | struct pl061_gpio *chip = get_irq_chip_data(irq); | 162 | struct pl061_gpio *chip = irq_data_get_irq_chip_data(d); |
163 | int offset = irq - chip->irq_base; | 163 | int offset = d->irq - chip->irq_base; |
164 | unsigned long flags; | 164 | unsigned long flags; |
165 | u8 gpiois, gpioibe, gpioiev; | 165 | u8 gpiois, gpioibe, gpioiev; |
166 | 166 | ||
@@ -203,9 +203,9 @@ static int pl061_irq_type(unsigned irq, unsigned trigger) | |||
203 | 203 | ||
204 | static struct irq_chip pl061_irqchip = { | 204 | static struct irq_chip pl061_irqchip = { |
205 | .name = "GPIO", | 205 | .name = "GPIO", |
206 | .enable = pl061_irq_enable, | 206 | .irq_enable = pl061_irq_enable, |
207 | .disable = pl061_irq_disable, | 207 | .irq_disable = pl061_irq_disable, |
208 | .set_type = pl061_irq_type, | 208 | .irq_set_type = pl061_irq_type, |
209 | }; | 209 | }; |
210 | 210 | ||
211 | static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | 211 | static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) |
@@ -214,7 +214,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
214 | struct list_head *ptr; | 214 | struct list_head *ptr; |
215 | struct pl061_gpio *chip; | 215 | struct pl061_gpio *chip; |
216 | 216 | ||
217 | desc->chip->ack(irq); | 217 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
218 | list_for_each(ptr, chip_list) { | 218 | list_for_each(ptr, chip_list) { |
219 | unsigned long pending; | 219 | unsigned long pending; |
220 | int offset; | 220 | int offset; |
@@ -229,7 +229,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc) | |||
229 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) | 229 | for_each_set_bit(offset, &pending, PL061_GPIO_NR) |
230 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); | 230 | generic_handle_irq(pl061_to_irq(&chip->gc, offset)); |
231 | } | 231 | } |
232 | desc->chip->unmask(irq); | 232 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
233 | } | 233 | } |
234 | 234 | ||
235 | static int pl061_probe(struct amba_device *dev, struct amba_id *id) | 235 | static int pl061_probe(struct amba_device *dev, struct amba_id *id) |
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c index 7c9e6a052c45..eb2901f8ab5e 100644 --- a/drivers/gpio/stmpe-gpio.c +++ b/drivers/gpio/stmpe-gpio.c | |||
@@ -122,10 +122,10 @@ static struct gpio_chip template_chip = { | |||
122 | .can_sleep = 1, | 122 | .can_sleep = 1, |
123 | }; | 123 | }; |
124 | 124 | ||
125 | static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type) | 125 | static int stmpe_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
126 | { | 126 | { |
127 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | 127 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
128 | int offset = irq - stmpe_gpio->irq_base; | 128 | int offset = d->irq - stmpe_gpio->irq_base; |
129 | int regoffset = offset / 8; | 129 | int regoffset = offset / 8; |
130 | int mask = 1 << (offset % 8); | 130 | int mask = 1 << (offset % 8); |
131 | 131 | ||
@@ -145,16 +145,16 @@ static int stmpe_gpio_irq_set_type(unsigned int irq, unsigned int type) | |||
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
147 | 147 | ||
148 | static void stmpe_gpio_irq_lock(unsigned int irq) | 148 | static void stmpe_gpio_irq_lock(struct irq_data *d) |
149 | { | 149 | { |
150 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | 150 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
151 | 151 | ||
152 | mutex_lock(&stmpe_gpio->irq_lock); | 152 | mutex_lock(&stmpe_gpio->irq_lock); |
153 | } | 153 | } |
154 | 154 | ||
155 | static void stmpe_gpio_irq_sync_unlock(unsigned int irq) | 155 | static void stmpe_gpio_irq_sync_unlock(struct irq_data *d) |
156 | { | 156 | { |
157 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | 157 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
158 | struct stmpe *stmpe = stmpe_gpio->stmpe; | 158 | struct stmpe *stmpe = stmpe_gpio->stmpe; |
159 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); | 159 | int num_banks = DIV_ROUND_UP(stmpe->num_gpios, 8); |
160 | static const u8 regmap[] = { | 160 | static const u8 regmap[] = { |
@@ -180,20 +180,20 @@ static void stmpe_gpio_irq_sync_unlock(unsigned int irq) | |||
180 | mutex_unlock(&stmpe_gpio->irq_lock); | 180 | mutex_unlock(&stmpe_gpio->irq_lock); |
181 | } | 181 | } |
182 | 182 | ||
183 | static void stmpe_gpio_irq_mask(unsigned int irq) | 183 | static void stmpe_gpio_irq_mask(struct irq_data *d) |
184 | { | 184 | { |
185 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | 185 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
186 | int offset = irq - stmpe_gpio->irq_base; | 186 | int offset = d->irq - stmpe_gpio->irq_base; |
187 | int regoffset = offset / 8; | 187 | int regoffset = offset / 8; |
188 | int mask = 1 << (offset % 8); | 188 | int mask = 1 << (offset % 8); |
189 | 189 | ||
190 | stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; | 190 | stmpe_gpio->regs[REG_IE][regoffset] &= ~mask; |
191 | } | 191 | } |
192 | 192 | ||
193 | static void stmpe_gpio_irq_unmask(unsigned int irq) | 193 | static void stmpe_gpio_irq_unmask(struct irq_data *d) |
194 | { | 194 | { |
195 | struct stmpe_gpio *stmpe_gpio = get_irq_chip_data(irq); | 195 | struct stmpe_gpio *stmpe_gpio = irq_data_get_irq_chip_data(d); |
196 | int offset = irq - stmpe_gpio->irq_base; | 196 | int offset = d->irq - stmpe_gpio->irq_base; |
197 | int regoffset = offset / 8; | 197 | int regoffset = offset / 8; |
198 | int mask = 1 << (offset % 8); | 198 | int mask = 1 << (offset % 8); |
199 | 199 | ||
@@ -202,11 +202,11 @@ static void stmpe_gpio_irq_unmask(unsigned int irq) | |||
202 | 202 | ||
203 | static struct irq_chip stmpe_gpio_irq_chip = { | 203 | static struct irq_chip stmpe_gpio_irq_chip = { |
204 | .name = "stmpe-gpio", | 204 | .name = "stmpe-gpio", |
205 | .bus_lock = stmpe_gpio_irq_lock, | 205 | .irq_bus_lock = stmpe_gpio_irq_lock, |
206 | .bus_sync_unlock = stmpe_gpio_irq_sync_unlock, | 206 | .irq_bus_sync_unlock = stmpe_gpio_irq_sync_unlock, |
207 | .mask = stmpe_gpio_irq_mask, | 207 | .irq_mask = stmpe_gpio_irq_mask, |
208 | .unmask = stmpe_gpio_irq_unmask, | 208 | .irq_unmask = stmpe_gpio_irq_unmask, |
209 | .set_type = stmpe_gpio_irq_set_type, | 209 | .irq_set_type = stmpe_gpio_irq_set_type, |
210 | }; | 210 | }; |
211 | 211 | ||
212 | static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | 212 | static irqreturn_t stmpe_gpio_irq(int irq, void *dev) |
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c index 823559ab0e24..e60be0015c9b 100644 --- a/drivers/gpio/sx150x.c +++ b/drivers/gpio/sx150x.c | |||
@@ -304,36 +304,36 @@ static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
304 | return chip->irq_base + offset; | 304 | return chip->irq_base + offset; |
305 | } | 305 | } |
306 | 306 | ||
307 | static void sx150x_irq_mask(unsigned int irq) | 307 | static void sx150x_irq_mask(struct irq_data *d) |
308 | { | 308 | { |
309 | struct irq_chip *ic = get_irq_chip(irq); | 309 | struct irq_chip *ic = irq_data_get_irq_chip(d); |
310 | struct sx150x_chip *chip; | 310 | struct sx150x_chip *chip; |
311 | unsigned n; | 311 | unsigned n; |
312 | 312 | ||
313 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 313 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
314 | n = irq - chip->irq_base; | 314 | n = d->irq - chip->irq_base; |
315 | 315 | ||
316 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); | 316 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); |
317 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); | 317 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); |
318 | } | 318 | } |
319 | 319 | ||
320 | static void sx150x_irq_unmask(unsigned int irq) | 320 | static void sx150x_irq_unmask(struct irq_data *d) |
321 | { | 321 | { |
322 | struct irq_chip *ic = get_irq_chip(irq); | 322 | struct irq_chip *ic = irq_data_get_irq_chip(d); |
323 | struct sx150x_chip *chip; | 323 | struct sx150x_chip *chip; |
324 | unsigned n; | 324 | unsigned n; |
325 | 325 | ||
326 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 326 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
327 | n = irq - chip->irq_base; | 327 | n = d->irq - chip->irq_base; |
328 | 328 | ||
329 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); | 329 | sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); |
330 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, | 330 | sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, |
331 | chip->irq_sense >> (n * 2)); | 331 | chip->irq_sense >> (n * 2)); |
332 | } | 332 | } |
333 | 333 | ||
334 | static int sx150x_irq_set_type(unsigned int irq, unsigned int flow_type) | 334 | static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) |
335 | { | 335 | { |
336 | struct irq_chip *ic = get_irq_chip(irq); | 336 | struct irq_chip *ic = irq_data_get_irq_chip(d); |
337 | struct sx150x_chip *chip; | 337 | struct sx150x_chip *chip; |
338 | unsigned n, val = 0; | 338 | unsigned n, val = 0; |
339 | 339 | ||
@@ -341,7 +341,7 @@ static int sx150x_irq_set_type(unsigned int irq, unsigned int flow_type) | |||
341 | return -EINVAL; | 341 | return -EINVAL; |
342 | 342 | ||
343 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 343 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
344 | n = irq - chip->irq_base; | 344 | n = d->irq - chip->irq_base; |
345 | 345 | ||
346 | if (flow_type & IRQ_TYPE_EDGE_RISING) | 346 | if (flow_type & IRQ_TYPE_EDGE_RISING) |
347 | val |= 0x1; | 347 | val |= 0x1; |
@@ -386,9 +386,9 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) | |||
386 | return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); | 386 | return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); |
387 | } | 387 | } |
388 | 388 | ||
389 | static void sx150x_irq_bus_lock(unsigned int irq) | 389 | static void sx150x_irq_bus_lock(struct irq_data *d) |
390 | { | 390 | { |
391 | struct irq_chip *ic = get_irq_chip(irq); | 391 | struct irq_chip *ic = irq_data_get_irq_chip(d); |
392 | struct sx150x_chip *chip; | 392 | struct sx150x_chip *chip; |
393 | 393 | ||
394 | chip = container_of(ic, struct sx150x_chip, irq_chip); | 394 | chip = container_of(ic, struct sx150x_chip, irq_chip); |
@@ -396,9 +396,9 @@ static void sx150x_irq_bus_lock(unsigned int irq) | |||
396 | mutex_lock(&chip->lock); | 396 | mutex_lock(&chip->lock); |
397 | } | 397 | } |
398 | 398 | ||
399 | static void sx150x_irq_bus_sync_unlock(unsigned int irq) | 399 | static void sx150x_irq_bus_sync_unlock(struct irq_data *d) |
400 | { | 400 | { |
401 | struct irq_chip *ic = get_irq_chip(irq); | 401 | struct irq_chip *ic = irq_data_get_irq_chip(d); |
402 | struct sx150x_chip *chip; | 402 | struct sx150x_chip *chip; |
403 | unsigned n; | 403 | unsigned n; |
404 | 404 | ||
@@ -437,16 +437,16 @@ static void sx150x_init_chip(struct sx150x_chip *chip, | |||
437 | if (pdata->oscio_is_gpo) | 437 | if (pdata->oscio_is_gpo) |
438 | ++chip->gpio_chip.ngpio; | 438 | ++chip->gpio_chip.ngpio; |
439 | 439 | ||
440 | chip->irq_chip.name = client->name; | 440 | chip->irq_chip.name = client->name; |
441 | chip->irq_chip.mask = sx150x_irq_mask; | 441 | chip->irq_chip.irq_mask = sx150x_irq_mask; |
442 | chip->irq_chip.unmask = sx150x_irq_unmask; | 442 | chip->irq_chip.irq_unmask = sx150x_irq_unmask; |
443 | chip->irq_chip.set_type = sx150x_irq_set_type; | 443 | chip->irq_chip.irq_set_type = sx150x_irq_set_type; |
444 | chip->irq_chip.bus_lock = sx150x_irq_bus_lock; | 444 | chip->irq_chip.irq_bus_lock = sx150x_irq_bus_lock; |
445 | chip->irq_chip.bus_sync_unlock = sx150x_irq_bus_sync_unlock; | 445 | chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; |
446 | chip->irq_summary = -1; | 446 | chip->irq_summary = -1; |
447 | chip->irq_base = -1; | 447 | chip->irq_base = -1; |
448 | chip->irq_sense = 0; | 448 | chip->irq_sense = 0; |
449 | chip->irq_set_type_pending = 0; | 449 | chip->irq_set_type_pending = 0; |
450 | } | 450 | } |
451 | 451 | ||
452 | static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) | 452 | static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) |
diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c index 180d584454fb..27200af1a595 100644 --- a/drivers/gpio/tc3589x-gpio.c +++ b/drivers/gpio/tc3589x-gpio.c | |||
@@ -110,10 +110,10 @@ static struct gpio_chip template_chip = { | |||
110 | .can_sleep = 1, | 110 | .can_sleep = 1, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | static int tc3589x_gpio_irq_set_type(unsigned int irq, unsigned int type) | 113 | static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
114 | { | 114 | { |
115 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | 115 | struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
116 | int offset = irq - tc3589x_gpio->irq_base; | 116 | int offset = d->irq - tc3589x_gpio->irq_base; |
117 | int regoffset = offset / 8; | 117 | int regoffset = offset / 8; |
118 | int mask = 1 << (offset % 8); | 118 | int mask = 1 << (offset % 8); |
119 | 119 | ||
@@ -137,16 +137,16 @@ static int tc3589x_gpio_irq_set_type(unsigned int irq, unsigned int type) | |||
137 | return 0; | 137 | return 0; |
138 | } | 138 | } |
139 | 139 | ||
140 | static void tc3589x_gpio_irq_lock(unsigned int irq) | 140 | static void tc3589x_gpio_irq_lock(struct irq_data *d) |
141 | { | 141 | { |
142 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | 142 | struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
143 | 143 | ||
144 | mutex_lock(&tc3589x_gpio->irq_lock); | 144 | mutex_lock(&tc3589x_gpio->irq_lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | static void tc3589x_gpio_irq_sync_unlock(unsigned int irq) | 147 | static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) |
148 | { | 148 | { |
149 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | 149 | struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
150 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; | 150 | struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; |
151 | static const u8 regmap[] = { | 151 | static const u8 regmap[] = { |
152 | [REG_IBE] = TC3589x_GPIOIBE0, | 152 | [REG_IBE] = TC3589x_GPIOIBE0, |
@@ -172,20 +172,20 @@ static void tc3589x_gpio_irq_sync_unlock(unsigned int irq) | |||
172 | mutex_unlock(&tc3589x_gpio->irq_lock); | 172 | mutex_unlock(&tc3589x_gpio->irq_lock); |
173 | } | 173 | } |
174 | 174 | ||
175 | static void tc3589x_gpio_irq_mask(unsigned int irq) | 175 | static void tc3589x_gpio_irq_mask(struct irq_data *d) |
176 | { | 176 | { |
177 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | 177 | struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
178 | int offset = irq - tc3589x_gpio->irq_base; | 178 | int offset = d->irq - tc3589x_gpio->irq_base; |
179 | int regoffset = offset / 8; | 179 | int regoffset = offset / 8; |
180 | int mask = 1 << (offset % 8); | 180 | int mask = 1 << (offset % 8); |
181 | 181 | ||
182 | tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; | 182 | tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; |
183 | } | 183 | } |
184 | 184 | ||
185 | static void tc3589x_gpio_irq_unmask(unsigned int irq) | 185 | static void tc3589x_gpio_irq_unmask(struct irq_data *d) |
186 | { | 186 | { |
187 | struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); | 187 | struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
188 | int offset = irq - tc3589x_gpio->irq_base; | 188 | int offset = d->irq - tc3589x_gpio->irq_base; |
189 | int regoffset = offset / 8; | 189 | int regoffset = offset / 8; |
190 | int mask = 1 << (offset % 8); | 190 | int mask = 1 << (offset % 8); |
191 | 191 | ||
@@ -194,11 +194,11 @@ static void tc3589x_gpio_irq_unmask(unsigned int irq) | |||
194 | 194 | ||
195 | static struct irq_chip tc3589x_gpio_irq_chip = { | 195 | static struct irq_chip tc3589x_gpio_irq_chip = { |
196 | .name = "tc3589x-gpio", | 196 | .name = "tc3589x-gpio", |
197 | .bus_lock = tc3589x_gpio_irq_lock, | 197 | .irq_bus_lock = tc3589x_gpio_irq_lock, |
198 | .bus_sync_unlock = tc3589x_gpio_irq_sync_unlock, | 198 | .irq_bus_sync_unlock = tc3589x_gpio_irq_sync_unlock, |
199 | .mask = tc3589x_gpio_irq_mask, | 199 | .irq_mask = tc3589x_gpio_irq_mask, |
200 | .unmask = tc3589x_gpio_irq_unmask, | 200 | .irq_unmask = tc3589x_gpio_irq_unmask, |
201 | .set_type = tc3589x_gpio_irq_set_type, | 201 | .irq_set_type = tc3589x_gpio_irq_set_type, |
202 | }; | 202 | }; |
203 | 203 | ||
204 | static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) | 204 | static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) |
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c index 45293662e950..349131eb1ce0 100644 --- a/drivers/gpio/timbgpio.c +++ b/drivers/gpio/timbgpio.c | |||
@@ -109,10 +109,10 @@ static int timbgpio_to_irq(struct gpio_chip *gpio, unsigned offset) | |||
109 | /* | 109 | /* |
110 | * GPIO IRQ | 110 | * GPIO IRQ |
111 | */ | 111 | */ |
112 | static void timbgpio_irq_disable(unsigned irq) | 112 | static void timbgpio_irq_disable(struct irq_data *d) |
113 | { | 113 | { |
114 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 114 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); |
115 | int offset = irq - tgpio->irq_base; | 115 | int offset = d->irq - tgpio->irq_base; |
116 | unsigned long flags; | 116 | unsigned long flags; |
117 | 117 | ||
118 | spin_lock_irqsave(&tgpio->lock, flags); | 118 | spin_lock_irqsave(&tgpio->lock, flags); |
@@ -121,10 +121,10 @@ static void timbgpio_irq_disable(unsigned irq) | |||
121 | spin_unlock_irqrestore(&tgpio->lock, flags); | 121 | spin_unlock_irqrestore(&tgpio->lock, flags); |
122 | } | 122 | } |
123 | 123 | ||
124 | static void timbgpio_irq_enable(unsigned irq) | 124 | static void timbgpio_irq_enable(struct irq_data *d) |
125 | { | 125 | { |
126 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 126 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); |
127 | int offset = irq - tgpio->irq_base; | 127 | int offset = d->irq - tgpio->irq_base; |
128 | unsigned long flags; | 128 | unsigned long flags; |
129 | 129 | ||
130 | spin_lock_irqsave(&tgpio->lock, flags); | 130 | spin_lock_irqsave(&tgpio->lock, flags); |
@@ -133,10 +133,10 @@ static void timbgpio_irq_enable(unsigned irq) | |||
133 | spin_unlock_irqrestore(&tgpio->lock, flags); | 133 | spin_unlock_irqrestore(&tgpio->lock, flags); |
134 | } | 134 | } |
135 | 135 | ||
136 | static int timbgpio_irq_type(unsigned irq, unsigned trigger) | 136 | static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) |
137 | { | 137 | { |
138 | struct timbgpio *tgpio = get_irq_chip_data(irq); | 138 | struct timbgpio *tgpio = irq_data_get_irq_chip_data(d); |
139 | int offset = irq - tgpio->irq_base; | 139 | int offset = d->irq - tgpio->irq_base; |
140 | unsigned long flags; | 140 | unsigned long flags; |
141 | u32 lvr, flr, bflr = 0; | 141 | u32 lvr, flr, bflr = 0; |
142 | u32 ver; | 142 | u32 ver; |
@@ -193,13 +193,13 @@ out: | |||
193 | return ret; | 193 | return ret; |
194 | } | 194 | } |
195 | 195 | ||
196 | static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) | 196 | static void timbgpio_irq(struct irq_data *d, struct irq_desc *desc) |
197 | { | 197 | { |
198 | struct timbgpio *tgpio = get_irq_data(irq); | 198 | struct timbgpio *tgpio = irq_data_get_irq_data(d); |
199 | unsigned long ipr; | 199 | unsigned long ipr; |
200 | int offset; | 200 | int offset; |
201 | 201 | ||
202 | desc->chip->ack(irq); | 202 | desc->irq_data.chip->ack(irq_get_irq_data(d)); |
203 | ipr = ioread32(tgpio->membase + TGPIO_IPR); | 203 | ipr = ioread32(tgpio->membase + TGPIO_IPR); |
204 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); | 204 | iowrite32(ipr, tgpio->membase + TGPIO_ICR); |
205 | 205 | ||
@@ -217,9 +217,9 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) | |||
217 | 217 | ||
218 | static struct irq_chip timbgpio_irqchip = { | 218 | static struct irq_chip timbgpio_irqchip = { |
219 | .name = "GPIO", | 219 | .name = "GPIO", |
220 | .enable = timbgpio_irq_enable, | 220 | .irq_enable = timbgpio_irq_enable, |
221 | .disable = timbgpio_irq_disable, | 221 | .irq_disable = timbgpio_irq_disable, |
222 | .set_type = timbgpio_irq_type, | 222 | .irq_set_type = timbgpio_irq_type, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static int __devinit timbgpio_probe(struct platform_device *pdev) | 225 | static int __devinit timbgpio_probe(struct platform_device *pdev) |
diff --git a/drivers/gpio/vr41xx_giu.c b/drivers/gpio/vr41xx_giu.c index b16c9a8c03f5..cffa3bd7ad3b 100644 --- a/drivers/gpio/vr41xx_giu.c +++ b/drivers/gpio/vr41xx_giu.c | |||
@@ -111,69 +111,69 @@ static inline u16 giu_clear(u16 offset, u16 clear) | |||
111 | return data; | 111 | return data; |
112 | } | 112 | } |
113 | 113 | ||
114 | static void ack_giuint_low(unsigned int irq) | 114 | static void ack_giuint_low(struct irq_data *d) |
115 | { | 115 | { |
116 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); | 116 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(d->irq)); |
117 | } | 117 | } |
118 | 118 | ||
119 | static void mask_giuint_low(unsigned int irq) | 119 | static void mask_giuint_low(struct irq_data *d) |
120 | { | 120 | { |
121 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | 121 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq)); |
122 | } | 122 | } |
123 | 123 | ||
124 | static void mask_ack_giuint_low(unsigned int irq) | 124 | static void mask_ack_giuint_low(struct irq_data *d) |
125 | { | 125 | { |
126 | unsigned int pin; | 126 | unsigned int pin; |
127 | 127 | ||
128 | pin = GPIO_PIN_OF_IRQ(irq); | 128 | pin = GPIO_PIN_OF_IRQ(d->irq); |
129 | giu_clear(GIUINTENL, 1 << pin); | 129 | giu_clear(GIUINTENL, 1 << pin); |
130 | giu_write(GIUINTSTATL, 1 << pin); | 130 | giu_write(GIUINTSTATL, 1 << pin); |
131 | } | 131 | } |
132 | 132 | ||
133 | static void unmask_giuint_low(unsigned int irq) | 133 | static void unmask_giuint_low(struct irq_data *d) |
134 | { | 134 | { |
135 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | 135 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(d->irq)); |
136 | } | 136 | } |
137 | 137 | ||
138 | static struct irq_chip giuint_low_irq_chip = { | 138 | static struct irq_chip giuint_low_irq_chip = { |
139 | .name = "GIUINTL", | 139 | .name = "GIUINTL", |
140 | .ack = ack_giuint_low, | 140 | .irq_ack = ack_giuint_low, |
141 | .mask = mask_giuint_low, | 141 | .irq_mask = mask_giuint_low, |
142 | .mask_ack = mask_ack_giuint_low, | 142 | .irq_mask_ack = mask_ack_giuint_low, |
143 | .unmask = unmask_giuint_low, | 143 | .irq_unmask = unmask_giuint_low, |
144 | }; | 144 | }; |
145 | 145 | ||
146 | static void ack_giuint_high(unsigned int irq) | 146 | static void ack_giuint_high(struct irq_data *d) |
147 | { | 147 | { |
148 | giu_write(GIUINTSTATH, | 148 | giu_write(GIUINTSTATH, |
149 | 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | 149 | 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); |
150 | } | 150 | } |
151 | 151 | ||
152 | static void mask_giuint_high(unsigned int irq) | 152 | static void mask_giuint_high(struct irq_data *d) |
153 | { | 153 | { |
154 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | 154 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); |
155 | } | 155 | } |
156 | 156 | ||
157 | static void mask_ack_giuint_high(unsigned int irq) | 157 | static void mask_ack_giuint_high(struct irq_data *d) |
158 | { | 158 | { |
159 | unsigned int pin; | 159 | unsigned int pin; |
160 | 160 | ||
161 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | 161 | pin = GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET; |
162 | giu_clear(GIUINTENH, 1 << pin); | 162 | giu_clear(GIUINTENH, 1 << pin); |
163 | giu_write(GIUINTSTATH, 1 << pin); | 163 | giu_write(GIUINTSTATH, 1 << pin); |
164 | } | 164 | } |
165 | 165 | ||
166 | static void unmask_giuint_high(unsigned int irq) | 166 | static void unmask_giuint_high(struct irq_data *d) |
167 | { | 167 | { |
168 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | 168 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(d->irq) - GIUINT_HIGH_OFFSET)); |
169 | } | 169 | } |
170 | 170 | ||
171 | static struct irq_chip giuint_high_irq_chip = { | 171 | static struct irq_chip giuint_high_irq_chip = { |
172 | .name = "GIUINTH", | 172 | .name = "GIUINTH", |
173 | .ack = ack_giuint_high, | 173 | .irq_ack = ack_giuint_high, |
174 | .mask = mask_giuint_high, | 174 | .irq_mask = mask_giuint_high, |
175 | .mask_ack = mask_ack_giuint_high, | 175 | .irq_mask_ack = mask_ack_giuint_high, |
176 | .unmask = unmask_giuint_high, | 176 | .irq_unmask = unmask_giuint_high, |
177 | }; | 177 | }; |
178 | 178 | ||
179 | static int giu_get_irq(unsigned int irq) | 179 | static int giu_get_irq(unsigned int irq) |
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c index 618398e4ed8e..c822baacd8fc 100644 --- a/drivers/gpio/wm8994-gpio.c +++ b/drivers/gpio/wm8994-gpio.c | |||
@@ -35,6 +35,29 @@ static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip) | |||
35 | return container_of(chip, struct wm8994_gpio, gpio_chip); | 35 | return container_of(chip, struct wm8994_gpio, gpio_chip); |
36 | } | 36 | } |
37 | 37 | ||
38 | static int wm8994_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
39 | { | ||
40 | struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); | ||
41 | struct wm8994 *wm8994 = wm8994_gpio->wm8994; | ||
42 | |||
43 | switch (wm8994->type) { | ||
44 | case WM8958: | ||
45 | switch (offset) { | ||
46 | case 1: | ||
47 | case 2: | ||
48 | case 3: | ||
49 | case 4: | ||
50 | case 6: | ||
51 | return -EINVAL; | ||
52 | } | ||
53 | break; | ||
54 | default: | ||
55 | break; | ||
56 | } | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
38 | static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | 61 | static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset) |
39 | { | 62 | { |
40 | struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); | 63 | struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); |
@@ -136,6 +159,7 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
136 | static struct gpio_chip template_chip = { | 159 | static struct gpio_chip template_chip = { |
137 | .label = "wm8994", | 160 | .label = "wm8994", |
138 | .owner = THIS_MODULE, | 161 | .owner = THIS_MODULE, |
162 | .request = wm8994_gpio_request, | ||
139 | .direction_input = wm8994_gpio_direction_in, | 163 | .direction_input = wm8994_gpio_direction_in, |
140 | .get = wm8994_gpio_get, | 164 | .get = wm8994_gpio_get, |
141 | .direction_output = wm8994_gpio_direction_out, | 165 | .direction_output = wm8994_gpio_direction_out, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index b14c81110575..d3a9c6e02477 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c | |||
@@ -59,7 +59,7 @@ static int nv40_set_intensity(struct backlight_device *bd) | |||
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
61 | 61 | ||
62 | static struct backlight_ops nv40_bl_ops = { | 62 | static const struct backlight_ops nv40_bl_ops = { |
63 | .options = BL_CORE_SUSPENDRESUME, | 63 | .options = BL_CORE_SUSPENDRESUME, |
64 | .get_brightness = nv40_get_intensity, | 64 | .get_brightness = nv40_get_intensity, |
65 | .update_status = nv40_set_intensity, | 65 | .update_status = nv40_set_intensity, |
@@ -82,7 +82,7 @@ static int nv50_set_intensity(struct backlight_device *bd) | |||
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static struct backlight_ops nv50_bl_ops = { | 85 | static const struct backlight_ops nv50_bl_ops = { |
86 | .options = BL_CORE_SUSPENDRESUME, | 86 | .options = BL_CORE_SUSPENDRESUME, |
87 | .get_brightness = nv50_get_intensity, | 87 | .get_brightness = nv50_get_intensity, |
88 | .update_status = nv50_set_intensity, | 88 | .update_status = nv50_set_intensity, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index d3046559bf05..2aef5cd3acf5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -1927,7 +1927,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1927 | * offset (8 bit): opcode | 1927 | * offset (8 bit): opcode |
1928 | * offset + 1 (16 bit): time | 1928 | * offset + 1 (16 bit): time |
1929 | * | 1929 | * |
1930 | * Sleep for "time" miliseconds. | 1930 | * Sleep for "time" milliseconds. |
1931 | */ | 1931 | */ |
1932 | 1932 | ||
1933 | unsigned time = ROM16(bios->data[offset + 1]); | 1933 | unsigned time = ROM16(bios->data[offset + 1]); |
@@ -1935,7 +1935,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1935 | if (!iexec->execute) | 1935 | if (!iexec->execute) |
1936 | return 3; | 1936 | return 3; |
1937 | 1937 | ||
1938 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n", | 1938 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n", |
1939 | offset, time); | 1939 | offset, time); |
1940 | 1940 | ||
1941 | msleep(time); | 1941 | msleep(time); |
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 58a0cd02c0a2..04b269d14a59 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h | |||
@@ -1629,7 +1629,7 @@ typedef struct _GET_ENGINE_CLOCK_PARAMETERS | |||
1629 | typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS | 1629 | typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS |
1630 | { | 1630 | { |
1631 | USHORT usPrescale; //Ratio between Engine clock and I2C clock | 1631 | USHORT usPrescale; //Ratio between Engine clock and I2C clock |
1632 | USHORT usVRAMAddress; //Adress in Frame Buffer where to pace raw EDID | 1632 | USHORT usVRAMAddress; //Address in Frame Buffer where to pace raw EDID |
1633 | USHORT usStatus; //When use output: lower byte EDID checksum, high byte hardware status | 1633 | USHORT usStatus; //When use output: lower byte EDID checksum, high byte hardware status |
1634 | //WHen use input: lower byte as 'byte to read':currently limited to 128byte or 1byte | 1634 | //WHen use input: lower byte as 'byte to read':currently limited to 128byte or 1byte |
1635 | UCHAR ucSlaveAddr; //Read from which slave | 1635 | UCHAR ucSlaveAddr; //Read from which slave |
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index ffbc278647bf..24cca2f69dfc 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -295,6 +295,23 @@ config HID_MONTEREY | |||
295 | ---help--- | 295 | ---help--- |
296 | Support for Monterey Genius KB29E. | 296 | Support for Monterey Genius KB29E. |
297 | 297 | ||
298 | config HID_MULTITOUCH | ||
299 | tristate "HID Multitouch panels" | ||
300 | depends on USB_HID | ||
301 | ---help--- | ||
302 | Generic support for HID multitouch panels. | ||
303 | |||
304 | Say Y here if you have one of the following devices: | ||
305 | - Cypress TrueTouch panels | ||
306 | - Hanvon dual touch panels | ||
307 | - Pixcir dual touch panels | ||
308 | - 'Sensing Win7-TwoFinger' panel by GeneralTouch | ||
309 | |||
310 | If unsure, say N. | ||
311 | |||
312 | To compile this driver as a module, choose M here: the | ||
313 | module will be called hid-multitouch. | ||
314 | |||
298 | config HID_NTRIG | 315 | config HID_NTRIG |
299 | tristate "N-Trig touch screen" | 316 | tristate "N-Trig touch screen" |
300 | depends on USB_HID | 317 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 6eae9a90b8dd..6efc2a0370ad 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -47,6 +47,7 @@ obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o | |||
47 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 47 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
48 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 48 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
49 | obj-$(CONFIG_HID_MOSART) += hid-mosart.o | 49 | obj-$(CONFIG_HID_MOSART) += hid-mosart.o |
50 | obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o | ||
50 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o | 51 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o |
51 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o | 52 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o |
52 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o | 53 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o |
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c index 375b50929a50..1ea066c55201 100644 --- a/drivers/hid/hid-cando.c +++ b/drivers/hid/hid-cando.c | |||
@@ -236,6 +236,8 @@ static const struct hid_device_id cando_devices[] = { | |||
236 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 236 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, | ||
240 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 241 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
240 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 242 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
241 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | 243 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 261168607c91..d678cf3d33d5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1312,7 +1312,9 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1312 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1312 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
1313 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 1313 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
1314 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | 1314 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, |
1315 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, | ||
1315 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1316 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
1317 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, | ||
1316 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1318 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
1317 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | 1319 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, |
1318 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1320 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
@@ -1324,6 +1326,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1324 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1326 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
1325 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, | 1327 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, |
1326 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1328 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1329 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | ||
1327 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1330 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
1328 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 1331 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, |
1329 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 1332 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, |
@@ -1335,11 +1338,13 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1335 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1338 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1336 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, | 1339 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
1337 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1340 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
1341 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, | ||
1338 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, | 1342 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, |
1339 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | 1343 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, |
1340 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1344 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1341 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1345 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1342 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | 1346 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
1347 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, | ||
1343 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, | 1348 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, |
1344 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | 1349 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, |
1345 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1350 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
@@ -1422,6 +1427,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1422 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 1427 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
1423 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
1424 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | 1429 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, |
1430 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, | ||
1425 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, | 1431 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, |
1426 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, | 1432 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, |
1427 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, | 1433 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, |
@@ -1640,7 +1646,6 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1640 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1646 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
1641 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, | 1647 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, |
1642 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, | 1648 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, |
1643 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, | ||
1644 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, | 1649 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, |
1645 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, | 1650 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, |
1646 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, | 1651 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f65cace77729..92a0d61a7379 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -140,7 +140,9 @@ | |||
140 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 | 140 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 |
141 | 141 | ||
142 | #define USB_VENDOR_ID_CANDO 0x2087 | 142 | #define USB_VENDOR_ID_CANDO 0x2087 |
143 | #define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703 | ||
143 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 144 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
145 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02 | ||
144 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 | 146 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 |
145 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 | 147 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 |
146 | 148 | ||
@@ -186,6 +188,7 @@ | |||
186 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 | 188 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 |
187 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 | 189 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 |
188 | #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 | 190 | #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 |
191 | #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 | ||
189 | 192 | ||
190 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 | 193 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 |
191 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a | 194 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a |
@@ -236,6 +239,7 @@ | |||
236 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 | 239 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 |
237 | 240 | ||
238 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc | 241 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc |
242 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 | ||
239 | 243 | ||
240 | #define USB_VENDOR_ID_GLAB 0x06c2 | 244 | #define USB_VENDOR_ID_GLAB 0x06c2 |
241 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 245 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
@@ -318,6 +322,9 @@ | |||
318 | #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 | 322 | #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 |
319 | #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff | 323 | #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff |
320 | 324 | ||
325 | #define USB_VENDOR_ID_HANVON 0x20b3 | ||
326 | #define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 | ||
327 | |||
321 | #define USB_VENDOR_ID_HAPP 0x078b | 328 | #define USB_VENDOR_ID_HAPP 0x078b |
322 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | 329 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 |
323 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | 330 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index e60fdb88101f..7f552bfad32c 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -290,6 +290,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
290 | goto ignore; | 290 | goto ignore; |
291 | } | 291 | } |
292 | 292 | ||
293 | if (field->report_type == HID_FEATURE_REPORT) { | ||
294 | if (device->driver->feature_mapping) { | ||
295 | device->driver->feature_mapping(device, hidinput, field, | ||
296 | usage); | ||
297 | } | ||
298 | goto ignore; | ||
299 | } | ||
300 | |||
293 | if (device->driver->input_mapping) { | 301 | if (device->driver->input_mapping) { |
294 | int ret = device->driver->input_mapping(device, hidinput, field, | 302 | int ret = device->driver->input_mapping(device, hidinput, field, |
295 | usage, &bit, &max); | 303 | usage, &bit, &max); |
@@ -839,7 +847,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
839 | struct hid_input *hidinput = NULL; | 847 | struct hid_input *hidinput = NULL; |
840 | struct input_dev *input_dev; | 848 | struct input_dev *input_dev; |
841 | int i, j, k; | 849 | int i, j, k; |
842 | int max_report_type = HID_OUTPUT_REPORT; | ||
843 | 850 | ||
844 | INIT_LIST_HEAD(&hid->inputs); | 851 | INIT_LIST_HEAD(&hid->inputs); |
845 | 852 | ||
@@ -856,10 +863,11 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
856 | return -1; | 863 | return -1; |
857 | } | 864 | } |
858 | 865 | ||
859 | if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) | 866 | for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) { |
860 | max_report_type = HID_INPUT_REPORT; | 867 | if (k == HID_OUTPUT_REPORT && |
868 | hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) | ||
869 | continue; | ||
861 | 870 | ||
862 | for (k = HID_INPUT_REPORT; k <= max_report_type; k++) | ||
863 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | 871 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { |
864 | 872 | ||
865 | if (!report->maxfield) | 873 | if (!report->maxfield) |
@@ -912,6 +920,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
912 | hidinput = NULL; | 920 | hidinput = NULL; |
913 | } | 921 | } |
914 | } | 922 | } |
923 | } | ||
915 | 924 | ||
916 | if (hidinput && input_register_device(hidinput->input)) | 925 | if (hidinput && input_register_device(hidinput->input)) |
917 | goto out_cleanup; | 926 | goto out_cleanup; |
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index 9fb050ce6f04..aed7ffe36283 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c | |||
@@ -257,6 +257,7 @@ static void mosart_remove(struct hid_device *hdev) | |||
257 | static const struct hid_device_id mosart_devices[] = { | 257 | static const struct hid_device_id mosart_devices[] = { |
258 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | 258 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, |
259 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | 259 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, |
260 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, | ||
260 | { } | 261 | { } |
261 | }; | 262 | }; |
262 | MODULE_DEVICE_TABLE(hid, mosart_devices); | 263 | MODULE_DEVICE_TABLE(hid, mosart_devices); |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c new file mode 100644 index 000000000000..07d3183fdde5 --- /dev/null +++ b/drivers/hid/hid-multitouch.c | |||
@@ -0,0 +1,516 @@ | |||
1 | /* | ||
2 | * HID driver for multitouch panels | ||
3 | * | ||
4 | * Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr> | ||
5 | * Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com> | ||
6 | * Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the Free | ||
13 | * Software Foundation; either version 2 of the License, or (at your option) | ||
14 | * any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/device.h> | ||
18 | #include <linux/hid.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/input/mt.h> | ||
23 | #include "usbhid/usbhid.h" | ||
24 | |||
25 | |||
26 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
27 | MODULE_DESCRIPTION("HID multitouch panels"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | #include "hid-ids.h" | ||
31 | |||
32 | /* quirks to control the device */ | ||
33 | #define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0) | ||
34 | #define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) | ||
35 | #define MT_QUIRK_CYPRESS (1 << 2) | ||
36 | #define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) | ||
37 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 4) | ||
38 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) | ||
39 | |||
40 | struct mt_slot { | ||
41 | __s32 x, y, p, w, h; | ||
42 | __s32 contactid; /* the device ContactID assigned to this slot */ | ||
43 | bool touch_state; /* is the touch valid? */ | ||
44 | bool seen_in_this_frame;/* has this slot been updated */ | ||
45 | }; | ||
46 | |||
47 | struct mt_device { | ||
48 | struct mt_slot curdata; /* placeholder of incoming data */ | ||
49 | struct mt_class *mtclass; /* our mt device class */ | ||
50 | unsigned last_field_index; /* last field index of the report */ | ||
51 | unsigned last_slot_field; /* the last field of a slot */ | ||
52 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ | ||
53 | __u8 num_received; /* how many contacts we received */ | ||
54 | __u8 num_expected; /* expected last contact index */ | ||
55 | bool curvalid; /* is the current contact valid? */ | ||
56 | struct mt_slot slots[0]; /* first slot */ | ||
57 | }; | ||
58 | |||
59 | struct mt_class { | ||
60 | __s32 name; /* MT_CLS */ | ||
61 | __s32 quirks; | ||
62 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
63 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
64 | __u8 maxcontacts; | ||
65 | }; | ||
66 | |||
67 | /* classes of device behavior */ | ||
68 | #define MT_CLS_DEFAULT 1 | ||
69 | #define MT_CLS_DUAL1 2 | ||
70 | #define MT_CLS_DUAL2 3 | ||
71 | #define MT_CLS_CYPRESS 4 | ||
72 | |||
73 | /* | ||
74 | * these device-dependent functions determine what slot corresponds | ||
75 | * to a valid contact that was just read. | ||
76 | */ | ||
77 | |||
78 | static int cypress_compute_slot(struct mt_device *td) | ||
79 | { | ||
80 | if (td->curdata.contactid != 0 || td->num_received == 0) | ||
81 | return td->curdata.contactid; | ||
82 | else | ||
83 | return -1; | ||
84 | } | ||
85 | |||
86 | static int find_slot_from_contactid(struct mt_device *td) | ||
87 | { | ||
88 | int i; | ||
89 | for (i = 0; i < td->mtclass->maxcontacts; ++i) { | ||
90 | if (td->slots[i].contactid == td->curdata.contactid && | ||
91 | td->slots[i].touch_state) | ||
92 | return i; | ||
93 | } | ||
94 | for (i = 0; i < td->mtclass->maxcontacts; ++i) { | ||
95 | if (!td->slots[i].seen_in_this_frame && | ||
96 | !td->slots[i].touch_state) | ||
97 | return i; | ||
98 | } | ||
99 | /* should not occurs. If this happens that means | ||
100 | * that the device sent more touches that it says | ||
101 | * in the report descriptor. It is ignored then. */ | ||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | struct mt_class mt_classes[] = { | ||
106 | { .name = MT_CLS_DEFAULT, | ||
107 | .quirks = MT_QUIRK_VALID_IS_INRANGE, | ||
108 | .maxcontacts = 10 }, | ||
109 | { .name = MT_CLS_DUAL1, | ||
110 | .quirks = MT_QUIRK_VALID_IS_INRANGE | | ||
111 | MT_QUIRK_SLOT_IS_CONTACTID, | ||
112 | .maxcontacts = 2 }, | ||
113 | { .name = MT_CLS_DUAL2, | ||
114 | .quirks = MT_QUIRK_VALID_IS_INRANGE | | ||
115 | MT_QUIRK_SLOT_IS_CONTACTNUMBER, | ||
116 | .maxcontacts = 2 }, | ||
117 | { .name = MT_CLS_CYPRESS, | ||
118 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | | ||
119 | MT_QUIRK_CYPRESS, | ||
120 | .maxcontacts = 10 }, | ||
121 | |||
122 | { } | ||
123 | }; | ||
124 | |||
125 | static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
126 | struct hid_field *field, struct hid_usage *usage) | ||
127 | { | ||
128 | if (usage->hid == HID_DG_INPUTMODE) { | ||
129 | struct mt_device *td = hid_get_drvdata(hdev); | ||
130 | td->inputmode = field->report->id; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void set_abs(struct input_dev *input, unsigned int code, | ||
135 | struct hid_field *field, int snratio) | ||
136 | { | ||
137 | int fmin = field->logical_minimum; | ||
138 | int fmax = field->logical_maximum; | ||
139 | int fuzz = snratio ? (fmax - fmin) / snratio : 0; | ||
140 | input_set_abs_params(input, code, fmin, fmax, fuzz, 0); | ||
141 | } | ||
142 | |||
143 | static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
144 | struct hid_field *field, struct hid_usage *usage, | ||
145 | unsigned long **bit, int *max) | ||
146 | { | ||
147 | struct mt_device *td = hid_get_drvdata(hdev); | ||
148 | struct mt_class *cls = td->mtclass; | ||
149 | switch (usage->hid & HID_USAGE_PAGE) { | ||
150 | |||
151 | case HID_UP_GENDESK: | ||
152 | switch (usage->hid) { | ||
153 | case HID_GD_X: | ||
154 | hid_map_usage(hi, usage, bit, max, | ||
155 | EV_ABS, ABS_MT_POSITION_X); | ||
156 | set_abs(hi->input, ABS_MT_POSITION_X, field, | ||
157 | cls->sn_move); | ||
158 | /* touchscreen emulation */ | ||
159 | set_abs(hi->input, ABS_X, field, cls->sn_move); | ||
160 | td->last_slot_field = usage->hid; | ||
161 | return 1; | ||
162 | case HID_GD_Y: | ||
163 | hid_map_usage(hi, usage, bit, max, | ||
164 | EV_ABS, ABS_MT_POSITION_Y); | ||
165 | set_abs(hi->input, ABS_MT_POSITION_Y, field, | ||
166 | cls->sn_move); | ||
167 | /* touchscreen emulation */ | ||
168 | set_abs(hi->input, ABS_Y, field, cls->sn_move); | ||
169 | td->last_slot_field = usage->hid; | ||
170 | return 1; | ||
171 | } | ||
172 | return 0; | ||
173 | |||
174 | case HID_UP_DIGITIZER: | ||
175 | switch (usage->hid) { | ||
176 | case HID_DG_INRANGE: | ||
177 | td->last_slot_field = usage->hid; | ||
178 | return 1; | ||
179 | case HID_DG_CONFIDENCE: | ||
180 | td->last_slot_field = usage->hid; | ||
181 | return 1; | ||
182 | case HID_DG_TIPSWITCH: | ||
183 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
184 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); | ||
185 | td->last_slot_field = usage->hid; | ||
186 | return 1; | ||
187 | case HID_DG_CONTACTID: | ||
188 | input_mt_init_slots(hi->input, | ||
189 | td->mtclass->maxcontacts); | ||
190 | td->last_slot_field = usage->hid; | ||
191 | return 1; | ||
192 | case HID_DG_WIDTH: | ||
193 | hid_map_usage(hi, usage, bit, max, | ||
194 | EV_ABS, ABS_MT_TOUCH_MAJOR); | ||
195 | td->last_slot_field = usage->hid; | ||
196 | return 1; | ||
197 | case HID_DG_HEIGHT: | ||
198 | hid_map_usage(hi, usage, bit, max, | ||
199 | EV_ABS, ABS_MT_TOUCH_MINOR); | ||
200 | field->logical_maximum = 1; | ||
201 | field->logical_minimum = 0; | ||
202 | set_abs(hi->input, ABS_MT_ORIENTATION, field, 0); | ||
203 | td->last_slot_field = usage->hid; | ||
204 | return 1; | ||
205 | case HID_DG_TIPPRESSURE: | ||
206 | hid_map_usage(hi, usage, bit, max, | ||
207 | EV_ABS, ABS_MT_PRESSURE); | ||
208 | set_abs(hi->input, ABS_MT_PRESSURE, field, | ||
209 | cls->sn_pressure); | ||
210 | /* touchscreen emulation */ | ||
211 | set_abs(hi->input, ABS_PRESSURE, field, | ||
212 | cls->sn_pressure); | ||
213 | td->last_slot_field = usage->hid; | ||
214 | return 1; | ||
215 | case HID_DG_CONTACTCOUNT: | ||
216 | td->last_field_index = field->report->maxfield - 1; | ||
217 | return 1; | ||
218 | case HID_DG_CONTACTMAX: | ||
219 | /* we don't set td->last_slot_field as contactcount and | ||
220 | * contact max are global to the report */ | ||
221 | return -1; | ||
222 | } | ||
223 | /* let hid-input decide for the others */ | ||
224 | return 0; | ||
225 | |||
226 | case 0xff000000: | ||
227 | /* we do not want to map these: no input-oriented meaning */ | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
235 | struct hid_field *field, struct hid_usage *usage, | ||
236 | unsigned long **bit, int *max) | ||
237 | { | ||
238 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
239 | set_bit(usage->type, hi->input->evbit); | ||
240 | |||
241 | return -1; | ||
242 | } | ||
243 | |||
244 | static int mt_compute_slot(struct mt_device *td) | ||
245 | { | ||
246 | __s32 quirks = td->mtclass->quirks; | ||
247 | |||
248 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) | ||
249 | return td->curdata.contactid; | ||
250 | |||
251 | if (quirks & MT_QUIRK_CYPRESS) | ||
252 | return cypress_compute_slot(td); | ||
253 | |||
254 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) | ||
255 | return td->num_received; | ||
256 | |||
257 | return find_slot_from_contactid(td); | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * this function is called when a whole contact has been processed, | ||
262 | * so that it can assign it to a slot and store the data there | ||
263 | */ | ||
264 | static void mt_complete_slot(struct mt_device *td) | ||
265 | { | ||
266 | td->curdata.seen_in_this_frame = true; | ||
267 | if (td->curvalid) { | ||
268 | int slotnum = mt_compute_slot(td); | ||
269 | |||
270 | if (slotnum >= 0 && slotnum < td->mtclass->maxcontacts) | ||
271 | td->slots[slotnum] = td->curdata; | ||
272 | } | ||
273 | td->num_received++; | ||
274 | } | ||
275 | |||
276 | |||
277 | /* | ||
278 | * this function is called when a whole packet has been received and processed, | ||
279 | * so that it can decide what to send to the input layer. | ||
280 | */ | ||
281 | static void mt_emit_event(struct mt_device *td, struct input_dev *input) | ||
282 | { | ||
283 | int i; | ||
284 | |||
285 | for (i = 0; i < td->mtclass->maxcontacts; ++i) { | ||
286 | struct mt_slot *s = &(td->slots[i]); | ||
287 | if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && | ||
288 | !s->seen_in_this_frame) { | ||
289 | s->touch_state = false; | ||
290 | } | ||
291 | |||
292 | input_mt_slot(input, i); | ||
293 | input_mt_report_slot_state(input, MT_TOOL_FINGER, | ||
294 | s->touch_state); | ||
295 | if (s->touch_state) { | ||
296 | input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); | ||
297 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); | ||
298 | input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); | ||
299 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w); | ||
300 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h); | ||
301 | } | ||
302 | s->seen_in_this_frame = false; | ||
303 | |||
304 | } | ||
305 | |||
306 | input_mt_report_pointer_emulation(input, true); | ||
307 | input_sync(input); | ||
308 | td->num_received = 0; | ||
309 | } | ||
310 | |||
311 | |||
312 | |||
313 | static int mt_event(struct hid_device *hid, struct hid_field *field, | ||
314 | struct hid_usage *usage, __s32 value) | ||
315 | { | ||
316 | struct mt_device *td = hid_get_drvdata(hid); | ||
317 | __s32 quirks = td->mtclass->quirks; | ||
318 | |||
319 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
320 | switch (usage->hid) { | ||
321 | case HID_DG_INRANGE: | ||
322 | if (quirks & MT_QUIRK_VALID_IS_INRANGE) | ||
323 | td->curvalid = value; | ||
324 | break; | ||
325 | case HID_DG_TIPSWITCH: | ||
326 | if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) | ||
327 | td->curvalid = value; | ||
328 | td->curdata.touch_state = value; | ||
329 | break; | ||
330 | case HID_DG_CONFIDENCE: | ||
331 | if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE) | ||
332 | td->curvalid = value; | ||
333 | break; | ||
334 | case HID_DG_CONTACTID: | ||
335 | td->curdata.contactid = value; | ||
336 | break; | ||
337 | case HID_DG_TIPPRESSURE: | ||
338 | td->curdata.p = value; | ||
339 | break; | ||
340 | case HID_GD_X: | ||
341 | td->curdata.x = value; | ||
342 | break; | ||
343 | case HID_GD_Y: | ||
344 | td->curdata.y = value; | ||
345 | break; | ||
346 | case HID_DG_WIDTH: | ||
347 | td->curdata.w = value; | ||
348 | break; | ||
349 | case HID_DG_HEIGHT: | ||
350 | td->curdata.h = value; | ||
351 | break; | ||
352 | case HID_DG_CONTACTCOUNT: | ||
353 | /* | ||
354 | * Includes multi-packet support where subsequent | ||
355 | * packets are sent with zero contactcount. | ||
356 | */ | ||
357 | if (value) | ||
358 | td->num_expected = value; | ||
359 | break; | ||
360 | |||
361 | default: | ||
362 | /* fallback to the generic hidinput handling */ | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | if (usage->hid == td->last_slot_field) | ||
367 | mt_complete_slot(td); | ||
368 | |||
369 | if (field->index == td->last_field_index | ||
370 | && td->num_received >= td->num_expected) | ||
371 | mt_emit_event(td, field->hidinput->input); | ||
372 | |||
373 | } | ||
374 | |||
375 | /* we have handled the hidinput part, now remains hiddev */ | ||
376 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
377 | hid->hiddev_hid_event(hid, field, usage, value); | ||
378 | |||
379 | return 1; | ||
380 | } | ||
381 | |||
382 | static void mt_set_input_mode(struct hid_device *hdev) | ||
383 | { | ||
384 | struct mt_device *td = hid_get_drvdata(hdev); | ||
385 | struct hid_report *r; | ||
386 | struct hid_report_enum *re; | ||
387 | |||
388 | if (td->inputmode < 0) | ||
389 | return; | ||
390 | |||
391 | re = &(hdev->report_enum[HID_FEATURE_REPORT]); | ||
392 | r = re->report_id_hash[td->inputmode]; | ||
393 | if (r) { | ||
394 | r->field[0]->value[0] = 0x02; | ||
395 | usbhid_submit_report(hdev, r, USB_DIR_OUT); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
400 | { | ||
401 | int ret, i; | ||
402 | struct mt_device *td; | ||
403 | struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ | ||
404 | |||
405 | for (i = 0; mt_classes[i].name ; i++) { | ||
406 | if (id->driver_data == mt_classes[i].name) { | ||
407 | mtclass = &(mt_classes[i]); | ||
408 | break; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | /* This allows the driver to correctly support devices | ||
413 | * that emit events over several HID messages. | ||
414 | */ | ||
415 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | ||
416 | |||
417 | td = kzalloc(sizeof(struct mt_device) + | ||
418 | mtclass->maxcontacts * sizeof(struct mt_slot), | ||
419 | GFP_KERNEL); | ||
420 | if (!td) { | ||
421 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | ||
422 | return -ENOMEM; | ||
423 | } | ||
424 | td->mtclass = mtclass; | ||
425 | td->inputmode = -1; | ||
426 | hid_set_drvdata(hdev, td); | ||
427 | |||
428 | ret = hid_parse(hdev); | ||
429 | if (ret != 0) | ||
430 | goto fail; | ||
431 | |||
432 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
433 | if (ret) | ||
434 | goto fail; | ||
435 | |||
436 | mt_set_input_mode(hdev); | ||
437 | |||
438 | return 0; | ||
439 | |||
440 | fail: | ||
441 | kfree(td); | ||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | #ifdef CONFIG_PM | ||
446 | static int mt_reset_resume(struct hid_device *hdev) | ||
447 | { | ||
448 | mt_set_input_mode(hdev); | ||
449 | return 0; | ||
450 | } | ||
451 | #endif | ||
452 | |||
453 | static void mt_remove(struct hid_device *hdev) | ||
454 | { | ||
455 | struct mt_device *td = hid_get_drvdata(hdev); | ||
456 | hid_hw_stop(hdev); | ||
457 | kfree(td); | ||
458 | hid_set_drvdata(hdev, NULL); | ||
459 | } | ||
460 | |||
461 | static const struct hid_device_id mt_devices[] = { | ||
462 | |||
463 | /* Cypress panel */ | ||
464 | { .driver_data = MT_CLS_CYPRESS, | ||
465 | HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, | ||
466 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | ||
467 | |||
468 | /* GeneralTouch panel */ | ||
469 | { .driver_data = MT_CLS_DUAL2, | ||
470 | HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, | ||
471 | USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, | ||
472 | |||
473 | /* PixCir-based panels */ | ||
474 | { .driver_data = MT_CLS_DUAL1, | ||
475 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON, | ||
476 | USB_DEVICE_ID_HANVON_MULTITOUCH) }, | ||
477 | { .driver_data = MT_CLS_DUAL1, | ||
478 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
479 | USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, | ||
480 | |||
481 | { } | ||
482 | }; | ||
483 | MODULE_DEVICE_TABLE(hid, mt_devices); | ||
484 | |||
485 | static const struct hid_usage_id mt_grabbed_usages[] = { | ||
486 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
487 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
488 | }; | ||
489 | |||
490 | static struct hid_driver mt_driver = { | ||
491 | .name = "hid-multitouch", | ||
492 | .id_table = mt_devices, | ||
493 | .probe = mt_probe, | ||
494 | .remove = mt_remove, | ||
495 | .input_mapping = mt_input_mapping, | ||
496 | .input_mapped = mt_input_mapped, | ||
497 | .feature_mapping = mt_feature_mapping, | ||
498 | .usage_table = mt_grabbed_usages, | ||
499 | .event = mt_event, | ||
500 | #ifdef CONFIG_PM | ||
501 | .reset_resume = mt_reset_resume, | ||
502 | #endif | ||
503 | }; | ||
504 | |||
505 | static int __init mt_init(void) | ||
506 | { | ||
507 | return hid_register_driver(&mt_driver); | ||
508 | } | ||
509 | |||
510 | static void __exit mt_exit(void) | ||
511 | { | ||
512 | hid_unregister_driver(&mt_driver); | ||
513 | } | ||
514 | |||
515 | module_init(mt_init); | ||
516 | module_exit(mt_exit); | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 76b9a149c7df..9a94b643ccde 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -35,7 +35,6 @@ static const struct hid_blacklist { | |||
35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, |
37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
38 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, | ||
39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
41 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index bdc13d28b1ea..35f00dae3676 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -809,10 +809,10 @@ config SENSORS_DME1737 | |||
809 | will be called dme1737. | 809 | will be called dme1737. |
810 | 810 | ||
811 | config SENSORS_EMC1403 | 811 | config SENSORS_EMC1403 |
812 | tristate "SMSC EMC1403 thermal sensor" | 812 | tristate "SMSC EMC1403/23 thermal sensor" |
813 | depends on I2C | 813 | depends on I2C |
814 | help | 814 | help |
815 | If you say yes here you get support for the SMSC EMC1403 | 815 | If you say yes here you get support for the SMSC EMC1403/23 |
816 | temperature monitoring chip. | 816 | temperature monitoring chip. |
817 | 817 | ||
818 | Threshold values can be configured using sysfs. | 818 | Threshold values can be configured using sysfs. |
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 0727ad250793..9e234b981b83 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * Alarms 16-bit map of active alarms | 20 | * Alarms 16-bit map of active alarms |
21 | * Analog Out 0..1250 mV output | 21 | * Analog Out 0..1250 mV output |
22 | * | 22 | * |
23 | * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear' | 23 | * Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm' |
24 | * | 24 | * |
25 | * Test hardware: Intel SE440BX-2 desktop motherboard --Grant | 25 | * Test hardware: Intel SE440BX-2 desktop motherboard --Grant |
26 | * | 26 | * |
@@ -476,13 +476,16 @@ static ssize_t set_aout(struct device *dev, | |||
476 | static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); | 476 | static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); |
477 | 477 | ||
478 | /* chassis_clear */ | 478 | /* chassis_clear */ |
479 | static ssize_t chassis_clear(struct device *dev, | 479 | static ssize_t chassis_clear_legacy(struct device *dev, |
480 | struct device_attribute *attr, | 480 | struct device_attribute *attr, |
481 | const char *buf, size_t count) | 481 | const char *buf, size_t count) |
482 | { | 482 | { |
483 | struct i2c_client *client = to_i2c_client(dev); | 483 | struct i2c_client *client = to_i2c_client(dev); |
484 | unsigned long val = simple_strtol(buf, NULL, 10); | 484 | unsigned long val = simple_strtol(buf, NULL, 10); |
485 | 485 | ||
486 | dev_warn(dev, "Attribute chassis_clear is deprecated, " | ||
487 | "use intrusion0_alarm instead\n"); | ||
488 | |||
486 | if (val == 1) { | 489 | if (val == 1) { |
487 | i2c_smbus_write_byte_data(client, | 490 | i2c_smbus_write_byte_data(client, |
488 | ADM9240_REG_CHASSIS_CLEAR, 0x80); | 491 | ADM9240_REG_CHASSIS_CLEAR, 0x80); |
@@ -490,7 +493,29 @@ static ssize_t chassis_clear(struct device *dev, | |||
490 | } | 493 | } |
491 | return count; | 494 | return count; |
492 | } | 495 | } |
493 | static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear); | 496 | static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear_legacy); |
497 | |||
498 | static ssize_t chassis_clear(struct device *dev, | ||
499 | struct device_attribute *attr, | ||
500 | const char *buf, size_t count) | ||
501 | { | ||
502 | struct i2c_client *client = to_i2c_client(dev); | ||
503 | struct adm9240_data *data = i2c_get_clientdata(client); | ||
504 | unsigned long val; | ||
505 | |||
506 | if (strict_strtoul(buf, 10, &val) || val != 0) | ||
507 | return -EINVAL; | ||
508 | |||
509 | mutex_lock(&data->update_lock); | ||
510 | i2c_smbus_write_byte_data(client, ADM9240_REG_CHASSIS_CLEAR, 0x80); | ||
511 | data->valid = 0; /* Force cache refresh */ | ||
512 | mutex_unlock(&data->update_lock); | ||
513 | dev_dbg(&client->dev, "chassis intrusion latch cleared\n"); | ||
514 | |||
515 | return count; | ||
516 | } | ||
517 | static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm, | ||
518 | chassis_clear, 12); | ||
494 | 519 | ||
495 | static struct attribute *adm9240_attributes[] = { | 520 | static struct attribute *adm9240_attributes[] = { |
496 | &sensor_dev_attr_in0_input.dev_attr.attr, | 521 | &sensor_dev_attr_in0_input.dev_attr.attr, |
@@ -532,6 +557,7 @@ static struct attribute *adm9240_attributes[] = { | |||
532 | &dev_attr_alarms.attr, | 557 | &dev_attr_alarms.attr, |
533 | &dev_attr_aout_output.attr, | 558 | &dev_attr_aout_output.attr, |
534 | &dev_attr_chassis_clear.attr, | 559 | &dev_attr_chassis_clear.attr, |
560 | &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, | ||
535 | &dev_attr_cpu0_vid.attr, | 561 | &dev_attr_cpu0_vid.attr, |
536 | NULL | 562 | NULL |
537 | }; | 563 | }; |
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index aac85f3aed50..c42c5a69a664 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | This driver is based on the lm75 and other lm_sensors/hwmon drivers | 5 | This driver is based on the lm75 and other lm_sensors/hwmon drivers |
6 | 6 | ||
7 | Written by Steve Hardy <steve@linuxrealtime.co.uk> | 7 | Written by Steve Hardy <shardy@redhat.com> |
8 | 8 | ||
9 | Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf | 9 | Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf |
10 | 10 | ||
@@ -271,7 +271,7 @@ static void __exit sensors_ads7828_exit(void) | |||
271 | i2c_del_driver(&ads7828_driver); | 271 | i2c_del_driver(&ads7828_driver); |
272 | } | 272 | } |
273 | 273 | ||
274 | MODULE_AUTHOR("Steve Hardy <steve@linuxrealtime.co.uk>"); | 274 | MODULE_AUTHOR("Steve Hardy <shardy@redhat.com>"); |
275 | MODULE_DESCRIPTION("ADS7828 driver"); | 275 | MODULE_DESCRIPTION("ADS7828 driver"); |
276 | MODULE_LICENSE("GPL"); | 276 | MODULE_LICENSE("GPL"); |
277 | 277 | ||
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index e9a610bfd0cc..d9c592713919 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c | |||
@@ -77,12 +77,14 @@ enum chips { dme1737, sch5027, sch311x, sch5127 }; | |||
77 | * in4 +12V | 77 | * in4 +12V |
78 | * in5 VTR (+3.3V stby) | 78 | * in5 VTR (+3.3V stby) |
79 | * in6 Vbat | 79 | * in6 Vbat |
80 | * in7 Vtrip (sch5127 only) | ||
80 | * | 81 | * |
81 | * --------------------------------------------------------------------- */ | 82 | * --------------------------------------------------------------------- */ |
82 | 83 | ||
83 | /* Voltages (in) numbered 0-6 (ix) */ | 84 | /* Voltages (in) numbered 0-7 (ix) */ |
84 | #define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) \ | 85 | #define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) : \ |
85 | : 0x94 + (ix)) | 86 | (ix) < 7 ? 0x94 + (ix) : \ |
87 | 0x1f) | ||
86 | #define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \ | 88 | #define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \ |
87 | : 0x91 + (ix) * 2) | 89 | : 0x91 + (ix) * 2) |
88 | #define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \ | 90 | #define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \ |
@@ -101,10 +103,11 @@ enum chips { dme1737, sch5027, sch311x, sch5127 }; | |||
101 | * IN_TEMP_LSB(1) = [temp3, temp1] | 103 | * IN_TEMP_LSB(1) = [temp3, temp1] |
102 | * IN_TEMP_LSB(2) = [in4, temp2] | 104 | * IN_TEMP_LSB(2) = [in4, temp2] |
103 | * IN_TEMP_LSB(3) = [in3, in0] | 105 | * IN_TEMP_LSB(3) = [in3, in0] |
104 | * IN_TEMP_LSB(4) = [in2, in1] */ | 106 | * IN_TEMP_LSB(4) = [in2, in1] |
107 | * IN_TEMP_LSB(5) = [res, in7] */ | ||
105 | #define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix)) | 108 | #define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix)) |
106 | static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0}; | 109 | static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0, 5}; |
107 | static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4}; | 110 | static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4, 4}; |
108 | static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1}; | 111 | static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1}; |
109 | static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; | 112 | static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; |
110 | 113 | ||
@@ -145,7 +148,7 @@ static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; | |||
145 | #define DME1737_REG_ALARM1 0x41 | 148 | #define DME1737_REG_ALARM1 0x41 |
146 | #define DME1737_REG_ALARM2 0x42 | 149 | #define DME1737_REG_ALARM2 0x42 |
147 | #define DME1737_REG_ALARM3 0x83 | 150 | #define DME1737_REG_ALARM3 0x83 |
148 | static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17}; | 151 | static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17, 18}; |
149 | static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; | 152 | static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; |
150 | static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; | 153 | static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; |
151 | 154 | ||
@@ -190,6 +193,7 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; | |||
190 | #define HAS_PWM_MIN (1 << 4) /* bit 4 */ | 193 | #define HAS_PWM_MIN (1 << 4) /* bit 4 */ |
191 | #define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */ | 194 | #define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */ |
192 | #define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */ | 195 | #define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */ |
196 | #define HAS_IN7 (1 << 17) /* bit 17 */ | ||
193 | 197 | ||
194 | /* --------------------------------------------------------------------- | 198 | /* --------------------------------------------------------------------- |
195 | * Data structures and manipulation thereof | 199 | * Data structures and manipulation thereof |
@@ -213,9 +217,9 @@ struct dme1737_data { | |||
213 | u32 has_features; | 217 | u32 has_features; |
214 | 218 | ||
215 | /* Register values */ | 219 | /* Register values */ |
216 | u16 in[7]; | 220 | u16 in[8]; |
217 | u8 in_min[7]; | 221 | u8 in_min[8]; |
218 | u8 in_max[7]; | 222 | u8 in_max[8]; |
219 | s16 temp[3]; | 223 | s16 temp[3]; |
220 | s8 temp_min[3]; | 224 | s8 temp_min[3]; |
221 | s8 temp_max[3]; | 225 | s8 temp_max[3]; |
@@ -247,7 +251,7 @@ static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, | |||
247 | static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, | 251 | static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, |
248 | 3300}; | 252 | 3300}; |
249 | static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300, | 253 | static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300, |
250 | 3300}; | 254 | 3300, 1500}; |
251 | #define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ | 255 | #define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ |
252 | (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ | 256 | (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ |
253 | (type) == sch5127 ? IN_NOMINAL_SCH5127 : \ | 257 | (type) == sch5127 ? IN_NOMINAL_SCH5127 : \ |
@@ -580,7 +584,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
580 | { | 584 | { |
581 | struct dme1737_data *data = dev_get_drvdata(dev); | 585 | struct dme1737_data *data = dev_get_drvdata(dev); |
582 | int ix; | 586 | int ix; |
583 | u8 lsb[5]; | 587 | u8 lsb[6]; |
584 | 588 | ||
585 | mutex_lock(&data->update_lock); | 589 | mutex_lock(&data->update_lock); |
586 | 590 | ||
@@ -603,6 +607,9 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
603 | /* Voltage inputs are stored as 16 bit values even | 607 | /* Voltage inputs are stored as 16 bit values even |
604 | * though they have only 12 bits resolution. This is | 608 | * though they have only 12 bits resolution. This is |
605 | * to make it consistent with the temp inputs. */ | 609 | * to make it consistent with the temp inputs. */ |
610 | if (ix == 7 && !(data->has_features & HAS_IN7)) { | ||
611 | continue; | ||
612 | } | ||
606 | data->in[ix] = dme1737_read(data, | 613 | data->in[ix] = dme1737_read(data, |
607 | DME1737_REG_IN(ix)) << 8; | 614 | DME1737_REG_IN(ix)) << 8; |
608 | data->in_min[ix] = dme1737_read(data, | 615 | data->in_min[ix] = dme1737_read(data, |
@@ -635,10 +642,16 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
635 | * which the registers are read (MSB first, then LSB) is | 642 | * which the registers are read (MSB first, then LSB) is |
636 | * important! */ | 643 | * important! */ |
637 | for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { | 644 | for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { |
645 | if (ix == 5 && !(data->has_features & HAS_IN7)) { | ||
646 | continue; | ||
647 | } | ||
638 | lsb[ix] = dme1737_read(data, | 648 | lsb[ix] = dme1737_read(data, |
639 | DME1737_REG_IN_TEMP_LSB(ix)); | 649 | DME1737_REG_IN_TEMP_LSB(ix)); |
640 | } | 650 | } |
641 | for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { | 651 | for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { |
652 | if (ix == 7 && !(data->has_features & HAS_IN7)) { | ||
653 | continue; | ||
654 | } | ||
642 | data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] << | 655 | data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] << |
643 | DME1737_REG_IN_LSB_SHL[ix]) & 0xf0; | 656 | DME1737_REG_IN_LSB_SHL[ix]) & 0xf0; |
644 | } | 657 | } |
@@ -762,7 +775,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
762 | 775 | ||
763 | /* --------------------------------------------------------------------- | 776 | /* --------------------------------------------------------------------- |
764 | * Voltage sysfs attributes | 777 | * Voltage sysfs attributes |
765 | * ix = [0-5] | 778 | * ix = [0-7] |
766 | * --------------------------------------------------------------------- */ | 779 | * --------------------------------------------------------------------- */ |
767 | 780 | ||
768 | #define SYS_IN_INPUT 0 | 781 | #define SYS_IN_INPUT 0 |
@@ -1439,7 +1452,7 @@ static ssize_t show_name(struct device *dev, struct device_attribute *attr, | |||
1439 | * Sysfs device attribute defines and structs | 1452 | * Sysfs device attribute defines and structs |
1440 | * --------------------------------------------------------------------- */ | 1453 | * --------------------------------------------------------------------- */ |
1441 | 1454 | ||
1442 | /* Voltages 0-6 */ | 1455 | /* Voltages 0-7 */ |
1443 | 1456 | ||
1444 | #define SENSOR_DEVICE_ATTR_IN(ix) \ | 1457 | #define SENSOR_DEVICE_ATTR_IN(ix) \ |
1445 | static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \ | 1458 | static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \ |
@@ -1458,6 +1471,7 @@ SENSOR_DEVICE_ATTR_IN(3); | |||
1458 | SENSOR_DEVICE_ATTR_IN(4); | 1471 | SENSOR_DEVICE_ATTR_IN(4); |
1459 | SENSOR_DEVICE_ATTR_IN(5); | 1472 | SENSOR_DEVICE_ATTR_IN(5); |
1460 | SENSOR_DEVICE_ATTR_IN(6); | 1473 | SENSOR_DEVICE_ATTR_IN(6); |
1474 | SENSOR_DEVICE_ATTR_IN(7); | ||
1461 | 1475 | ||
1462 | /* Temperatures 1-3 */ | 1476 | /* Temperatures 1-3 */ |
1463 | 1477 | ||
@@ -1576,7 +1590,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); /* for ISA devices */ | |||
1576 | * created unconditionally. The attributes that need modification of their | 1590 | * created unconditionally. The attributes that need modification of their |
1577 | * permissions are created read-only and write permissions are added or removed | 1591 | * permissions are created read-only and write permissions are added or removed |
1578 | * on the fly when required */ | 1592 | * on the fly when required */ |
1579 | static struct attribute *dme1737_attr[] ={ | 1593 | static struct attribute *dme1737_attr[] = { |
1580 | /* Voltages */ | 1594 | /* Voltages */ |
1581 | &sensor_dev_attr_in0_input.dev_attr.attr, | 1595 | &sensor_dev_attr_in0_input.dev_attr.attr, |
1582 | &sensor_dev_attr_in0_min.dev_attr.attr, | 1596 | &sensor_dev_attr_in0_min.dev_attr.attr, |
@@ -1681,7 +1695,7 @@ static const struct attribute_group dme1737_zone3_group = { | |||
1681 | }; | 1695 | }; |
1682 | 1696 | ||
1683 | 1697 | ||
1684 | /* The following struct holds temp zone hysteresis related attributes, which | 1698 | /* The following struct holds temp zone hysteresis related attributes, which |
1685 | * are not available in all chips. The following chips support them: | 1699 | * are not available in all chips. The following chips support them: |
1686 | * DME1737, SCH311x */ | 1700 | * DME1737, SCH311x */ |
1687 | static struct attribute *dme1737_zone_hyst_attr[] = { | 1701 | static struct attribute *dme1737_zone_hyst_attr[] = { |
@@ -1695,6 +1709,21 @@ static const struct attribute_group dme1737_zone_hyst_group = { | |||
1695 | .attrs = dme1737_zone_hyst_attr, | 1709 | .attrs = dme1737_zone_hyst_attr, |
1696 | }; | 1710 | }; |
1697 | 1711 | ||
1712 | /* The following struct holds voltage in7 related attributes, which | ||
1713 | * are not available in all chips. The following chips support them: | ||
1714 | * SCH5127 */ | ||
1715 | static struct attribute *dme1737_in7_attr[] = { | ||
1716 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
1717 | &sensor_dev_attr_in7_min.dev_attr.attr, | ||
1718 | &sensor_dev_attr_in7_max.dev_attr.attr, | ||
1719 | &sensor_dev_attr_in7_alarm.dev_attr.attr, | ||
1720 | NULL | ||
1721 | }; | ||
1722 | |||
1723 | static const struct attribute_group dme1737_in7_group = { | ||
1724 | .attrs = dme1737_in7_attr, | ||
1725 | }; | ||
1726 | |||
1698 | /* The following structs hold the PWM attributes, some of which are optional. | 1727 | /* The following structs hold the PWM attributes, some of which are optional. |
1699 | * Their creation depends on the chip configuration which is determined during | 1728 | * Their creation depends on the chip configuration which is determined during |
1700 | * module load. */ | 1729 | * module load. */ |
@@ -1986,6 +2015,9 @@ static void dme1737_remove_files(struct device *dev) | |||
1986 | if (data->has_features & HAS_ZONE_HYST) { | 2015 | if (data->has_features & HAS_ZONE_HYST) { |
1987 | sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group); | 2016 | sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group); |
1988 | } | 2017 | } |
2018 | if (data->has_features & HAS_IN7) { | ||
2019 | sysfs_remove_group(&dev->kobj, &dme1737_in7_group); | ||
2020 | } | ||
1989 | sysfs_remove_group(&dev->kobj, &dme1737_group); | 2021 | sysfs_remove_group(&dev->kobj, &dme1737_group); |
1990 | 2022 | ||
1991 | if (!data->client) { | 2023 | if (!data->client) { |
@@ -1999,43 +2031,58 @@ static int dme1737_create_files(struct device *dev) | |||
1999 | int err, ix; | 2031 | int err, ix; |
2000 | 2032 | ||
2001 | /* Create a name attribute for ISA devices */ | 2033 | /* Create a name attribute for ISA devices */ |
2002 | if (!data->client && | 2034 | if (!data->client) { |
2003 | (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) { | 2035 | err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr); |
2004 | goto exit; | 2036 | if (err) { |
2037 | goto exit; | ||
2038 | } | ||
2005 | } | 2039 | } |
2006 | 2040 | ||
2007 | /* Create standard sysfs attributes */ | 2041 | /* Create standard sysfs attributes */ |
2008 | if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) { | 2042 | err = sysfs_create_group(&dev->kobj, &dme1737_group); |
2043 | if (err) { | ||
2009 | goto exit_remove; | 2044 | goto exit_remove; |
2010 | } | 2045 | } |
2011 | 2046 | ||
2012 | /* Create chip-dependent sysfs attributes */ | 2047 | /* Create chip-dependent sysfs attributes */ |
2013 | if ((data->has_features & HAS_TEMP_OFFSET) && | 2048 | if (data->has_features & HAS_TEMP_OFFSET) { |
2014 | (err = sysfs_create_group(&dev->kobj, | 2049 | err = sysfs_create_group(&dev->kobj, |
2015 | &dme1737_temp_offset_group))) { | 2050 | &dme1737_temp_offset_group); |
2016 | goto exit_remove; | 2051 | if (err) { |
2052 | goto exit_remove; | ||
2053 | } | ||
2017 | } | 2054 | } |
2018 | if ((data->has_features & HAS_VID) && | 2055 | if (data->has_features & HAS_VID) { |
2019 | (err = sysfs_create_group(&dev->kobj, | 2056 | err = sysfs_create_group(&dev->kobj, &dme1737_vid_group); |
2020 | &dme1737_vid_group))) { | 2057 | if (err) { |
2021 | goto exit_remove; | 2058 | goto exit_remove; |
2059 | } | ||
2022 | } | 2060 | } |
2023 | if ((data->has_features & HAS_ZONE3) && | 2061 | if (data->has_features & HAS_ZONE3) { |
2024 | (err = sysfs_create_group(&dev->kobj, | 2062 | err = sysfs_create_group(&dev->kobj, &dme1737_zone3_group); |
2025 | &dme1737_zone3_group))) { | 2063 | if (err) { |
2026 | goto exit_remove; | 2064 | goto exit_remove; |
2065 | } | ||
2027 | } | 2066 | } |
2028 | if ((data->has_features & HAS_ZONE_HYST) && | 2067 | if (data->has_features & HAS_ZONE_HYST) { |
2029 | (err = sysfs_create_group(&dev->kobj, | 2068 | err = sysfs_create_group(&dev->kobj, &dme1737_zone_hyst_group); |
2030 | &dme1737_zone_hyst_group))) { | 2069 | if (err) { |
2031 | goto exit_remove; | 2070 | goto exit_remove; |
2071 | } | ||
2072 | } | ||
2073 | if (data->has_features & HAS_IN7) { | ||
2074 | err = sysfs_create_group(&dev->kobj, &dme1737_in7_group); | ||
2075 | if (err) { | ||
2076 | goto exit_remove; | ||
2077 | } | ||
2032 | } | 2078 | } |
2033 | 2079 | ||
2034 | /* Create fan sysfs attributes */ | 2080 | /* Create fan sysfs attributes */ |
2035 | for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { | 2081 | for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { |
2036 | if (data->has_features & HAS_FAN(ix)) { | 2082 | if (data->has_features & HAS_FAN(ix)) { |
2037 | if ((err = sysfs_create_group(&dev->kobj, | 2083 | err = sysfs_create_group(&dev->kobj, |
2038 | &dme1737_fan_group[ix]))) { | 2084 | &dme1737_fan_group[ix]); |
2085 | if (err) { | ||
2039 | goto exit_remove; | 2086 | goto exit_remove; |
2040 | } | 2087 | } |
2041 | } | 2088 | } |
@@ -2044,14 +2091,17 @@ static int dme1737_create_files(struct device *dev) | |||
2044 | /* Create PWM sysfs attributes */ | 2091 | /* Create PWM sysfs attributes */ |
2045 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { | 2092 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { |
2046 | if (data->has_features & HAS_PWM(ix)) { | 2093 | if (data->has_features & HAS_PWM(ix)) { |
2047 | if ((err = sysfs_create_group(&dev->kobj, | 2094 | err = sysfs_create_group(&dev->kobj, |
2048 | &dme1737_pwm_group[ix]))) { | 2095 | &dme1737_pwm_group[ix]); |
2096 | if (err) { | ||
2049 | goto exit_remove; | 2097 | goto exit_remove; |
2050 | } | 2098 | } |
2051 | if ((data->has_features & HAS_PWM_MIN) && ix < 3 && | 2099 | if ((data->has_features & HAS_PWM_MIN) && (ix < 3)) { |
2052 | (err = sysfs_create_file(&dev->kobj, | 2100 | err = sysfs_create_file(&dev->kobj, |
2053 | dme1737_auto_pwm_min_attr[ix]))) { | 2101 | dme1737_auto_pwm_min_attr[ix]); |
2054 | goto exit_remove; | 2102 | if (err) { |
2103 | goto exit_remove; | ||
2104 | } | ||
2055 | } | 2105 | } |
2056 | } | 2106 | } |
2057 | } | 2107 | } |
@@ -2188,7 +2238,7 @@ static int dme1737_init_device(struct device *dev) | |||
2188 | data->has_features |= HAS_ZONE3; | 2238 | data->has_features |= HAS_ZONE3; |
2189 | break; | 2239 | break; |
2190 | case sch5127: | 2240 | case sch5127: |
2191 | data->has_features |= HAS_FAN(2) | HAS_PWM(2); | 2241 | data->has_features |= HAS_FAN(2) | HAS_PWM(2) | HAS_IN7; |
2192 | break; | 2242 | break; |
2193 | default: | 2243 | default: |
2194 | break; | 2244 | break; |
@@ -2281,8 +2331,9 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) | |||
2281 | dme1737_sio_outb(sio_cip, 0x07, 0x0a); | 2331 | dme1737_sio_outb(sio_cip, 0x07, 0x0a); |
2282 | 2332 | ||
2283 | /* Get the base address of the runtime registers */ | 2333 | /* Get the base address of the runtime registers */ |
2284 | if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | | 2334 | addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | |
2285 | dme1737_sio_inb(sio_cip, 0x61))) { | 2335 | dme1737_sio_inb(sio_cip, 0x61); |
2336 | if (!addr) { | ||
2286 | err = -ENODEV; | 2337 | err = -ENODEV; |
2287 | goto exit; | 2338 | goto exit; |
2288 | } | 2339 | } |
@@ -2363,13 +2414,15 @@ static int dme1737_i2c_probe(struct i2c_client *client, | |||
2363 | mutex_init(&data->update_lock); | 2414 | mutex_init(&data->update_lock); |
2364 | 2415 | ||
2365 | /* Initialize the DME1737 chip */ | 2416 | /* Initialize the DME1737 chip */ |
2366 | if ((err = dme1737_init_device(dev))) { | 2417 | err = dme1737_init_device(dev); |
2418 | if (err) { | ||
2367 | dev_err(dev, "Failed to initialize device.\n"); | 2419 | dev_err(dev, "Failed to initialize device.\n"); |
2368 | goto exit_kfree; | 2420 | goto exit_kfree; |
2369 | } | 2421 | } |
2370 | 2422 | ||
2371 | /* Create sysfs files */ | 2423 | /* Create sysfs files */ |
2372 | if ((err = dme1737_create_files(dev))) { | 2424 | err = dme1737_create_files(dev); |
2425 | if (err) { | ||
2373 | dev_err(dev, "Failed to create sysfs files.\n"); | 2426 | dev_err(dev, "Failed to create sysfs files.\n"); |
2374 | goto exit_kfree; | 2427 | goto exit_kfree; |
2375 | } | 2428 | } |
@@ -2446,8 +2499,9 @@ static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) | |||
2446 | dme1737_sio_outb(sio_cip, 0x07, 0x0a); | 2499 | dme1737_sio_outb(sio_cip, 0x07, 0x0a); |
2447 | 2500 | ||
2448 | /* Get the base address of the runtime registers */ | 2501 | /* Get the base address of the runtime registers */ |
2449 | if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | | 2502 | base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | |
2450 | dme1737_sio_inb(sio_cip, 0x61))) { | 2503 | dme1737_sio_inb(sio_cip, 0x61); |
2504 | if (!base_addr) { | ||
2451 | pr_err("Base address not set\n"); | 2505 | pr_err("Base address not set\n"); |
2452 | err = -ENODEV; | 2506 | err = -ENODEV; |
2453 | goto exit; | 2507 | goto exit; |
@@ -2476,18 +2530,21 @@ static int __init dme1737_isa_device_add(unsigned short addr) | |||
2476 | if (err) | 2530 | if (err) |
2477 | goto exit; | 2531 | goto exit; |
2478 | 2532 | ||
2479 | if (!(pdev = platform_device_alloc("dme1737", addr))) { | 2533 | pdev = platform_device_alloc("dme1737", addr); |
2534 | if (!pdev) { | ||
2480 | pr_err("Failed to allocate device\n"); | 2535 | pr_err("Failed to allocate device\n"); |
2481 | err = -ENOMEM; | 2536 | err = -ENOMEM; |
2482 | goto exit; | 2537 | goto exit; |
2483 | } | 2538 | } |
2484 | 2539 | ||
2485 | if ((err = platform_device_add_resources(pdev, &res, 1))) { | 2540 | err = platform_device_add_resources(pdev, &res, 1); |
2541 | if (err) { | ||
2486 | pr_err("Failed to add device resource (err = %d)\n", err); | 2542 | pr_err("Failed to add device resource (err = %d)\n", err); |
2487 | goto exit_device_put; | 2543 | goto exit_device_put; |
2488 | } | 2544 | } |
2489 | 2545 | ||
2490 | if ((err = platform_device_add(pdev))) { | 2546 | err = platform_device_add(pdev); |
2547 | if (err) { | ||
2491 | pr_err("Failed to add device (err = %d)\n", err); | 2548 | pr_err("Failed to add device (err = %d)\n", err); |
2492 | goto exit_device_put; | 2549 | goto exit_device_put; |
2493 | } | 2550 | } |
@@ -2514,11 +2571,12 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) | |||
2514 | dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", | 2571 | dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", |
2515 | (unsigned short)res->start, | 2572 | (unsigned short)res->start, |
2516 | (unsigned short)res->start + DME1737_EXTENT - 1); | 2573 | (unsigned short)res->start + DME1737_EXTENT - 1); |
2517 | err = -EBUSY; | 2574 | err = -EBUSY; |
2518 | goto exit; | 2575 | goto exit; |
2519 | } | 2576 | } |
2520 | 2577 | ||
2521 | if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) { | 2578 | data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); |
2579 | if (!data) { | ||
2522 | err = -ENOMEM; | 2580 | err = -ENOMEM; |
2523 | goto exit_release_region; | 2581 | goto exit_release_region; |
2524 | } | 2582 | } |
@@ -2565,13 +2623,15 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) | |||
2565 | data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr); | 2623 | data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr); |
2566 | 2624 | ||
2567 | /* Initialize the chip */ | 2625 | /* Initialize the chip */ |
2568 | if ((err = dme1737_init_device(dev))) { | 2626 | err = dme1737_init_device(dev); |
2627 | if (err) { | ||
2569 | dev_err(dev, "Failed to initialize device.\n"); | 2628 | dev_err(dev, "Failed to initialize device.\n"); |
2570 | goto exit_kfree; | 2629 | goto exit_kfree; |
2571 | } | 2630 | } |
2572 | 2631 | ||
2573 | /* Create sysfs files */ | 2632 | /* Create sysfs files */ |
2574 | if ((err = dme1737_create_files(dev))) { | 2633 | err = dme1737_create_files(dev); |
2634 | if (err) { | ||
2575 | dev_err(dev, "Failed to create sysfs files.\n"); | 2635 | dev_err(dev, "Failed to create sysfs files.\n"); |
2576 | goto exit_kfree; | 2636 | goto exit_kfree; |
2577 | } | 2637 | } |
@@ -2628,7 +2688,8 @@ static int __init dme1737_init(void) | |||
2628 | int err; | 2688 | int err; |
2629 | unsigned short addr; | 2689 | unsigned short addr; |
2630 | 2690 | ||
2631 | if ((err = i2c_add_driver(&dme1737_i2c_driver))) { | 2691 | err = i2c_add_driver(&dme1737_i2c_driver); |
2692 | if (err) { | ||
2632 | goto exit; | 2693 | goto exit; |
2633 | } | 2694 | } |
2634 | 2695 | ||
@@ -2641,12 +2702,14 @@ static int __init dme1737_init(void) | |||
2641 | return 0; | 2702 | return 0; |
2642 | } | 2703 | } |
2643 | 2704 | ||
2644 | if ((err = platform_driver_register(&dme1737_isa_driver))) { | 2705 | err = platform_driver_register(&dme1737_isa_driver); |
2706 | if (err) { | ||
2645 | goto exit_del_i2c_driver; | 2707 | goto exit_del_i2c_driver; |
2646 | } | 2708 | } |
2647 | 2709 | ||
2648 | /* Sets global pdev as a side effect */ | 2710 | /* Sets global pdev as a side effect */ |
2649 | if ((err = dme1737_isa_device_add(addr))) { | 2711 | err = dme1737_isa_device_add(addr); |
2712 | if (err) { | ||
2650 | goto exit_del_isa_driver; | 2713 | goto exit_del_isa_driver; |
2651 | } | 2714 | } |
2652 | 2715 | ||
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 8dee3f38fdfb..5dea9faa1656 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c | |||
@@ -269,23 +269,30 @@ static int emc1403_detect(struct i2c_client *client, | |||
269 | struct i2c_board_info *info) | 269 | struct i2c_board_info *info) |
270 | { | 270 | { |
271 | int id; | 271 | int id; |
272 | /* Check if thermal chip is SMSC and EMC1403 */ | 272 | /* Check if thermal chip is SMSC and EMC1403 or EMC1423 */ |
273 | 273 | ||
274 | id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG); | 274 | id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG); |
275 | if (id != 0x5d) | 275 | if (id != 0x5d) |
276 | return -ENODEV; | 276 | return -ENODEV; |
277 | 277 | ||
278 | id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); | ||
279 | switch (id) { | ||
280 | case 0x21: | ||
281 | strlcpy(info->type, "emc1403", I2C_NAME_SIZE); | ||
282 | break; | ||
283 | case 0x23: | ||
284 | strlcpy(info->type, "emc1423", I2C_NAME_SIZE); | ||
285 | break; | ||
278 | /* Note: 0x25 is the 1404 which is very similar and this | 286 | /* Note: 0x25 is the 1404 which is very similar and this |
279 | driver could be extended */ | 287 | driver could be extended */ |
280 | id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); | 288 | default: |
281 | if (id != 0x21) | ||
282 | return -ENODEV; | 289 | return -ENODEV; |
290 | } | ||
283 | 291 | ||
284 | id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); | 292 | id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); |
285 | if (id != 0x01) | 293 | if (id != 0x01) |
286 | return -ENODEV; | 294 | return -ENODEV; |
287 | 295 | ||
288 | strlcpy(info->type, "emc1403", I2C_NAME_SIZE); | ||
289 | return 0; | 296 | return 0; |
290 | } | 297 | } |
291 | 298 | ||
@@ -342,6 +349,7 @@ static const unsigned short emc1403_address_list[] = { | |||
342 | 349 | ||
343 | static const struct i2c_device_id emc1403_idtable[] = { | 350 | static const struct i2c_device_id emc1403_idtable[] = { |
344 | { "emc1403", 0 }, | 351 | { "emc1403", 0 }, |
352 | { "emc1423", 0 }, | ||
345 | { } | 353 | { } |
346 | }; | 354 | }; |
347 | MODULE_DEVICE_TABLE(i2c, emc1403_idtable); | 355 | MODULE_DEVICE_TABLE(i2c, emc1403_idtable); |
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index d4d4ca65d371..aa6d8b686f82 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/kref.h> | 49 | #include <linux/kref.h> |
50 | 50 | ||
51 | /* Addresses to scan */ | 51 | /* Addresses to scan */ |
52 | static DEFINE_MUTEX(watchdog_mutex); | ||
53 | static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; | 52 | static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; |
54 | 53 | ||
55 | /* Insmod parameters */ | 54 | /* Insmod parameters */ |
@@ -850,7 +849,7 @@ static ssize_t watchdog_write(struct file *filp, const char __user *buf, | |||
850 | 849 | ||
851 | static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 850 | static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
852 | { | 851 | { |
853 | static struct watchdog_info ident = { | 852 | struct watchdog_info ident = { |
854 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | 853 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
855 | WDIOF_CARDRESET, | 854 | WDIOF_CARDRESET, |
856 | .identity = "FSC watchdog" | 855 | .identity = "FSC watchdog" |
@@ -858,7 +857,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar | |||
858 | int i, ret = 0; | 857 | int i, ret = 0; |
859 | struct fschmd_data *data = filp->private_data; | 858 | struct fschmd_data *data = filp->private_data; |
860 | 859 | ||
861 | mutex_lock(&watchdog_mutex); | ||
862 | switch (cmd) { | 860 | switch (cmd) { |
863 | case WDIOC_GETSUPPORT: | 861 | case WDIOC_GETSUPPORT: |
864 | ident.firmware_version = data->revision; | 862 | ident.firmware_version = data->revision; |
@@ -915,7 +913,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long ar | |||
915 | default: | 913 | default: |
916 | ret = -ENOTTY; | 914 | ret = -ENOTTY; |
917 | } | 915 | } |
918 | mutex_unlock(&watchdog_mutex); | ||
919 | return ret; | 916 | return ret; |
920 | } | 917 | } |
921 | 918 | ||
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index a428a9264195..316b64823f7b 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -38,6 +38,8 @@ | |||
38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
39 | */ | 39 | */ |
40 | 40 | ||
41 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
42 | |||
41 | #include <linux/module.h> | 43 | #include <linux/module.h> |
42 | #include <linux/init.h> | 44 | #include <linux/init.h> |
43 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
@@ -1570,26 +1572,25 @@ static int __init it87_find(unsigned short *address, | |||
1570 | case 0xffff: /* No device at all */ | 1572 | case 0xffff: /* No device at all */ |
1571 | goto exit; | 1573 | goto exit; |
1572 | default: | 1574 | default: |
1573 | pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n", | 1575 | pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type); |
1574 | chip_type); | ||
1575 | goto exit; | 1576 | goto exit; |
1576 | } | 1577 | } |
1577 | 1578 | ||
1578 | superio_select(PME); | 1579 | superio_select(PME); |
1579 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { | 1580 | if (!(superio_inb(IT87_ACT_REG) & 0x01)) { |
1580 | pr_info("it87: Device not activated, skipping\n"); | 1581 | pr_info("Device not activated, skipping\n"); |
1581 | goto exit; | 1582 | goto exit; |
1582 | } | 1583 | } |
1583 | 1584 | ||
1584 | *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); | 1585 | *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); |
1585 | if (*address == 0) { | 1586 | if (*address == 0) { |
1586 | pr_info("it87: Base address not set, skipping\n"); | 1587 | pr_info("Base address not set, skipping\n"); |
1587 | goto exit; | 1588 | goto exit; |
1588 | } | 1589 | } |
1589 | 1590 | ||
1590 | err = 0; | 1591 | err = 0; |
1591 | sio_data->revision = superio_inb(DEVREV) & 0x0f; | 1592 | sio_data->revision = superio_inb(DEVREV) & 0x0f; |
1592 | pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n", | 1593 | pr_info("Found IT%04xF chip at 0x%x, revision %d\n", |
1593 | chip_type, *address, sio_data->revision); | 1594 | chip_type, *address, sio_data->revision); |
1594 | 1595 | ||
1595 | /* in8 (Vbat) is always internal */ | 1596 | /* in8 (Vbat) is always internal */ |
@@ -1615,7 +1616,7 @@ static int __init it87_find(unsigned short *address, | |||
1615 | } else { | 1616 | } else { |
1616 | /* We need at least 4 VID pins */ | 1617 | /* We need at least 4 VID pins */ |
1617 | if (reg & 0x0f) { | 1618 | if (reg & 0x0f) { |
1618 | pr_info("it87: VID is disabled (pins used for GPIO)\n"); | 1619 | pr_info("VID is disabled (pins used for GPIO)\n"); |
1619 | sio_data->skip_vid = 1; | 1620 | sio_data->skip_vid = 1; |
1620 | } | 1621 | } |
1621 | } | 1622 | } |
@@ -1651,7 +1652,7 @@ static int __init it87_find(unsigned short *address, | |||
1651 | if (sio_data->type == it8720 && !(reg & (1 << 1))) { | 1652 | if (sio_data->type == it8720 && !(reg & (1 << 1))) { |
1652 | reg |= (1 << 1); | 1653 | reg |= (1 << 1); |
1653 | superio_outb(IT87_SIO_PINX2_REG, reg); | 1654 | superio_outb(IT87_SIO_PINX2_REG, reg); |
1654 | pr_notice("it87: Routing internal VCCH to in7\n"); | 1655 | pr_notice("Routing internal VCCH to in7\n"); |
1655 | } | 1656 | } |
1656 | if (reg & (1 << 0)) | 1657 | if (reg & (1 << 0)) |
1657 | sio_data->internal |= (1 << 0); | 1658 | sio_data->internal |= (1 << 0); |
@@ -1661,7 +1662,7 @@ static int __init it87_find(unsigned short *address, | |||
1661 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; | 1662 | sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; |
1662 | } | 1663 | } |
1663 | if (sio_data->beep_pin) | 1664 | if (sio_data->beep_pin) |
1664 | pr_info("it87: Beeping is supported\n"); | 1665 | pr_info("Beeping is supported\n"); |
1665 | 1666 | ||
1666 | /* Disable specific features based on DMI strings */ | 1667 | /* Disable specific features based on DMI strings */ |
1667 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | 1668 | board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); |
@@ -1675,8 +1676,7 @@ static int __init it87_find(unsigned short *address, | |||
1675 | the PWM2 duty cycle, so we disable it. | 1676 | the PWM2 duty cycle, so we disable it. |
1676 | I use the board name string as the trigger in case | 1677 | I use the board name string as the trigger in case |
1677 | the same board is ever used in other systems. */ | 1678 | the same board is ever used in other systems. */ |
1678 | pr_info("it87: Disabling pwm2 due to " | 1679 | pr_info("Disabling pwm2 due to hardware constraints\n"); |
1679 | "hardware constraints\n"); | ||
1680 | sio_data->skip_pwm = (1 << 1); | 1680 | sio_data->skip_pwm = (1 << 1); |
1681 | } | 1681 | } |
1682 | } | 1682 | } |
@@ -2189,28 +2189,26 @@ static int __init it87_device_add(unsigned short address, | |||
2189 | pdev = platform_device_alloc(DRVNAME, address); | 2189 | pdev = platform_device_alloc(DRVNAME, address); |
2190 | if (!pdev) { | 2190 | if (!pdev) { |
2191 | err = -ENOMEM; | 2191 | err = -ENOMEM; |
2192 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | 2192 | pr_err("Device allocation failed\n"); |
2193 | goto exit; | 2193 | goto exit; |
2194 | } | 2194 | } |
2195 | 2195 | ||
2196 | err = platform_device_add_resources(pdev, &res, 1); | 2196 | err = platform_device_add_resources(pdev, &res, 1); |
2197 | if (err) { | 2197 | if (err) { |
2198 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 2198 | pr_err("Device resource addition failed (%d)\n", err); |
2199 | "(%d)\n", err); | ||
2200 | goto exit_device_put; | 2199 | goto exit_device_put; |
2201 | } | 2200 | } |
2202 | 2201 | ||
2203 | err = platform_device_add_data(pdev, sio_data, | 2202 | err = platform_device_add_data(pdev, sio_data, |
2204 | sizeof(struct it87_sio_data)); | 2203 | sizeof(struct it87_sio_data)); |
2205 | if (err) { | 2204 | if (err) { |
2206 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | 2205 | pr_err("Platform data allocation failed\n"); |
2207 | goto exit_device_put; | 2206 | goto exit_device_put; |
2208 | } | 2207 | } |
2209 | 2208 | ||
2210 | err = platform_device_add(pdev); | 2209 | err = platform_device_add(pdev); |
2211 | if (err) { | 2210 | if (err) { |
2212 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | 2211 | pr_err("Device addition failed (%d)\n", err); |
2213 | err); | ||
2214 | goto exit_device_put; | 2212 | goto exit_device_put; |
2215 | } | 2213 | } |
2216 | 2214 | ||
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 72ff2c4e757d..4cb24eafe318 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
@@ -19,6 +19,8 @@ | |||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
23 | #include <linux/init.h> | 25 | #include <linux/init.h> |
24 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
@@ -858,7 +860,7 @@ static int __init lm78_isa_found(unsigned short address) | |||
858 | * individually for the probing phase. */ | 860 | * individually for the probing phase. */ |
859 | for (port = address; port < address + LM78_EXTENT; port++) { | 861 | for (port = address; port < address + LM78_EXTENT; port++) { |
860 | if (!request_region(port, 1, "lm78")) { | 862 | if (!request_region(port, 1, "lm78")) { |
861 | pr_debug("lm78: Failed to request port 0x%x\n", port); | 863 | pr_debug("Failed to request port 0x%x\n", port); |
862 | goto release; | 864 | goto release; |
863 | } | 865 | } |
864 | } | 866 | } |
@@ -920,7 +922,7 @@ static int __init lm78_isa_found(unsigned short address) | |||
920 | found = 1; | 922 | found = 1; |
921 | 923 | ||
922 | if (found) | 924 | if (found) |
923 | pr_info("lm78: Found an %s chip at %#x\n", | 925 | pr_info("Found an %s chip at %#x\n", |
924 | val & 0x80 ? "LM79" : "LM78", (int)address); | 926 | val & 0x80 ? "LM79" : "LM78", (int)address); |
925 | 927 | ||
926 | release: | 928 | release: |
@@ -942,21 +944,19 @@ static int __init lm78_isa_device_add(unsigned short address) | |||
942 | pdev = platform_device_alloc("lm78", address); | 944 | pdev = platform_device_alloc("lm78", address); |
943 | if (!pdev) { | 945 | if (!pdev) { |
944 | err = -ENOMEM; | 946 | err = -ENOMEM; |
945 | printk(KERN_ERR "lm78: Device allocation failed\n"); | 947 | pr_err("Device allocation failed\n"); |
946 | goto exit; | 948 | goto exit; |
947 | } | 949 | } |
948 | 950 | ||
949 | err = platform_device_add_resources(pdev, &res, 1); | 951 | err = platform_device_add_resources(pdev, &res, 1); |
950 | if (err) { | 952 | if (err) { |
951 | printk(KERN_ERR "lm78: Device resource addition failed " | 953 | pr_err("Device resource addition failed (%d)\n", err); |
952 | "(%d)\n", err); | ||
953 | goto exit_device_put; | 954 | goto exit_device_put; |
954 | } | 955 | } |
955 | 956 | ||
956 | err = platform_device_add(pdev); | 957 | err = platform_device_add(pdev); |
957 | if (err) { | 958 | if (err) { |
958 | printk(KERN_ERR "lm78: Device addition failed (%d)\n", | 959 | pr_err("Device addition failed (%d)\n", err); |
959 | err); | ||
960 | goto exit_device_put; | 960 | goto exit_device_put; |
961 | } | 961 | } |
962 | 962 | ||
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 68e69a49633c..3d99b8854d7c 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
@@ -33,6 +33,8 @@ | |||
33 | * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F). | 33 | * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F). |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
37 | |||
36 | #include <linux/module.h> | 38 | #include <linux/module.h> |
37 | #include <linux/init.h> | 39 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
@@ -1031,16 +1033,15 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses | |||
1031 | 1033 | ||
1032 | val = superio_inb(sioaddr, ACT); | 1034 | val = superio_inb(sioaddr, ACT); |
1033 | if (!(val & 0x01)) { | 1035 | if (!(val & 0x01)) { |
1034 | printk(KERN_INFO "pc87360: Device 0x%02x not " | 1036 | pr_info("Device 0x%02x not activated\n", logdev[i]); |
1035 | "activated\n", logdev[i]); | ||
1036 | continue; | 1037 | continue; |
1037 | } | 1038 | } |
1038 | 1039 | ||
1039 | val = (superio_inb(sioaddr, BASE) << 8) | 1040 | val = (superio_inb(sioaddr, BASE) << 8) |
1040 | | superio_inb(sioaddr, BASE + 1); | 1041 | | superio_inb(sioaddr, BASE + 1); |
1041 | if (!val) { | 1042 | if (!val) { |
1042 | printk(KERN_INFO "pc87360: Base address not set for " | 1043 | pr_info("Base address not set for device 0x%02x\n", |
1043 | "device 0x%02x\n", logdev[i]); | 1044 | logdev[i]); |
1044 | continue; | 1045 | continue; |
1045 | } | 1046 | } |
1046 | 1047 | ||
@@ -1050,17 +1051,15 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses | |||
1050 | confreg[0] = superio_inb(sioaddr, 0xF0); | 1051 | confreg[0] = superio_inb(sioaddr, 0xF0); |
1051 | confreg[1] = superio_inb(sioaddr, 0xF1); | 1052 | confreg[1] = superio_inb(sioaddr, 0xF1); |
1052 | 1053 | ||
1053 | #ifdef DEBUG | 1054 | pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 1, |
1054 | printk(KERN_DEBUG "pc87360: Fan 1: mon=%d " | 1055 | (confreg[0] >> 2) & 1, (confreg[0] >> 3) & 1, |
1055 | "ctrl=%d inv=%d\n", (confreg[0]>>2)&1, | 1056 | (confreg[0] >> 4) & 1); |
1056 | (confreg[0]>>3)&1, (confreg[0]>>4)&1); | 1057 | pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 2, |
1057 | printk(KERN_DEBUG "pc87360: Fan 2: mon=%d " | 1058 | (confreg[0] >> 5) & 1, (confreg[0] >> 6) & 1, |
1058 | "ctrl=%d inv=%d\n", (confreg[0]>>5)&1, | 1059 | (confreg[0] >> 7) & 1); |
1059 | (confreg[0]>>6)&1, (confreg[0]>>7)&1); | 1060 | pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3, |
1060 | printk(KERN_DEBUG "pc87360: Fan 3: mon=%d " | 1061 | confreg[1] & 1, (confreg[1] >> 1) & 1, |
1061 | "ctrl=%d inv=%d\n", confreg[1]&1, | 1062 | (confreg[1] >> 2) & 1); |
1062 | (confreg[1]>>1)&1, (confreg[1]>>2)&1); | ||
1063 | #endif | ||
1064 | } else if (i==1) { /* Voltages */ | 1063 | } else if (i==1) { /* Voltages */ |
1065 | /* Are we using thermistors? */ | 1064 | /* Are we using thermistors? */ |
1066 | if (*devid == 0xE9) { /* PC87366 */ | 1065 | if (*devid == 0xE9) { /* PC87366 */ |
@@ -1071,14 +1070,12 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses | |||
1071 | confreg[3] = superio_inb(sioaddr, 0x25); | 1070 | confreg[3] = superio_inb(sioaddr, 0x25); |
1072 | 1071 | ||
1073 | if (confreg[2] & 0x40) { | 1072 | if (confreg[2] & 0x40) { |
1074 | printk(KERN_INFO "pc87360: Using " | 1073 | pr_info("Using thermistors for " |
1075 | "thermistors for temperature " | 1074 | "temperature monitoring\n"); |
1076 | "monitoring\n"); | ||
1077 | } | 1075 | } |
1078 | if (confreg[3] & 0xE0) { | 1076 | if (confreg[3] & 0xE0) { |
1079 | printk(KERN_INFO "pc87360: VID " | 1077 | pr_info("VID inputs routed (mode %u)\n", |
1080 | "inputs routed (mode %u)\n", | 1078 | confreg[3] >> 5); |
1081 | confreg[3] >> 5); | ||
1082 | } | 1079 | } |
1083 | } | 1080 | } |
1084 | } | 1081 | } |
@@ -1616,7 +1613,7 @@ static int __init pc87360_device_add(unsigned short address) | |||
1616 | pdev = platform_device_alloc("pc87360", address); | 1613 | pdev = platform_device_alloc("pc87360", address); |
1617 | if (!pdev) { | 1614 | if (!pdev) { |
1618 | err = -ENOMEM; | 1615 | err = -ENOMEM; |
1619 | printk(KERN_ERR "pc87360: Device allocation failed\n"); | 1616 | pr_err("Device allocation failed\n"); |
1620 | goto exit; | 1617 | goto exit; |
1621 | } | 1618 | } |
1622 | 1619 | ||
@@ -1639,15 +1636,13 @@ static int __init pc87360_device_add(unsigned short address) | |||
1639 | 1636 | ||
1640 | err = platform_device_add_resources(pdev, res, res_count); | 1637 | err = platform_device_add_resources(pdev, res, res_count); |
1641 | if (err) { | 1638 | if (err) { |
1642 | printk(KERN_ERR "pc87360: Device resources addition failed " | 1639 | pr_err("Device resources addition failed (%d)\n", err); |
1643 | "(%d)\n", err); | ||
1644 | goto exit_device_put; | 1640 | goto exit_device_put; |
1645 | } | 1641 | } |
1646 | 1642 | ||
1647 | err = platform_device_add(pdev); | 1643 | err = platform_device_add(pdev); |
1648 | if (err) { | 1644 | if (err) { |
1649 | printk(KERN_ERR "pc87360: Device addition failed (%d)\n", | 1645 | pr_err("Device addition failed (%d)\n", err); |
1650 | err); | ||
1651 | goto exit_device_put; | 1646 | goto exit_device_put; |
1652 | } | 1647 | } |
1653 | 1648 | ||
@@ -1666,8 +1661,7 @@ static int __init pc87360_init(void) | |||
1666 | 1661 | ||
1667 | if (pc87360_find(0x2e, &devid, extra_isa) | 1662 | if (pc87360_find(0x2e, &devid, extra_isa) |
1668 | && pc87360_find(0x4e, &devid, extra_isa)) { | 1663 | && pc87360_find(0x4e, &devid, extra_isa)) { |
1669 | printk(KERN_WARNING "pc87360: PC8736x not detected, " | 1664 | pr_warn("PC8736x not detected, module not inserted\n"); |
1670 | "module not inserted.\n"); | ||
1671 | return -ENODEV; | 1665 | return -ENODEV; |
1672 | } | 1666 | } |
1673 | 1667 | ||
@@ -1680,8 +1674,7 @@ static int __init pc87360_init(void) | |||
1680 | } | 1674 | } |
1681 | 1675 | ||
1682 | if (address == 0x0000) { | 1676 | if (address == 0x0000) { |
1683 | printk(KERN_WARNING "pc87360: No active logical device, " | 1677 | pr_warn("No active logical device, module not inserted\n"); |
1684 | "module not inserted.\n"); | ||
1685 | return -ENODEV; | 1678 | return -ENODEV; |
1686 | } | 1679 | } |
1687 | 1680 | ||
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 9ec4daaf6ca6..8da2181630b1 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c | |||
@@ -22,6 +22,8 @@ | |||
22 | * mode, and voltages aren't supported at all. | 22 | * mode, and voltages aren't supported at all. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
26 | |||
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
26 | #include <linux/init.h> | 28 | #include <linux/init.h> |
27 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
@@ -1077,7 +1079,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev) | |||
1077 | data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL); | 1079 | data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL); |
1078 | if (!data) { | 1080 | if (!data) { |
1079 | err = -ENOMEM; | 1081 | err = -ENOMEM; |
1080 | printk(KERN_ERR DRVNAME ": Out of memory\n"); | 1082 | pr_err("Out of memory\n"); |
1081 | goto exit; | 1083 | goto exit; |
1082 | } | 1084 | } |
1083 | 1085 | ||
@@ -1196,28 +1198,26 @@ static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data) | |||
1196 | pdev = platform_device_alloc(DRVNAME, res[0].start); | 1198 | pdev = platform_device_alloc(DRVNAME, res[0].start); |
1197 | if (!pdev) { | 1199 | if (!pdev) { |
1198 | err = -ENOMEM; | 1200 | err = -ENOMEM; |
1199 | printk(KERN_ERR DRVNAME ": Device allocation failed\n"); | 1201 | pr_err("Device allocation failed\n"); |
1200 | goto exit; | 1202 | goto exit; |
1201 | } | 1203 | } |
1202 | 1204 | ||
1203 | err = platform_device_add_resources(pdev, res, res_count); | 1205 | err = platform_device_add_resources(pdev, res, res_count); |
1204 | if (err) { | 1206 | if (err) { |
1205 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 1207 | pr_err("Device resource addition failed (%d)\n", err); |
1206 | "(%d)\n", err); | ||
1207 | goto exit_device_put; | 1208 | goto exit_device_put; |
1208 | } | 1209 | } |
1209 | 1210 | ||
1210 | err = platform_device_add_data(pdev, sio_data, | 1211 | err = platform_device_add_data(pdev, sio_data, |
1211 | sizeof(struct pc87427_sio_data)); | 1212 | sizeof(struct pc87427_sio_data)); |
1212 | if (err) { | 1213 | if (err) { |
1213 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | 1214 | pr_err("Platform data allocation failed\n"); |
1214 | goto exit_device_put; | 1215 | goto exit_device_put; |
1215 | } | 1216 | } |
1216 | 1217 | ||
1217 | err = platform_device_add(pdev); | 1218 | err = platform_device_add(pdev); |
1218 | if (err) { | 1219 | if (err) { |
1219 | printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", | 1220 | pr_err("Device addition failed (%d)\n", err); |
1220 | err); | ||
1221 | goto exit_device_put; | 1221 | goto exit_device_put; |
1222 | } | 1222 | } |
1223 | 1223 | ||
@@ -1249,23 +1249,23 @@ static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) | |||
1249 | 1249 | ||
1250 | val = superio_inb(sioaddr, SIOREG_ACT); | 1250 | val = superio_inb(sioaddr, SIOREG_ACT); |
1251 | if (!(val & 0x01)) { | 1251 | if (!(val & 0x01)) { |
1252 | printk(KERN_INFO DRVNAME ": Logical device 0x%02x " | 1252 | pr_info("Logical device 0x%02x not activated\n", |
1253 | "not activated\n", logdev[i]); | 1253 | logdev[i]); |
1254 | continue; | 1254 | continue; |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | val = superio_inb(sioaddr, SIOREG_MAP); | 1257 | val = superio_inb(sioaddr, SIOREG_MAP); |
1258 | if (val & 0x01) { | 1258 | if (val & 0x01) { |
1259 | printk(KERN_WARNING DRVNAME ": Logical device 0x%02x " | 1259 | pr_warn("Logical device 0x%02x is memory-mapped, " |
1260 | "is memory-mapped, can't use\n", logdev[i]); | 1260 | "can't use\n", logdev[i]); |
1261 | continue; | 1261 | continue; |
1262 | } | 1262 | } |
1263 | 1263 | ||
1264 | val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8) | 1264 | val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8) |
1265 | | superio_inb(sioaddr, SIOREG_IOBASE + 1); | 1265 | | superio_inb(sioaddr, SIOREG_IOBASE + 1); |
1266 | if (!val) { | 1266 | if (!val) { |
1267 | printk(KERN_INFO DRVNAME ": I/O base address not set " | 1267 | pr_info("I/O base address not set for logical device " |
1268 | "for logical device 0x%02x\n", logdev[i]); | 1268 | "0x%02x\n", logdev[i]); |
1269 | continue; | 1269 | continue; |
1270 | } | 1270 | } |
1271 | sio_data->address[i] = val; | 1271 | sio_data->address[i] = val; |
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 13e8d218e495..25e91665a0a2 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c | |||
@@ -689,6 +689,13 @@ static int __devexit via686a_remove(struct platform_device *pdev) | |||
689 | return 0; | 689 | return 0; |
690 | } | 690 | } |
691 | 691 | ||
692 | static void via686a_update_fan_div(struct via686a_data *data) | ||
693 | { | ||
694 | int reg = via686a_read_value(data, VIA686A_REG_FANDIV); | ||
695 | data->fan_div[0] = (reg >> 4) & 0x03; | ||
696 | data->fan_div[1] = reg >> 6; | ||
697 | } | ||
698 | |||
692 | static void __devinit via686a_init_device(struct via686a_data *data) | 699 | static void __devinit via686a_init_device(struct via686a_data *data) |
693 | { | 700 | { |
694 | u8 reg; | 701 | u8 reg; |
@@ -702,6 +709,9 @@ static void __devinit via686a_init_device(struct via686a_data *data) | |||
702 | via686a_write_value(data, VIA686A_REG_TEMP_MODE, | 709 | via686a_write_value(data, VIA686A_REG_TEMP_MODE, |
703 | (reg & ~VIA686A_TEMP_MODE_MASK) | 710 | (reg & ~VIA686A_TEMP_MODE_MASK) |
704 | | VIA686A_TEMP_MODE_CONTINUOUS); | 711 | | VIA686A_TEMP_MODE_CONTINUOUS); |
712 | |||
713 | /* Pre-read fan clock divisor values */ | ||
714 | via686a_update_fan_div(data); | ||
705 | } | 715 | } |
706 | 716 | ||
707 | static struct via686a_data *via686a_update_device(struct device *dev) | 717 | static struct via686a_data *via686a_update_device(struct device *dev) |
@@ -753,9 +763,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) | |||
753 | (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & | 763 | (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & |
754 | 0xc0) >> 6; | 764 | 0xc0) >> 6; |
755 | 765 | ||
756 | i = via686a_read_value(data, VIA686A_REG_FANDIV); | 766 | via686a_update_fan_div(data); |
757 | data->fan_div[0] = (i >> 4) & 0x03; | ||
758 | data->fan_div[1] = i >> 6; | ||
759 | data->alarms = | 767 | data->alarms = |
760 | via686a_read_value(data, | 768 | via686a_read_value(data, |
761 | VIA686A_REG_ALARM1) | | 769 | VIA686A_REG_ALARM1) | |
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index c84b9b4e6960..eed43a008be1 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -33,6 +33,8 @@ | |||
33 | 33 | ||
34 | */ | 34 | */ |
35 | 35 | ||
36 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
37 | |||
36 | #include <linux/module.h> | 38 | #include <linux/module.h> |
37 | #include <linux/init.h> | 39 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
@@ -1798,8 +1800,7 @@ w83781d_isa_found(unsigned short address) | |||
1798 | * individually for the probing phase. */ | 1800 | * individually for the probing phase. */ |
1799 | for (port = address; port < address + W83781D_EXTENT; port++) { | 1801 | for (port = address; port < address + W83781D_EXTENT; port++) { |
1800 | if (!request_region(port, 1, "w83781d")) { | 1802 | if (!request_region(port, 1, "w83781d")) { |
1801 | pr_debug("w83781d: Failed to request port 0x%x\n", | 1803 | pr_debug("Failed to request port 0x%x\n", port); |
1802 | port); | ||
1803 | goto release; | 1804 | goto release; |
1804 | } | 1805 | } |
1805 | } | 1806 | } |
@@ -1811,7 +1812,7 @@ w83781d_isa_found(unsigned short address) | |||
1811 | if (inb_p(address + 2) != val | 1812 | if (inb_p(address + 2) != val |
1812 | || inb_p(address + 3) != val | 1813 | || inb_p(address + 3) != val |
1813 | || inb_p(address + 7) != val) { | 1814 | || inb_p(address + 7) != val) { |
1814 | pr_debug("w83781d: Detection failed at step 1\n"); | 1815 | pr_debug("Detection failed at step %d\n", 1); |
1815 | goto release; | 1816 | goto release; |
1816 | } | 1817 | } |
1817 | #undef REALLY_SLOW_IO | 1818 | #undef REALLY_SLOW_IO |
@@ -1820,14 +1821,14 @@ w83781d_isa_found(unsigned short address) | |||
1820 | MSB (busy flag) should be clear initially, set after the write. */ | 1821 | MSB (busy flag) should be clear initially, set after the write. */ |
1821 | save = inb_p(address + W83781D_ADDR_REG_OFFSET); | 1822 | save = inb_p(address + W83781D_ADDR_REG_OFFSET); |
1822 | if (save & 0x80) { | 1823 | if (save & 0x80) { |
1823 | pr_debug("w83781d: Detection failed at step 2\n"); | 1824 | pr_debug("Detection failed at step %d\n", 2); |
1824 | goto release; | 1825 | goto release; |
1825 | } | 1826 | } |
1826 | val = ~save & 0x7f; | 1827 | val = ~save & 0x7f; |
1827 | outb_p(val, address + W83781D_ADDR_REG_OFFSET); | 1828 | outb_p(val, address + W83781D_ADDR_REG_OFFSET); |
1828 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { | 1829 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { |
1829 | outb_p(save, address + W83781D_ADDR_REG_OFFSET); | 1830 | outb_p(save, address + W83781D_ADDR_REG_OFFSET); |
1830 | pr_debug("w83781d: Detection failed at step 3\n"); | 1831 | pr_debug("Detection failed at step %d\n", 3); |
1831 | goto release; | 1832 | goto release; |
1832 | } | 1833 | } |
1833 | 1834 | ||
@@ -1835,7 +1836,7 @@ w83781d_isa_found(unsigned short address) | |||
1835 | outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); | 1836 | outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); |
1836 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | 1837 | val = inb_p(address + W83781D_DATA_REG_OFFSET); |
1837 | if (val & 0x80) { | 1838 | if (val & 0x80) { |
1838 | pr_debug("w83781d: Detection failed at step 4\n"); | 1839 | pr_debug("Detection failed at step %d\n", 4); |
1839 | goto release; | 1840 | goto release; |
1840 | } | 1841 | } |
1841 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | 1842 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); |
@@ -1844,19 +1845,19 @@ w83781d_isa_found(unsigned short address) | |||
1844 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | 1845 | val = inb_p(address + W83781D_DATA_REG_OFFSET); |
1845 | if ((!(save & 0x80) && (val != 0xa3)) | 1846 | if ((!(save & 0x80) && (val != 0xa3)) |
1846 | || ((save & 0x80) && (val != 0x5c))) { | 1847 | || ((save & 0x80) && (val != 0x5c))) { |
1847 | pr_debug("w83781d: Detection failed at step 5\n"); | 1848 | pr_debug("Detection failed at step %d\n", 5); |
1848 | goto release; | 1849 | goto release; |
1849 | } | 1850 | } |
1850 | outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); | 1851 | outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); |
1851 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | 1852 | val = inb_p(address + W83781D_DATA_REG_OFFSET); |
1852 | if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ | 1853 | if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ |
1853 | pr_debug("w83781d: Detection failed at step 6\n"); | 1854 | pr_debug("Detection failed at step %d\n", 6); |
1854 | goto release; | 1855 | goto release; |
1855 | } | 1856 | } |
1856 | 1857 | ||
1857 | /* The busy flag should be clear again */ | 1858 | /* The busy flag should be clear again */ |
1858 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { | 1859 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { |
1859 | pr_debug("w83781d: Detection failed at step 7\n"); | 1860 | pr_debug("Detection failed at step %d\n", 7); |
1860 | goto release; | 1861 | goto release; |
1861 | } | 1862 | } |
1862 | 1863 | ||
@@ -1871,7 +1872,7 @@ w83781d_isa_found(unsigned short address) | |||
1871 | found = 1; | 1872 | found = 1; |
1872 | 1873 | ||
1873 | if (found) | 1874 | if (found) |
1874 | pr_info("w83781d: Found a %s chip at %#x\n", | 1875 | pr_info("Found a %s chip at %#x\n", |
1875 | val == 0x30 ? "W83782D" : "W83781D", (int)address); | 1876 | val == 0x30 ? "W83782D" : "W83781D", (int)address); |
1876 | 1877 | ||
1877 | release: | 1878 | release: |
@@ -1894,21 +1895,19 @@ w83781d_isa_device_add(unsigned short address) | |||
1894 | pdev = platform_device_alloc("w83781d", address); | 1895 | pdev = platform_device_alloc("w83781d", address); |
1895 | if (!pdev) { | 1896 | if (!pdev) { |
1896 | err = -ENOMEM; | 1897 | err = -ENOMEM; |
1897 | printk(KERN_ERR "w83781d: Device allocation failed\n"); | 1898 | pr_err("Device allocation failed\n"); |
1898 | goto exit; | 1899 | goto exit; |
1899 | } | 1900 | } |
1900 | 1901 | ||
1901 | err = platform_device_add_resources(pdev, &res, 1); | 1902 | err = platform_device_add_resources(pdev, &res, 1); |
1902 | if (err) { | 1903 | if (err) { |
1903 | printk(KERN_ERR "w83781d: Device resource addition failed " | 1904 | pr_err("Device resource addition failed (%d)\n", err); |
1904 | "(%d)\n", err); | ||
1905 | goto exit_device_put; | 1905 | goto exit_device_put; |
1906 | } | 1906 | } |
1907 | 1907 | ||
1908 | err = platform_device_add(pdev); | 1908 | err = platform_device_add(pdev); |
1909 | if (err) { | 1909 | if (err) { |
1910 | printk(KERN_ERR "w83781d: Device addition failed (%d)\n", | 1910 | pr_err("Device addition failed (%d)\n", err); |
1911 | err); | ||
1912 | goto exit_device_put; | 1911 | goto exit_device_put; |
1913 | } | 1912 | } |
1914 | 1913 | ||
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 679718e6b017..63841f8cec07 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -691,7 +691,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, | |||
691 | } | 691 | } |
692 | 692 | ||
693 | static ssize_t | 693 | static ssize_t |
694 | show_regs_chassis(struct device *dev, struct device_attribute *attr, | 694 | show_chassis(struct device *dev, struct device_attribute *attr, |
695 | char *buf) | 695 | char *buf) |
696 | { | 696 | { |
697 | struct w83792d_data *data = w83792d_update_device(dev); | 697 | struct w83792d_data *data = w83792d_update_device(dev); |
@@ -699,6 +699,16 @@ show_regs_chassis(struct device *dev, struct device_attribute *attr, | |||
699 | } | 699 | } |
700 | 700 | ||
701 | static ssize_t | 701 | static ssize_t |
702 | show_regs_chassis(struct device *dev, struct device_attribute *attr, | ||
703 | char *buf) | ||
704 | { | ||
705 | dev_warn(dev, | ||
706 | "Attribute %s is deprecated, use intrusion0_alarm instead\n", | ||
707 | "chassis"); | ||
708 | return show_chassis(dev, attr, buf); | ||
709 | } | ||
710 | |||
711 | static ssize_t | ||
702 | show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) | 712 | show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) |
703 | { | 713 | { |
704 | struct w83792d_data *data = w83792d_update_device(dev); | 714 | struct w83792d_data *data = w83792d_update_device(dev); |
@@ -706,7 +716,7 @@ show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) | |||
706 | } | 716 | } |
707 | 717 | ||
708 | static ssize_t | 718 | static ssize_t |
709 | store_chassis_clear(struct device *dev, struct device_attribute *attr, | 719 | store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr, |
710 | const char *buf, size_t count) | 720 | const char *buf, size_t count) |
711 | { | 721 | { |
712 | struct i2c_client *client = to_i2c_client(dev); | 722 | struct i2c_client *client = to_i2c_client(dev); |
@@ -714,6 +724,10 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, | |||
714 | u32 val; | 724 | u32 val; |
715 | u8 temp1 = 0, temp2 = 0; | 725 | u8 temp1 = 0, temp2 = 0; |
716 | 726 | ||
727 | dev_warn(dev, | ||
728 | "Attribute %s is deprecated, use intrusion0_alarm instead\n", | ||
729 | "chassis_clear"); | ||
730 | |||
717 | val = simple_strtoul(buf, NULL, 10); | 731 | val = simple_strtoul(buf, NULL, 10); |
718 | mutex_lock(&data->update_lock); | 732 | mutex_lock(&data->update_lock); |
719 | data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); | 733 | data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); |
@@ -726,6 +740,27 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, | |||
726 | return count; | 740 | return count; |
727 | } | 741 | } |
728 | 742 | ||
743 | static ssize_t | ||
744 | store_chassis_clear(struct device *dev, struct device_attribute *attr, | ||
745 | const char *buf, size_t count) | ||
746 | { | ||
747 | struct i2c_client *client = to_i2c_client(dev); | ||
748 | struct w83792d_data *data = i2c_get_clientdata(client); | ||
749 | unsigned long val; | ||
750 | u8 reg; | ||
751 | |||
752 | if (strict_strtoul(buf, 10, &val) || val != 0) | ||
753 | return -EINVAL; | ||
754 | |||
755 | mutex_lock(&data->update_lock); | ||
756 | reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR); | ||
757 | w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80); | ||
758 | data->valid = 0; /* Force cache refresh */ | ||
759 | mutex_unlock(&data->update_lock); | ||
760 | |||
761 | return count; | ||
762 | } | ||
763 | |||
729 | /* For Smart Fan I / Thermal Cruise */ | 764 | /* For Smart Fan I / Thermal Cruise */ |
730 | static ssize_t | 765 | static ssize_t |
731 | show_thermal_cruise(struct device *dev, struct device_attribute *attr, | 766 | show_thermal_cruise(struct device *dev, struct device_attribute *attr, |
@@ -1012,7 +1047,9 @@ static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); | |||
1012 | static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); | 1047 | static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); |
1013 | static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); | 1048 | static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); |
1014 | static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, | 1049 | static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, |
1015 | show_chassis_clear, store_chassis_clear); | 1050 | show_chassis_clear, store_chassis_clear_legacy); |
1051 | static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, | ||
1052 | show_chassis, store_chassis_clear); | ||
1016 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); | 1053 | static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); |
1017 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); | 1054 | static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); |
1018 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); | 1055 | static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); |
@@ -1214,6 +1251,7 @@ static struct attribute *w83792d_attributes[] = { | |||
1214 | &dev_attr_alarms.attr, | 1251 | &dev_attr_alarms.attr, |
1215 | &dev_attr_chassis.attr, | 1252 | &dev_attr_chassis.attr, |
1216 | &dev_attr_chassis_clear.attr, | 1253 | &dev_attr_chassis_clear.attr, |
1254 | &dev_attr_intrusion0_alarm.attr, | ||
1217 | &sensor_dev_attr_tolerance1.dev_attr.attr, | 1255 | &sensor_dev_attr_tolerance1.dev_attr.attr, |
1218 | &sensor_dev_attr_thermal_cruise1.dev_attr.attr, | 1256 | &sensor_dev_attr_thermal_cruise1.dev_attr.attr, |
1219 | &sensor_dev_attr_tolerance2.dev_attr.attr, | 1257 | &sensor_dev_attr_tolerance2.dev_attr.attr, |
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 8e540ada47d2..e3bdedfb5347 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */ | 51 | #define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */ |
52 | 52 | ||
53 | /* Addresses to scan */ | 53 | /* Addresses to scan */ |
54 | static DEFINE_MUTEX(watchdog_mutex); | ||
55 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | 54 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, |
56 | I2C_CLIENT_END }; | 55 | I2C_CLIENT_END }; |
57 | 56 | ||
@@ -421,14 +420,17 @@ store_beep_enable(struct device *dev, struct device_attribute *attr, | |||
421 | 420 | ||
422 | /* Write any value to clear chassis alarm */ | 421 | /* Write any value to clear chassis alarm */ |
423 | static ssize_t | 422 | static ssize_t |
424 | store_chassis_clear(struct device *dev, | 423 | store_chassis_clear_legacy(struct device *dev, |
425 | struct device_attribute *attr, const char *buf, | 424 | struct device_attribute *attr, const char *buf, |
426 | size_t count) | 425 | size_t count) |
427 | { | 426 | { |
428 | struct i2c_client *client = to_i2c_client(dev); | 427 | struct i2c_client *client = to_i2c_client(dev); |
429 | struct w83793_data *data = i2c_get_clientdata(client); | 428 | struct w83793_data *data = i2c_get_clientdata(client); |
430 | u8 val; | 429 | u8 val; |
431 | 430 | ||
431 | dev_warn(dev, "Attribute chassis is deprecated, " | ||
432 | "use intrusion0_alarm instead\n"); | ||
433 | |||
432 | mutex_lock(&data->update_lock); | 434 | mutex_lock(&data->update_lock); |
433 | val = w83793_read_value(client, W83793_REG_CLR_CHASSIS); | 435 | val = w83793_read_value(client, W83793_REG_CLR_CHASSIS); |
434 | val |= 0x80; | 436 | val |= 0x80; |
@@ -437,6 +439,28 @@ store_chassis_clear(struct device *dev, | |||
437 | return count; | 439 | return count; |
438 | } | 440 | } |
439 | 441 | ||
442 | /* Write 0 to clear chassis alarm */ | ||
443 | static ssize_t | ||
444 | store_chassis_clear(struct device *dev, | ||
445 | struct device_attribute *attr, const char *buf, | ||
446 | size_t count) | ||
447 | { | ||
448 | struct i2c_client *client = to_i2c_client(dev); | ||
449 | struct w83793_data *data = i2c_get_clientdata(client); | ||
450 | unsigned long val; | ||
451 | u8 reg; | ||
452 | |||
453 | if (strict_strtoul(buf, 10, &val) || val != 0) | ||
454 | return -EINVAL; | ||
455 | |||
456 | mutex_lock(&data->update_lock); | ||
457 | reg = w83793_read_value(client, W83793_REG_CLR_CHASSIS); | ||
458 | w83793_write_value(client, W83793_REG_CLR_CHASSIS, reg | 0x80); | ||
459 | data->valid = 0; /* Force cache refresh */ | ||
460 | mutex_unlock(&data->update_lock); | ||
461 | return count; | ||
462 | } | ||
463 | |||
440 | #define FAN_INPUT 0 | 464 | #define FAN_INPUT 0 |
441 | #define FAN_MIN 1 | 465 | #define FAN_MIN 1 |
442 | static ssize_t | 466 | static ssize_t |
@@ -1102,6 +1126,8 @@ static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm); | |||
1102 | 1126 | ||
1103 | static struct sensor_device_attribute_2 sda_single_files[] = { | 1127 | static struct sensor_device_attribute_2 sda_single_files[] = { |
1104 | SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, | 1128 | SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, |
1129 | store_chassis_clear_legacy, ALARM_STATUS, 30), | ||
1130 | SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, | ||
1105 | store_chassis_clear, ALARM_STATUS, 30), | 1131 | store_chassis_clear, ALARM_STATUS, 30), |
1106 | SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable, | 1132 | SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable, |
1107 | store_beep_enable, NOT_USED, NOT_USED), | 1133 | store_beep_enable, NOT_USED, NOT_USED), |
@@ -1323,7 +1349,7 @@ static ssize_t watchdog_write(struct file *filp, const char __user *buf, | |||
1323 | static long watchdog_ioctl(struct file *filp, unsigned int cmd, | 1349 | static long watchdog_ioctl(struct file *filp, unsigned int cmd, |
1324 | unsigned long arg) | 1350 | unsigned long arg) |
1325 | { | 1351 | { |
1326 | static struct watchdog_info ident = { | 1352 | struct watchdog_info ident = { |
1327 | .options = WDIOF_KEEPALIVEPING | | 1353 | .options = WDIOF_KEEPALIVEPING | |
1328 | WDIOF_SETTIMEOUT | | 1354 | WDIOF_SETTIMEOUT | |
1329 | WDIOF_CARDRESET, | 1355 | WDIOF_CARDRESET, |
@@ -1333,7 +1359,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, | |||
1333 | int val, ret = 0; | 1359 | int val, ret = 0; |
1334 | struct w83793_data *data = filp->private_data; | 1360 | struct w83793_data *data = filp->private_data; |
1335 | 1361 | ||
1336 | mutex_lock(&watchdog_mutex); | ||
1337 | switch (cmd) { | 1362 | switch (cmd) { |
1338 | case WDIOC_GETSUPPORT: | 1363 | case WDIOC_GETSUPPORT: |
1339 | if (!nowayout) | 1364 | if (!nowayout) |
@@ -1387,7 +1412,6 @@ static long watchdog_ioctl(struct file *filp, unsigned int cmd, | |||
1387 | default: | 1412 | default: |
1388 | ret = -ENOTTY; | 1413 | ret = -ENOTTY; |
1389 | } | 1414 | } |
1390 | mutex_unlock(&watchdog_mutex); | ||
1391 | return ret; | 1415 | return ret; |
1392 | } | 1416 | } |
1393 | 1417 | ||
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index cdbc7448491e..845232d7f611 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c | |||
@@ -458,6 +458,7 @@ static void w83795_update_limits(struct i2c_client *client) | |||
458 | { | 458 | { |
459 | struct w83795_data *data = i2c_get_clientdata(client); | 459 | struct w83795_data *data = i2c_get_clientdata(client); |
460 | int i, limit; | 460 | int i, limit; |
461 | u8 lsb; | ||
461 | 462 | ||
462 | /* Read the voltage limits */ | 463 | /* Read the voltage limits */ |
463 | for (i = 0; i < ARRAY_SIZE(data->in); i++) { | 464 | for (i = 0; i < ARRAY_SIZE(data->in); i++) { |
@@ -479,9 +480,8 @@ static void w83795_update_limits(struct i2c_client *client) | |||
479 | } | 480 | } |
480 | 481 | ||
481 | /* Read the fan limits */ | 482 | /* Read the fan limits */ |
483 | lsb = 0; /* Silent false gcc warning */ | ||
482 | for (i = 0; i < ARRAY_SIZE(data->fan); i++) { | 484 | for (i = 0; i < ARRAY_SIZE(data->fan); i++) { |
483 | u8 lsb; | ||
484 | |||
485 | /* Each register contains LSB for 2 fans, but we want to | 485 | /* Each register contains LSB for 2 fans, but we want to |
486 | * read it only once to save time */ | 486 | * read it only once to save time */ |
487 | if ((i & 1) == 0 && (data->has_fan & (3 << i))) | 487 | if ((i & 1) == 0 && (data->has_fan & (3 << i))) |
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index f7148fdd46e0..594ed5059c4a 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c | |||
@@ -434,7 +434,7 @@ static int read_i2c(struct nmk_i2c_dev *dev) | |||
434 | } | 434 | } |
435 | 435 | ||
436 | if (timeout == 0) { | 436 | if (timeout == 0) { |
437 | /* controler has timedout, re-init the h/w */ | 437 | /* controller has timedout, re-init the h/w */ |
438 | dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n"); | 438 | dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n"); |
439 | (void) init_hw(dev); | 439 | (void) init_hw(dev); |
440 | status = -ETIMEDOUT; | 440 | status = -ETIMEDOUT; |
@@ -498,7 +498,7 @@ static int write_i2c(struct nmk_i2c_dev *dev) | |||
498 | } | 498 | } |
499 | 499 | ||
500 | if (timeout == 0) { | 500 | if (timeout == 0) { |
501 | /* controler has timedout, re-init the h/w */ | 501 | /* controller has timedout, re-init the h/w */ |
502 | dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n"); | 502 | dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n"); |
503 | (void) init_hw(dev); | 503 | (void) init_hw(dev); |
504 | status = -ETIMEDOUT; | 504 | status = -ETIMEDOUT; |
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h index 4bb997aa39d0..83d2e19d31ae 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_wr.h +++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h | |||
@@ -689,7 +689,7 @@ struct t3_swrq { | |||
689 | * A T3 WQ implements both the SQ and RQ. | 689 | * A T3 WQ implements both the SQ and RQ. |
690 | */ | 690 | */ |
691 | struct t3_wq { | 691 | struct t3_wq { |
692 | union t3_wr *queue; /* DMA accessable memory */ | 692 | union t3_wr *queue; /* DMA accessible memory */ |
693 | dma_addr_t dma_addr; /* DMA address for HW */ | 693 | dma_addr_t dma_addr; /* DMA address for HW */ |
694 | DEFINE_DMA_UNMAP_ADDR(mapping); /* unmap kruft */ | 694 | DEFINE_DMA_UNMAP_ADDR(mapping); /* unmap kruft */ |
695 | u32 error; /* 1 once we go to ERROR */ | 695 | u32 error; /* 1 once we go to ERROR */ |
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index cc600c2dd0b3..2fe19ec9ba60 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h | |||
@@ -46,7 +46,6 @@ | |||
46 | #include <linux/timer.h> | 46 | #include <linux/timer.h> |
47 | #include <linux/io.h> | 47 | #include <linux/io.h> |
48 | #include <linux/kfifo.h> | 48 | #include <linux/kfifo.h> |
49 | #include <linux/mutex.h> | ||
50 | 49 | ||
51 | #include <asm/byteorder.h> | 50 | #include <asm/byteorder.h> |
52 | 51 | ||
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index dbbb0e85afe4..abd409d592ef 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c | |||
@@ -332,7 +332,7 @@ MODULE_PARM_DESC(txselect, \ | |||
332 | #define krp_serdesctrl KREG_IBPORT_IDX(IBSerdesCtrl) | 332 | #define krp_serdesctrl KREG_IBPORT_IDX(IBSerdesCtrl) |
333 | 333 | ||
334 | /* | 334 | /* |
335 | * Per-context kernel registers. Acess only with qib_read_kreg_ctxt() | 335 | * Per-context kernel registers. Access only with qib_read_kreg_ctxt() |
336 | * or qib_write_kreg_ctxt() | 336 | * or qib_write_kreg_ctxt() |
337 | */ | 337 | */ |
338 | #define krc_rcvhdraddr KREG_IDX(RcvHdrAddr0) | 338 | #define krc_rcvhdraddr KREG_IDX(RcvHdrAddr0) |
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index 5b596165b571..56eb471b5576 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
@@ -255,6 +255,16 @@ config JOYSTICK_AMIGA | |||
255 | To compile this driver as a module, choose M here: the | 255 | To compile this driver as a module, choose M here: the |
256 | module will be called amijoy. | 256 | module will be called amijoy. |
257 | 257 | ||
258 | config JOYSTICK_AS5011 | ||
259 | tristate "Austria Microsystem AS5011 joystick" | ||
260 | depends on I2C | ||
261 | help | ||
262 | Say Y here if you have an AS5011 digital joystick connected to your | ||
263 | system. | ||
264 | |||
265 | To compile this driver as a module, choose M here: the | ||
266 | module will be called as5011. | ||
267 | |||
258 | config JOYSTICK_JOYDUMP | 268 | config JOYSTICK_JOYDUMP |
259 | tristate "Gameport data dumper" | 269 | tristate "Gameport data dumper" |
260 | select GAMEPORT | 270 | select GAMEPORT |
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile index f3a8cbe2abb6..92dc0de9dfed 100644 --- a/drivers/input/joystick/Makefile +++ b/drivers/input/joystick/Makefile | |||
@@ -7,6 +7,7 @@ | |||
7 | obj-$(CONFIG_JOYSTICK_A3D) += a3d.o | 7 | obj-$(CONFIG_JOYSTICK_A3D) += a3d.o |
8 | obj-$(CONFIG_JOYSTICK_ADI) += adi.o | 8 | obj-$(CONFIG_JOYSTICK_ADI) += adi.o |
9 | obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o | 9 | obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o |
10 | obj-$(CONFIG_JOYSTICK_AS5011) += as5011.o | ||
10 | obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o | 11 | obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o |
11 | obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o | 12 | obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o |
12 | obj-$(CONFIG_JOYSTICK_DB9) += db9.o | 13 | obj-$(CONFIG_JOYSTICK_DB9) += db9.o |
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c new file mode 100644 index 000000000000..f6732b57ca07 --- /dev/null +++ b/drivers/input/joystick/as5011.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010, 2011 Fabien Marteau <fabien.marteau@armadeus.com> | ||
3 | * Sponsored by ARMadeus Systems | ||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | * Driver for Austria Microsystems joysticks AS5011 | ||
20 | * | ||
21 | * TODO: | ||
22 | * - Power on the chip when open() and power down when close() | ||
23 | * - Manage power mode | ||
24 | */ | ||
25 | |||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/input.h> | ||
29 | #include <linux/gpio.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/input/as5011.h> | ||
32 | #include <linux/slab.h> | ||
33 | |||
34 | #define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick" | ||
35 | #define MODULE_DEVICE_ALIAS "as5011" | ||
36 | |||
37 | MODULE_AUTHOR("Fabien Marteau <fabien.marteau@armadeus.com>"); | ||
38 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | /* registers */ | ||
42 | #define AS5011_CTRL1 0x76 | ||
43 | #define AS5011_CTRL2 0x75 | ||
44 | #define AS5011_XP 0x43 | ||
45 | #define AS5011_XN 0x44 | ||
46 | #define AS5011_YP 0x53 | ||
47 | #define AS5011_YN 0x54 | ||
48 | #define AS5011_X_REG 0x41 | ||
49 | #define AS5011_Y_REG 0x42 | ||
50 | #define AS5011_X_RES_INT 0x51 | ||
51 | #define AS5011_Y_RES_INT 0x52 | ||
52 | |||
53 | /* CTRL1 bits */ | ||
54 | #define AS5011_CTRL1_LP_PULSED 0x80 | ||
55 | #define AS5011_CTRL1_LP_ACTIVE 0x40 | ||
56 | #define AS5011_CTRL1_LP_CONTINUE 0x20 | ||
57 | #define AS5011_CTRL1_INT_WUP_EN 0x10 | ||
58 | #define AS5011_CTRL1_INT_ACT_EN 0x08 | ||
59 | #define AS5011_CTRL1_EXT_CLK_EN 0x04 | ||
60 | #define AS5011_CTRL1_SOFT_RST 0x02 | ||
61 | #define AS5011_CTRL1_DATA_VALID 0x01 | ||
62 | |||
63 | /* CTRL2 bits */ | ||
64 | #define AS5011_CTRL2_EXT_SAMPLE_EN 0x08 | ||
65 | #define AS5011_CTRL2_RC_BIAS_ON 0x04 | ||
66 | #define AS5011_CTRL2_INV_SPINNING 0x02 | ||
67 | |||
68 | #define AS5011_MAX_AXIS 80 | ||
69 | #define AS5011_MIN_AXIS (-80) | ||
70 | #define AS5011_FUZZ 8 | ||
71 | #define AS5011_FLAT 40 | ||
72 | |||
73 | struct as5011_device { | ||
74 | struct input_dev *input_dev; | ||
75 | struct i2c_client *i2c_client; | ||
76 | unsigned int button_gpio; | ||
77 | unsigned int button_irq; | ||
78 | unsigned int axis_irq; | ||
79 | }; | ||
80 | |||
81 | static int as5011_i2c_write(struct i2c_client *client, | ||
82 | uint8_t aregaddr, | ||
83 | uint8_t avalue) | ||
84 | { | ||
85 | uint8_t data[2] = { aregaddr, avalue }; | ||
86 | struct i2c_msg msg = { | ||
87 | client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data | ||
88 | }; | ||
89 | int error; | ||
90 | |||
91 | error = i2c_transfer(client->adapter, &msg, 1); | ||
92 | return error < 0 ? error : 0; | ||
93 | } | ||
94 | |||
95 | static int as5011_i2c_read(struct i2c_client *client, | ||
96 | uint8_t aregaddr, signed char *value) | ||
97 | { | ||
98 | uint8_t data[2] = { aregaddr }; | ||
99 | struct i2c_msg msg_set[2] = { | ||
100 | { client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data }, | ||
101 | { client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data } | ||
102 | }; | ||
103 | int error; | ||
104 | |||
105 | error = i2c_transfer(client->adapter, msg_set, 2); | ||
106 | if (error < 0) | ||
107 | return error; | ||
108 | |||
109 | *value = data[0] & 0x80 ? -1 * (1 + ~data[0]) : data[0]; | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static irqreturn_t as5011_button_interrupt(int irq, void *dev_id) | ||
114 | { | ||
115 | struct as5011_device *as5011 = dev_id; | ||
116 | int val = gpio_get_value_cansleep(as5011->button_gpio); | ||
117 | |||
118 | input_report_key(as5011->input_dev, BTN_JOYSTICK, !val); | ||
119 | input_sync(as5011->input_dev); | ||
120 | |||
121 | return IRQ_HANDLED; | ||
122 | } | ||
123 | |||
124 | static irqreturn_t as5011_axis_interrupt(int irq, void *dev_id) | ||
125 | { | ||
126 | struct as5011_device *as5011 = dev_id; | ||
127 | int error; | ||
128 | signed char x, y; | ||
129 | |||
130 | error = as5011_i2c_read(as5011->i2c_client, AS5011_X_RES_INT, &x); | ||
131 | if (error < 0) | ||
132 | goto out; | ||
133 | |||
134 | error = as5011_i2c_read(as5011->i2c_client, AS5011_Y_RES_INT, &y); | ||
135 | if (error < 0) | ||
136 | goto out; | ||
137 | |||
138 | input_report_abs(as5011->input_dev, ABS_X, x); | ||
139 | input_report_abs(as5011->input_dev, ABS_Y, y); | ||
140 | input_sync(as5011->input_dev); | ||
141 | |||
142 | out: | ||
143 | return IRQ_HANDLED; | ||
144 | } | ||
145 | |||
146 | static int __devinit as5011_configure_chip(struct as5011_device *as5011, | ||
147 | const struct as5011_platform_data *plat_dat) | ||
148 | { | ||
149 | struct i2c_client *client = as5011->i2c_client; | ||
150 | int error; | ||
151 | signed char value; | ||
152 | |||
153 | /* chip soft reset */ | ||
154 | error = as5011_i2c_write(client, AS5011_CTRL1, | ||
155 | AS5011_CTRL1_SOFT_RST); | ||
156 | if (error < 0) { | ||
157 | dev_err(&client->dev, "Soft reset failed\n"); | ||
158 | return error; | ||
159 | } | ||
160 | |||
161 | mdelay(10); | ||
162 | |||
163 | error = as5011_i2c_write(client, AS5011_CTRL1, | ||
164 | AS5011_CTRL1_LP_PULSED | | ||
165 | AS5011_CTRL1_LP_ACTIVE | | ||
166 | AS5011_CTRL1_INT_ACT_EN); | ||
167 | if (error < 0) { | ||
168 | dev_err(&client->dev, "Power config failed\n"); | ||
169 | return error; | ||
170 | } | ||
171 | |||
172 | error = as5011_i2c_write(client, AS5011_CTRL2, | ||
173 | AS5011_CTRL2_INV_SPINNING); | ||
174 | if (error < 0) { | ||
175 | dev_err(&client->dev, "Can't invert spinning\n"); | ||
176 | return error; | ||
177 | } | ||
178 | |||
179 | /* write threshold */ | ||
180 | error = as5011_i2c_write(client, AS5011_XP, plat_dat->xp); | ||
181 | if (error < 0) { | ||
182 | dev_err(&client->dev, "Can't write threshold\n"); | ||
183 | return error; | ||
184 | } | ||
185 | |||
186 | error = as5011_i2c_write(client, AS5011_XN, plat_dat->xn); | ||
187 | if (error < 0) { | ||
188 | dev_err(&client->dev, "Can't write threshold\n"); | ||
189 | return error; | ||
190 | } | ||
191 | |||
192 | error = as5011_i2c_write(client, AS5011_YP, plat_dat->yp); | ||
193 | if (error < 0) { | ||
194 | dev_err(&client->dev, "Can't write threshold\n"); | ||
195 | return error; | ||
196 | } | ||
197 | |||
198 | error = as5011_i2c_write(client, AS5011_YN, plat_dat->yn); | ||
199 | if (error < 0) { | ||
200 | dev_err(&client->dev, "Can't write threshold\n"); | ||
201 | return error; | ||
202 | } | ||
203 | |||
204 | /* to free irq gpio in chip */ | ||
205 | error = as5011_i2c_read(client, AS5011_X_RES_INT, &value); | ||
206 | if (error < 0) { | ||
207 | dev_err(&client->dev, "Can't read i2c X resolution value\n"); | ||
208 | return error; | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int __devinit as5011_probe(struct i2c_client *client, | ||
215 | const struct i2c_device_id *id) | ||
216 | { | ||
217 | const struct as5011_platform_data *plat_data; | ||
218 | struct as5011_device *as5011; | ||
219 | struct input_dev *input_dev; | ||
220 | int irq; | ||
221 | int error; | ||
222 | |||
223 | plat_data = client->dev.platform_data; | ||
224 | if (!plat_data) | ||
225 | return -EINVAL; | ||
226 | |||
227 | if (!plat_data->axis_irq) { | ||
228 | dev_err(&client->dev, "No axis IRQ?\n"); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | if (!i2c_check_functionality(client->adapter, | ||
233 | I2C_FUNC_PROTOCOL_MANGLING)) { | ||
234 | dev_err(&client->dev, | ||
235 | "need i2c bus that supports protocol mangling\n"); | ||
236 | return -ENODEV; | ||
237 | } | ||
238 | |||
239 | as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL); | ||
240 | input_dev = input_allocate_device(); | ||
241 | if (!as5011 || !input_dev) { | ||
242 | dev_err(&client->dev, | ||
243 | "Can't allocate memory for device structure\n"); | ||
244 | error = -ENOMEM; | ||
245 | goto err_free_mem; | ||
246 | } | ||
247 | |||
248 | as5011->i2c_client = client; | ||
249 | as5011->input_dev = input_dev; | ||
250 | as5011->button_gpio = plat_data->button_gpio; | ||
251 | as5011->axis_irq = plat_data->axis_irq; | ||
252 | |||
253 | input_dev->name = "Austria Microsystem as5011 joystick"; | ||
254 | input_dev->id.bustype = BUS_I2C; | ||
255 | input_dev->dev.parent = &client->dev; | ||
256 | |||
257 | __set_bit(EV_KEY, input_dev->evbit); | ||
258 | __set_bit(EV_ABS, input_dev->evbit); | ||
259 | __set_bit(BTN_JOYSTICK, input_dev->keybit); | ||
260 | |||
261 | input_set_abs_params(input_dev, ABS_X, | ||
262 | AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT); | ||
263 | input_set_abs_params(as5011->input_dev, ABS_Y, | ||
264 | AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT); | ||
265 | |||
266 | error = gpio_request(as5011->button_gpio, "AS5011 button"); | ||
267 | if (error < 0) { | ||
268 | dev_err(&client->dev, "Failed to request button gpio\n"); | ||
269 | goto err_free_mem; | ||
270 | } | ||
271 | |||
272 | irq = gpio_to_irq(as5011->button_gpio); | ||
273 | if (irq < 0) { | ||
274 | dev_err(&client->dev, | ||
275 | "Failed to get irq number for button gpio\n"); | ||
276 | goto err_free_button_gpio; | ||
277 | } | ||
278 | |||
279 | as5011->button_irq = irq; | ||
280 | |||
281 | error = request_threaded_irq(as5011->button_irq, | ||
282 | NULL, as5011_button_interrupt, | ||
283 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
284 | "as5011_button", as5011); | ||
285 | if (error < 0) { | ||
286 | dev_err(&client->dev, | ||
287 | "Can't allocate button irq %d\n", as5011->button_irq); | ||
288 | goto err_free_button_gpio; | ||
289 | } | ||
290 | |||
291 | error = as5011_configure_chip(as5011, plat_data); | ||
292 | if (error) | ||
293 | goto err_free_button_irq; | ||
294 | |||
295 | error = request_threaded_irq(as5011->axis_irq, NULL, | ||
296 | as5011_axis_interrupt, | ||
297 | plat_data->axis_irqflags, | ||
298 | "as5011_joystick", as5011); | ||
299 | if (error) { | ||
300 | dev_err(&client->dev, | ||
301 | "Can't allocate axis irq %d\n", plat_data->axis_irq); | ||
302 | goto err_free_button_irq; | ||
303 | } | ||
304 | |||
305 | error = input_register_device(as5011->input_dev); | ||
306 | if (error) { | ||
307 | dev_err(&client->dev, "Failed to register input device\n"); | ||
308 | goto err_free_axis_irq; | ||
309 | } | ||
310 | |||
311 | i2c_set_clientdata(client, as5011); | ||
312 | |||
313 | return 0; | ||
314 | |||
315 | err_free_axis_irq: | ||
316 | free_irq(as5011->axis_irq, as5011); | ||
317 | err_free_button_irq: | ||
318 | free_irq(as5011->button_irq, as5011); | ||
319 | err_free_button_gpio: | ||
320 | gpio_free(as5011->button_gpio); | ||
321 | err_free_mem: | ||
322 | input_free_device(input_dev); | ||
323 | kfree(as5011); | ||
324 | |||
325 | return error; | ||
326 | } | ||
327 | |||
328 | static int __devexit as5011_remove(struct i2c_client *client) | ||
329 | { | ||
330 | struct as5011_device *as5011 = i2c_get_clientdata(client); | ||
331 | |||
332 | free_irq(as5011->axis_irq, as5011); | ||
333 | free_irq(as5011->button_irq, as5011); | ||
334 | gpio_free(as5011->button_gpio); | ||
335 | |||
336 | input_unregister_device(as5011->input_dev); | ||
337 | kfree(as5011); | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static const struct i2c_device_id as5011_id[] = { | ||
343 | { MODULE_DEVICE_ALIAS, 0 }, | ||
344 | { } | ||
345 | }; | ||
346 | MODULE_DEVICE_TABLE(i2c, as5011_id); | ||
347 | |||
348 | static struct i2c_driver as5011_driver = { | ||
349 | .driver = { | ||
350 | .name = "as5011", | ||
351 | }, | ||
352 | .probe = as5011_probe, | ||
353 | .remove = __devexit_p(as5011_remove), | ||
354 | .id_table = as5011_id, | ||
355 | }; | ||
356 | |||
357 | static int __init as5011_init(void) | ||
358 | { | ||
359 | return i2c_add_driver(&as5011_driver); | ||
360 | } | ||
361 | module_init(as5011_init); | ||
362 | |||
363 | static void __exit as5011_exit(void) | ||
364 | { | ||
365 | i2c_del_driver(&as5011_driver); | ||
366 | } | ||
367 | module_exit(as5011_exit); | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index f829998fabe6..7b3c0b8fa432 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -12,18 +12,6 @@ menuconfig INPUT_KEYBOARD | |||
12 | 12 | ||
13 | if INPUT_KEYBOARD | 13 | if INPUT_KEYBOARD |
14 | 14 | ||
15 | config KEYBOARD_AAED2000 | ||
16 | tristate "AAED-2000 keyboard" | ||
17 | depends on MACH_AAED2000 | ||
18 | select INPUT_POLLDEV | ||
19 | default y | ||
20 | help | ||
21 | Say Y here to enable the keyboard on the Agilent AAED-2000 | ||
22 | development board. | ||
23 | |||
24 | To compile this driver as a module, choose M here: the | ||
25 | module will be called aaed2000_kbd. | ||
26 | |||
27 | config KEYBOARD_ADP5520 | 15 | config KEYBOARD_ADP5520 |
28 | tristate "Keypad Support for ADP5520 PMIC" | 16 | tristate "Keypad Support for ADP5520 PMIC" |
29 | depends on PMIC_ADP5520 | 17 | depends on PMIC_ADP5520 |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 8933e9ca938d..4e5571b72cda 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | ||
8 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o | 7 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o |
9 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | 8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o |
10 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 9 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
diff --git a/drivers/input/keyboard/aaed2000_kbd.c b/drivers/input/keyboard/aaed2000_kbd.c deleted file mode 100644 index 18222a689a03..000000000000 --- a/drivers/input/keyboard/aaed2000_kbd.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * Keyboard driver for the AAED-2000 dev board | ||
3 | * | ||
4 | * Copyright (c) 2006 Nicolas Bellido Y Ortega | ||
5 | * | ||
6 | * Based on corgikbd.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/input-polldev.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | #include <mach/hardware.h> | ||
24 | #include <mach/aaed2000.h> | ||
25 | |||
26 | #define KB_ROWS 12 | ||
27 | #define KB_COLS 8 | ||
28 | #define KB_ROWMASK(r) (1 << (r)) | ||
29 | #define SCANCODE(r,c) (((c) * KB_ROWS) + (r)) | ||
30 | #define NR_SCANCODES (KB_COLS * KB_ROWS) | ||
31 | |||
32 | #define SCAN_INTERVAL (50) /* ms */ | ||
33 | #define KB_ACTIVATE_DELAY (20) /* us */ | ||
34 | |||
35 | static unsigned char aaedkbd_keycode[NR_SCANCODES] = { | ||
36 | KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, 0, KEY_SPACE, KEY_KP6, 0, KEY_KPDOT, 0, 0, | ||
37 | KEY_K, KEY_M, KEY_O, KEY_DOT, KEY_SLASH, 0, KEY_F, 0, 0, 0, KEY_LEFTSHIFT, 0, | ||
38 | KEY_I, KEY_P, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, 0, 0, 0, 0, KEY_RIGHTSHIFT, 0, | ||
39 | KEY_8, KEY_L, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_ENTER, 0, 0, 0, 0, 0, 0, 0, | ||
40 | KEY_J, KEY_H, KEY_B, KEY_KP8, KEY_KP4, 0, KEY_C, KEY_D, KEY_S, KEY_A, 0, KEY_CAPSLOCK, | ||
41 | KEY_Y, KEY_U, KEY_N, KEY_T, 0, 0, KEY_R, KEY_E, KEY_W, KEY_Q, 0, KEY_TAB, | ||
42 | KEY_7, KEY_6, KEY_G, 0, KEY_5, 0, KEY_4, KEY_3, KEY_2, KEY_1, 0, KEY_GRAVE, | ||
43 | 0, 0, KEY_COMMA, 0, KEY_KP2, 0, KEY_V, KEY_LEFTALT, KEY_X, KEY_Z, 0, KEY_LEFTCTRL | ||
44 | }; | ||
45 | |||
46 | struct aaedkbd { | ||
47 | unsigned char keycode[ARRAY_SIZE(aaedkbd_keycode)]; | ||
48 | struct input_polled_dev *poll_dev; | ||
49 | int kbdscan_state[KB_COLS]; | ||
50 | int kbdscan_count[KB_COLS]; | ||
51 | }; | ||
52 | |||
53 | #define KBDSCAN_STABLE_COUNT 2 | ||
54 | |||
55 | static void aaedkbd_report_col(struct aaedkbd *aaedkbd, | ||
56 | unsigned int col, unsigned int rowd) | ||
57 | { | ||
58 | unsigned int scancode, pressed; | ||
59 | unsigned int row; | ||
60 | |||
61 | for (row = 0; row < KB_ROWS; row++) { | ||
62 | scancode = SCANCODE(row, col); | ||
63 | pressed = rowd & KB_ROWMASK(row); | ||
64 | |||
65 | input_report_key(aaedkbd->poll_dev->input, | ||
66 | aaedkbd->keycode[scancode], pressed); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
71 | static void aaedkbd_poll(struct input_polled_dev *dev) | ||
72 | { | ||
73 | struct aaedkbd *aaedkbd = dev->private; | ||
74 | unsigned int col, rowd; | ||
75 | |||
76 | col = 0; | ||
77 | do { | ||
78 | AAEC_GPIO_KSCAN = col + 8; | ||
79 | udelay(KB_ACTIVATE_DELAY); | ||
80 | rowd = AAED_EXT_GPIO & AAED_EGPIO_KBD_SCAN; | ||
81 | |||
82 | if (rowd != aaedkbd->kbdscan_state[col]) { | ||
83 | aaedkbd->kbdscan_count[col] = 0; | ||
84 | aaedkbd->kbdscan_state[col] = rowd; | ||
85 | } else if (++aaedkbd->kbdscan_count[col] >= KBDSCAN_STABLE_COUNT) { | ||
86 | aaedkbd_report_col(aaedkbd, col, rowd); | ||
87 | col++; | ||
88 | } | ||
89 | } while (col < KB_COLS); | ||
90 | |||
91 | AAEC_GPIO_KSCAN = 0x07; | ||
92 | input_sync(dev->input); | ||
93 | } | ||
94 | |||
95 | static int __devinit aaedkbd_probe(struct platform_device *pdev) | ||
96 | { | ||
97 | struct aaedkbd *aaedkbd; | ||
98 | struct input_polled_dev *poll_dev; | ||
99 | struct input_dev *input_dev; | ||
100 | int i; | ||
101 | int error; | ||
102 | |||
103 | aaedkbd = kzalloc(sizeof(struct aaedkbd), GFP_KERNEL); | ||
104 | poll_dev = input_allocate_polled_device(); | ||
105 | if (!aaedkbd || !poll_dev) { | ||
106 | error = -ENOMEM; | ||
107 | goto fail; | ||
108 | } | ||
109 | |||
110 | platform_set_drvdata(pdev, aaedkbd); | ||
111 | |||
112 | aaedkbd->poll_dev = poll_dev; | ||
113 | memcpy(aaedkbd->keycode, aaedkbd_keycode, sizeof(aaedkbd->keycode)); | ||
114 | |||
115 | poll_dev->private = aaedkbd; | ||
116 | poll_dev->poll = aaedkbd_poll; | ||
117 | poll_dev->poll_interval = SCAN_INTERVAL; | ||
118 | |||
119 | input_dev = poll_dev->input; | ||
120 | input_dev->name = "AAED-2000 Keyboard"; | ||
121 | input_dev->phys = "aaedkbd/input0"; | ||
122 | input_dev->id.bustype = BUS_HOST; | ||
123 | input_dev->id.vendor = 0x0001; | ||
124 | input_dev->id.product = 0x0001; | ||
125 | input_dev->id.version = 0x0100; | ||
126 | input_dev->dev.parent = &pdev->dev; | ||
127 | |||
128 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
129 | input_dev->keycode = aaedkbd->keycode; | ||
130 | input_dev->keycodesize = sizeof(unsigned char); | ||
131 | input_dev->keycodemax = ARRAY_SIZE(aaedkbd_keycode); | ||
132 | |||
133 | for (i = 0; i < ARRAY_SIZE(aaedkbd_keycode); i++) | ||
134 | set_bit(aaedkbd->keycode[i], input_dev->keybit); | ||
135 | clear_bit(0, input_dev->keybit); | ||
136 | |||
137 | error = input_register_polled_device(aaedkbd->poll_dev); | ||
138 | if (error) | ||
139 | goto fail; | ||
140 | |||
141 | return 0; | ||
142 | |||
143 | fail: kfree(aaedkbd); | ||
144 | input_free_polled_device(poll_dev); | ||
145 | return error; | ||
146 | } | ||
147 | |||
148 | static int __devexit aaedkbd_remove(struct platform_device *pdev) | ||
149 | { | ||
150 | struct aaedkbd *aaedkbd = platform_get_drvdata(pdev); | ||
151 | |||
152 | input_unregister_polled_device(aaedkbd->poll_dev); | ||
153 | input_free_polled_device(aaedkbd->poll_dev); | ||
154 | kfree(aaedkbd); | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* work with hotplug and coldplug */ | ||
160 | MODULE_ALIAS("platform:aaed2000-keyboard"); | ||
161 | |||
162 | static struct platform_driver aaedkbd_driver = { | ||
163 | .probe = aaedkbd_probe, | ||
164 | .remove = __devexit_p(aaedkbd_remove), | ||
165 | .driver = { | ||
166 | .name = "aaed2000-keyboard", | ||
167 | .owner = THIS_MODULE, | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | static int __init aaedkbd_init(void) | ||
172 | { | ||
173 | return platform_driver_register(&aaedkbd_driver); | ||
174 | } | ||
175 | |||
176 | static void __exit aaedkbd_exit(void) | ||
177 | { | ||
178 | platform_driver_unregister(&aaedkbd_driver); | ||
179 | } | ||
180 | |||
181 | module_init(aaedkbd_init); | ||
182 | module_exit(aaedkbd_exit); | ||
183 | |||
184 | MODULE_AUTHOR("Nicolas Bellido Y Ortega"); | ||
185 | MODULE_DESCRIPTION("AAED-2000 Keyboard Driver"); | ||
186 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index bcb1fdedb595..307eef77a172 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
@@ -229,7 +229,7 @@ config SERIO_PS2MULT | |||
229 | tristate "TQC PS/2 multiplexer" | 229 | tristate "TQC PS/2 multiplexer" |
230 | help | 230 | help |
231 | Say Y here if you have the PS/2 line multiplexer like the one | 231 | Say Y here if you have the PS/2 line multiplexer like the one |
232 | present on TQC boads. | 232 | present on TQC boards. |
233 | 233 | ||
234 | To compile this driver as a module, choose M here: the | 234 | To compile this driver as a module, choose M here: the |
235 | module will be called ps2mult. | 235 | module will be called ps2mult. |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5ae0fc4578fe..bb9f5d31f0d0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -424,6 +424,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { | |||
424 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | 424 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), |
425 | }, | 425 | }, |
426 | }, | 426 | }, |
427 | { | ||
428 | /* Dell Vostro V13 */ | ||
429 | .matches = { | ||
430 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
431 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), | ||
432 | }, | ||
433 | }, | ||
427 | { } | 434 | { } |
428 | }; | 435 | }; |
429 | 436 | ||
@@ -545,6 +552,17 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { | |||
545 | }; | 552 | }; |
546 | #endif | 553 | #endif |
547 | 554 | ||
555 | static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = { | ||
556 | { | ||
557 | /* Dell Vostro V13 */ | ||
558 | .matches = { | ||
559 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
560 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"), | ||
561 | }, | ||
562 | }, | ||
563 | { } | ||
564 | }; | ||
565 | |||
548 | /* | 566 | /* |
549 | * Some Wistron based laptops need us to explicitly enable the 'Dritek | 567 | * Some Wistron based laptops need us to explicitly enable the 'Dritek |
550 | * keyboard extension' to make their extra keys start generating scancodes. | 568 | * keyboard extension' to make their extra keys start generating scancodes. |
@@ -896,6 +914,9 @@ static int __init i8042_platform_init(void) | |||
896 | if (dmi_check_system(i8042_dmi_nomux_table)) | 914 | if (dmi_check_system(i8042_dmi_nomux_table)) |
897 | i8042_nomux = true; | 915 | i8042_nomux = true; |
898 | 916 | ||
917 | if (dmi_check_system(i8042_dmi_notimeout_table)) | ||
918 | i8042_notimeout = true; | ||
919 | |||
899 | if (dmi_check_system(i8042_dmi_dritek_table)) | 920 | if (dmi_check_system(i8042_dmi_dritek_table)) |
900 | i8042_dritek = true; | 921 | i8042_dritek = true; |
901 | #endif /* CONFIG_X86 */ | 922 | #endif /* CONFIG_X86 */ |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index c04ff00a3663..ac4c93689ab9 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -63,6 +63,10 @@ static bool i8042_noloop; | |||
63 | module_param_named(noloop, i8042_noloop, bool, 0); | 63 | module_param_named(noloop, i8042_noloop, bool, 0); |
64 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 64 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
65 | 65 | ||
66 | static bool i8042_notimeout; | ||
67 | module_param_named(notimeout, i8042_notimeout, bool, 0); | ||
68 | MODULE_PARM_DESC(notimeout, "Ignore timeouts signalled by i8042"); | ||
69 | |||
66 | #ifdef CONFIG_X86 | 70 | #ifdef CONFIG_X86 |
67 | static bool i8042_dritek; | 71 | static bool i8042_dritek; |
68 | module_param_named(dritek, i8042_dritek, bool, 0); | 72 | module_param_named(dritek, i8042_dritek, bool, 0); |
@@ -504,7 +508,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
504 | } else { | 508 | } else { |
505 | 509 | ||
506 | dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | | 510 | dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | |
507 | ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0); | 511 | ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); |
508 | 512 | ||
509 | port_no = (str & I8042_STR_AUXDATA) ? | 513 | port_no = (str & I8042_STR_AUXDATA) ? |
510 | I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; | 514 | I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 07ac77d393a4..0c9f4b158ff0 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -610,7 +610,7 @@ config TOUCHSCREEN_USB_ZYTRONIC | |||
610 | 610 | ||
611 | config TOUCHSCREEN_USB_ETT_TC45USB | 611 | config TOUCHSCREEN_USB_ETT_TC45USB |
612 | default y | 612 | default y |
613 | bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED | 613 | bool "ET&T USB series TC4UM/TC5UH touchscreen controller support" if EMBEDDED |
614 | depends on TOUCHSCREEN_USB_COMPOSITE | 614 | depends on TOUCHSCREEN_USB_COMPOSITE |
615 | 615 | ||
616 | config TOUCHSCREEN_USB_NEXIO | 616 | config TOUCHSCREEN_USB_NEXIO |
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index d82a38ee9a3e..4e4e58cec6c8 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c | |||
@@ -10,14 +10,16 @@ | |||
10 | #include <linux/i2c.h> | 10 | #include <linux/i2c.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/pm.h> | ||
13 | 14 | ||
14 | #include "ad7879.h" | 15 | #include "ad7879.h" |
15 | 16 | ||
16 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ | 17 | #define AD7879_DEVID 0x79 /* AD7879-1/AD7889-1 */ |
17 | 18 | ||
18 | #ifdef CONFIG_PM | 19 | #ifdef CONFIG_PM |
19 | static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message) | 20 | static int ad7879_i2c_suspend(struct device *dev) |
20 | { | 21 | { |
22 | struct i2c_client *client = to_i2c_client(dev); | ||
21 | struct ad7879 *ts = i2c_get_clientdata(client); | 23 | struct ad7879 *ts = i2c_get_clientdata(client); |
22 | 24 | ||
23 | ad7879_suspend(ts); | 25 | ad7879_suspend(ts); |
@@ -25,17 +27,17 @@ static int ad7879_i2c_suspend(struct i2c_client *client, pm_message_t message) | |||
25 | return 0; | 27 | return 0; |
26 | } | 28 | } |
27 | 29 | ||
28 | static int ad7879_i2c_resume(struct i2c_client *client) | 30 | static int ad7879_i2c_resume(struct device *dev) |
29 | { | 31 | { |
32 | struct i2c_client *client = to_i2c_client(dev); | ||
30 | struct ad7879 *ts = i2c_get_clientdata(client); | 33 | struct ad7879 *ts = i2c_get_clientdata(client); |
31 | 34 | ||
32 | ad7879_resume(ts); | 35 | ad7879_resume(ts); |
33 | 36 | ||
34 | return 0; | 37 | return 0; |
35 | } | 38 | } |
36 | #else | 39 | |
37 | # define ad7879_i2c_suspend NULL | 40 | static SIMPLE_DEV_PM_OPS(ad7879_i2c_pm, ad7879_i2c_suspend, ad7879_i2c_resume); |
38 | # define ad7879_i2c_resume NULL | ||
39 | #endif | 41 | #endif |
40 | 42 | ||
41 | /* All registers are word-sized. | 43 | /* All registers are word-sized. |
@@ -117,11 +119,12 @@ static struct i2c_driver ad7879_i2c_driver = { | |||
117 | .driver = { | 119 | .driver = { |
118 | .name = "ad7879", | 120 | .name = "ad7879", |
119 | .owner = THIS_MODULE, | 121 | .owner = THIS_MODULE, |
122 | #ifdef CONFIG_PM | ||
123 | .pm = &ad7879_i2c_pm, | ||
124 | #endif | ||
120 | }, | 125 | }, |
121 | .probe = ad7879_i2c_probe, | 126 | .probe = ad7879_i2c_probe, |
122 | .remove = __devexit_p(ad7879_i2c_remove), | 127 | .remove = __devexit_p(ad7879_i2c_remove), |
123 | .suspend = ad7879_i2c_suspend, | ||
124 | .resume = ad7879_i2c_resume, | ||
125 | .id_table = ad7879_id, | 128 | .id_table = ad7879_id, |
126 | }; | 129 | }; |
127 | 130 | ||
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index d0c3a7229adf..a93c5c26ab3f 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c | |||
@@ -280,8 +280,9 @@ err_free_mem: | |||
280 | } | 280 | } |
281 | 281 | ||
282 | #ifdef CONFIG_PM | 282 | #ifdef CONFIG_PM |
283 | static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg) | 283 | static int cy8ctmg110_suspend(struct device *dev) |
284 | { | 284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | ||
285 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 286 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
286 | 287 | ||
287 | if (device_may_wakeup(&client->dev)) | 288 | if (device_may_wakeup(&client->dev)) |
@@ -293,8 +294,9 @@ static int cy8ctmg110_suspend(struct i2c_client *client, pm_message_t mesg) | |||
293 | return 0; | 294 | return 0; |
294 | } | 295 | } |
295 | 296 | ||
296 | static int cy8ctmg110_resume(struct i2c_client *client) | 297 | static int cy8ctmg110_resume(struct device *dev) |
297 | { | 298 | { |
299 | struct i2c_client *client = to_i2c_client(dev); | ||
298 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); | 300 | struct cy8ctmg110 *ts = i2c_get_clientdata(client); |
299 | 301 | ||
300 | if (device_may_wakeup(&client->dev)) | 302 | if (device_may_wakeup(&client->dev)) |
@@ -305,6 +307,8 @@ static int cy8ctmg110_resume(struct i2c_client *client) | |||
305 | } | 307 | } |
306 | return 0; | 308 | return 0; |
307 | } | 309 | } |
310 | |||
311 | static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); | ||
308 | #endif | 312 | #endif |
309 | 313 | ||
310 | static int __devexit cy8ctmg110_remove(struct i2c_client *client) | 314 | static int __devexit cy8ctmg110_remove(struct i2c_client *client) |
@@ -335,14 +339,13 @@ static struct i2c_driver cy8ctmg110_driver = { | |||
335 | .driver = { | 339 | .driver = { |
336 | .owner = THIS_MODULE, | 340 | .owner = THIS_MODULE, |
337 | .name = CY8CTMG110_DRIVER_NAME, | 341 | .name = CY8CTMG110_DRIVER_NAME, |
342 | #ifdef CONFIG_PM | ||
343 | .pm = &cy8ctmg110_pm, | ||
344 | #endif | ||
338 | }, | 345 | }, |
339 | .id_table = cy8ctmg110_idtable, | 346 | .id_table = cy8ctmg110_idtable, |
340 | .probe = cy8ctmg110_probe, | 347 | .probe = cy8ctmg110_probe, |
341 | .remove = __devexit_p(cy8ctmg110_remove), | 348 | .remove = __devexit_p(cy8ctmg110_remove), |
342 | #ifdef CONFIG_PM | ||
343 | .suspend = cy8ctmg110_suspend, | ||
344 | .resume = cy8ctmg110_resume, | ||
345 | #endif | ||
346 | }; | 349 | }; |
347 | 350 | ||
348 | static int __init cy8ctmg110_init(void) | 351 | static int __init cy8ctmg110_init(void) |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 7a3a916f84a8..7f8f538a9806 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -261,8 +261,9 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | #ifdef CONFIG_PM | 263 | #ifdef CONFIG_PM |
264 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 264 | static int eeti_ts_suspend(struct device *dev) |
265 | { | 265 | { |
266 | struct i2c_client *client = to_i2c_client(dev); | ||
266 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 267 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
267 | struct input_dev *input_dev = priv->input; | 268 | struct input_dev *input_dev = priv->input; |
268 | 269 | ||
@@ -279,8 +280,9 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |||
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
281 | 282 | ||
282 | static int eeti_ts_resume(struct i2c_client *client) | 283 | static int eeti_ts_resume(struct device *dev) |
283 | { | 284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | ||
284 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 286 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
285 | struct input_dev *input_dev = priv->input; | 287 | struct input_dev *input_dev = priv->input; |
286 | 288 | ||
@@ -296,9 +298,8 @@ static int eeti_ts_resume(struct i2c_client *client) | |||
296 | 298 | ||
297 | return 0; | 299 | return 0; |
298 | } | 300 | } |
299 | #else | 301 | |
300 | #define eeti_ts_suspend NULL | 302 | static SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume); |
301 | #define eeti_ts_resume NULL | ||
302 | #endif | 303 | #endif |
303 | 304 | ||
304 | static const struct i2c_device_id eeti_ts_id[] = { | 305 | static const struct i2c_device_id eeti_ts_id[] = { |
@@ -310,11 +311,12 @@ MODULE_DEVICE_TABLE(i2c, eeti_ts_id); | |||
310 | static struct i2c_driver eeti_ts_driver = { | 311 | static struct i2c_driver eeti_ts_driver = { |
311 | .driver = { | 312 | .driver = { |
312 | .name = "eeti_ts", | 313 | .name = "eeti_ts", |
314 | #ifdef CONFIG_PM | ||
315 | .pm = &eeti_ts_pm, | ||
316 | #endif | ||
313 | }, | 317 | }, |
314 | .probe = eeti_ts_probe, | 318 | .probe = eeti_ts_probe, |
315 | .remove = __devexit_p(eeti_ts_remove), | 319 | .remove = __devexit_p(eeti_ts_remove), |
316 | .suspend = eeti_ts_suspend, | ||
317 | .resume = eeti_ts_resume, | ||
318 | .id_table = eeti_ts_id, | 320 | .id_table = eeti_ts_id, |
319 | }; | 321 | }; |
320 | 322 | ||
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 6ee9940aaf5b..2d84c80ceb66 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
@@ -261,25 +261,27 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | #ifdef CONFIG_PM | 263 | #ifdef CONFIG_PM |
264 | static int mcs5000_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 264 | static int mcs5000_ts_suspend(struct device *dev) |
265 | { | 265 | { |
266 | struct i2c_client *client = to_i2c_client(dev); | ||
267 | |||
266 | /* Touch sleep mode */ | 268 | /* Touch sleep mode */ |
267 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); | 269 | i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); |
268 | 270 | ||
269 | return 0; | 271 | return 0; |
270 | } | 272 | } |
271 | 273 | ||
272 | static int mcs5000_ts_resume(struct i2c_client *client) | 274 | static int mcs5000_ts_resume(struct device *dev) |
273 | { | 275 | { |
276 | struct i2c_client *client = to_i2c_client(dev); | ||
274 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); | 277 | struct mcs5000_ts_data *data = i2c_get_clientdata(client); |
275 | 278 | ||
276 | mcs5000_ts_phys_init(data); | 279 | mcs5000_ts_phys_init(data); |
277 | 280 | ||
278 | return 0; | 281 | return 0; |
279 | } | 282 | } |
280 | #else | 283 | |
281 | #define mcs5000_ts_suspend NULL | 284 | static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume); |
282 | #define mcs5000_ts_resume NULL | ||
283 | #endif | 285 | #endif |
284 | 286 | ||
285 | static const struct i2c_device_id mcs5000_ts_id[] = { | 287 | static const struct i2c_device_id mcs5000_ts_id[] = { |
@@ -291,10 +293,11 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); | |||
291 | static struct i2c_driver mcs5000_ts_driver = { | 293 | static struct i2c_driver mcs5000_ts_driver = { |
292 | .probe = mcs5000_ts_probe, | 294 | .probe = mcs5000_ts_probe, |
293 | .remove = __devexit_p(mcs5000_ts_remove), | 295 | .remove = __devexit_p(mcs5000_ts_remove), |
294 | .suspend = mcs5000_ts_suspend, | ||
295 | .resume = mcs5000_ts_resume, | ||
296 | .driver = { | 296 | .driver = { |
297 | .name = "mcs5000_ts", | 297 | .name = "mcs5000_ts", |
298 | #ifdef CONFIG_PM | ||
299 | .pm = &mcs5000_ts_pm, | ||
300 | #endif | ||
298 | }, | 301 | }, |
299 | .id_table = mcs5000_ts_id, | 302 | .id_table = mcs5000_ts_id, |
300 | }; | 303 | }; |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index defe5dd3627c..5803bd0c1cca 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/pm.h> | ||
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <asm/io.h> | 28 | #include <asm/io.h> |
28 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
@@ -226,8 +227,9 @@ static int migor_ts_remove(struct i2c_client *client) | |||
226 | return 0; | 227 | return 0; |
227 | } | 228 | } |
228 | 229 | ||
229 | static int migor_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 230 | static int migor_ts_suspend(struct device *dev) |
230 | { | 231 | { |
232 | struct i2c_client *client = to_i2c_client(dev); | ||
231 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); | 233 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
232 | 234 | ||
233 | if (device_may_wakeup(&client->dev)) | 235 | if (device_may_wakeup(&client->dev)) |
@@ -236,8 +238,9 @@ static int migor_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |||
236 | return 0; | 238 | return 0; |
237 | } | 239 | } |
238 | 240 | ||
239 | static int migor_ts_resume(struct i2c_client *client) | 241 | static int migor_ts_resume(struct device *dev) |
240 | { | 242 | { |
243 | struct i2c_client *client = to_i2c_client(dev); | ||
241 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); | 244 | struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); |
242 | 245 | ||
243 | if (device_may_wakeup(&client->dev)) | 246 | if (device_may_wakeup(&client->dev)) |
@@ -246,6 +249,8 @@ static int migor_ts_resume(struct i2c_client *client) | |||
246 | return 0; | 249 | return 0; |
247 | } | 250 | } |
248 | 251 | ||
252 | static SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume); | ||
253 | |||
249 | static const struct i2c_device_id migor_ts_id[] = { | 254 | static const struct i2c_device_id migor_ts_id[] = { |
250 | { "migor_ts", 0 }, | 255 | { "migor_ts", 0 }, |
251 | { } | 256 | { } |
@@ -255,11 +260,10 @@ MODULE_DEVICE_TABLE(i2c, migor_ts); | |||
255 | static struct i2c_driver migor_ts_driver = { | 260 | static struct i2c_driver migor_ts_driver = { |
256 | .driver = { | 261 | .driver = { |
257 | .name = "migor_ts", | 262 | .name = "migor_ts", |
263 | .pm = &migor_ts_pm, | ||
258 | }, | 264 | }, |
259 | .probe = migor_ts_probe, | 265 | .probe = migor_ts_probe, |
260 | .remove = migor_ts_remove, | 266 | .remove = migor_ts_remove, |
261 | .suspend = migor_ts_suspend, | ||
262 | .resume = migor_ts_resume, | ||
263 | .id_table = migor_ts_id, | 267 | .id_table = migor_ts_id, |
264 | }; | 268 | }; |
265 | 269 | ||
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 8ed53aded2d3..5cb8449c909d 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (c) 2008 Jaya Kumar | 4 | * Copyright (c) 2008 Jaya Kumar |
5 | * Copyright (c) 2010 Red Hat, Inc. | 5 | * Copyright (c) 2010 Red Hat, Inc. |
6 | * Copyright (c) 2010 - 2011 Ping Cheng, Wacom. <pingc@wacom.com> | ||
6 | * | 7 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
8 | * License. See the file COPYING in the main directory of this archive for | 9 | * License. See the file COPYING in the main directory of this archive for |
@@ -64,11 +65,11 @@ struct w8001_coord { | |||
64 | 65 | ||
65 | /* touch query reply packet */ | 66 | /* touch query reply packet */ |
66 | struct w8001_touch_query { | 67 | struct w8001_touch_query { |
68 | u16 x; | ||
69 | u16 y; | ||
67 | u8 panel_res; | 70 | u8 panel_res; |
68 | u8 capacity_res; | 71 | u8 capacity_res; |
69 | u8 sensor_id; | 72 | u8 sensor_id; |
70 | u16 x; | ||
71 | u16 y; | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | /* | 75 | /* |
@@ -87,9 +88,14 @@ struct w8001 { | |||
87 | char phys[32]; | 88 | char phys[32]; |
88 | int type; | 89 | int type; |
89 | unsigned int pktlen; | 90 | unsigned int pktlen; |
91 | u16 max_touch_x; | ||
92 | u16 max_touch_y; | ||
93 | u16 max_pen_x; | ||
94 | u16 max_pen_y; | ||
95 | char name[64]; | ||
90 | }; | 96 | }; |
91 | 97 | ||
92 | static void parse_data(u8 *data, struct w8001_coord *coord) | 98 | static void parse_pen_data(u8 *data, struct w8001_coord *coord) |
93 | { | 99 | { |
94 | memset(coord, 0, sizeof(*coord)); | 100 | memset(coord, 0, sizeof(*coord)); |
95 | 101 | ||
@@ -113,11 +119,30 @@ static void parse_data(u8 *data, struct w8001_coord *coord) | |||
113 | coord->tilt_y = data[8] & 0x7F; | 119 | coord->tilt_y = data[8] & 0x7F; |
114 | } | 120 | } |
115 | 121 | ||
116 | static void parse_touch(struct w8001 *w8001) | 122 | static void parse_single_touch(u8 *data, struct w8001_coord *coord) |
123 | { | ||
124 | coord->x = (data[1] << 7) | data[2]; | ||
125 | coord->y = (data[3] << 7) | data[4]; | ||
126 | coord->tsw = data[0] & 0x01; | ||
127 | } | ||
128 | |||
129 | static void scale_touch_coordinates(struct w8001 *w8001, | ||
130 | unsigned int *x, unsigned int *y) | ||
131 | { | ||
132 | if (w8001->max_pen_x && w8001->max_touch_x) | ||
133 | *x = *x * w8001->max_pen_x / w8001->max_touch_x; | ||
134 | |||
135 | if (w8001->max_pen_y && w8001->max_touch_y) | ||
136 | *y = *y * w8001->max_pen_y / w8001->max_touch_y; | ||
137 | } | ||
138 | |||
139 | static void parse_multi_touch(struct w8001 *w8001) | ||
117 | { | 140 | { |
118 | struct input_dev *dev = w8001->dev; | 141 | struct input_dev *dev = w8001->dev; |
119 | unsigned char *data = w8001->data; | 142 | unsigned char *data = w8001->data; |
143 | unsigned int x, y; | ||
120 | int i; | 144 | int i; |
145 | int count = 0; | ||
121 | 146 | ||
122 | for (i = 0; i < 2; i++) { | 147 | for (i = 0; i < 2; i++) { |
123 | bool touch = data[0] & (1 << i); | 148 | bool touch = data[0] & (1 << i); |
@@ -125,15 +150,29 @@ static void parse_touch(struct w8001 *w8001) | |||
125 | input_mt_slot(dev, i); | 150 | input_mt_slot(dev, i); |
126 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch); | 151 | input_mt_report_slot_state(dev, MT_TOOL_FINGER, touch); |
127 | if (touch) { | 152 | if (touch) { |
128 | int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]); | 153 | x = (data[6 * i + 1] << 7) | data[6 * i + 2]; |
129 | int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]); | 154 | y = (data[6 * i + 3] << 7) | data[6 * i + 4]; |
130 | /* data[5,6] and [11,12] is finger capacity */ | 155 | /* data[5,6] and [11,12] is finger capacity */ |
131 | 156 | ||
157 | /* scale to pen maximum */ | ||
158 | scale_touch_coordinates(w8001, &x, &y); | ||
159 | |||
132 | input_report_abs(dev, ABS_MT_POSITION_X, x); | 160 | input_report_abs(dev, ABS_MT_POSITION_X, x); |
133 | input_report_abs(dev, ABS_MT_POSITION_Y, y); | 161 | input_report_abs(dev, ABS_MT_POSITION_Y, y); |
162 | count++; | ||
134 | } | 163 | } |
135 | } | 164 | } |
136 | 165 | ||
166 | /* emulate single touch events when stylus is out of proximity. | ||
167 | * This is to make single touch backward support consistent | ||
168 | * across all Wacom single touch devices. | ||
169 | */ | ||
170 | if (w8001->type != BTN_TOOL_PEN && | ||
171 | w8001->type != BTN_TOOL_RUBBER) { | ||
172 | w8001->type = count == 1 ? BTN_TOOL_FINGER : KEY_RESERVED; | ||
173 | input_mt_report_pointer_emulation(dev, true); | ||
174 | } | ||
175 | |||
137 | input_sync(dev); | 176 | input_sync(dev); |
138 | } | 177 | } |
139 | 178 | ||
@@ -152,6 +191,15 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query) | |||
152 | query->y = data[5] << 9; | 191 | query->y = data[5] << 9; |
153 | query->y |= data[6] << 2; | 192 | query->y |= data[6] << 2; |
154 | query->y |= (data[2] >> 3) & 0x3; | 193 | query->y |= (data[2] >> 3) & 0x3; |
194 | |||
195 | /* Early days' single-finger touch models need the following defaults */ | ||
196 | if (!query->x && !query->y) { | ||
197 | query->x = 1024; | ||
198 | query->y = 1024; | ||
199 | if (query->panel_res) | ||
200 | query->x = query->y = (1 << query->panel_res); | ||
201 | query->panel_res = 10; | ||
202 | } | ||
155 | } | 203 | } |
156 | 204 | ||
157 | static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | 205 | static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) |
@@ -161,16 +209,15 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | |||
161 | /* | 209 | /* |
162 | * We have 1 bit for proximity (rdy) and 3 bits for tip, side, | 210 | * We have 1 bit for proximity (rdy) and 3 bits for tip, side, |
163 | * side2/eraser. If rdy && f2 are set, this can be either pen + side2, | 211 | * side2/eraser. If rdy && f2 are set, this can be either pen + side2, |
164 | * or eraser. assume | 212 | * or eraser. Assume: |
165 | * - if dev is already in proximity and f2 is toggled → pen + side2 | 213 | * - if dev is already in proximity and f2 is toggled → pen + side2 |
166 | * - if dev comes into proximity with f2 set → eraser | 214 | * - if dev comes into proximity with f2 set → eraser |
167 | * If f2 disappears after assuming eraser, fake proximity out for | 215 | * If f2 disappears after assuming eraser, fake proximity out for |
168 | * eraser and in for pen. | 216 | * eraser and in for pen. |
169 | */ | 217 | */ |
170 | 218 | ||
171 | if (!w8001->type) { | 219 | switch (w8001->type) { |
172 | w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 220 | case BTN_TOOL_RUBBER: |
173 | } else if (w8001->type == BTN_TOOL_RUBBER) { | ||
174 | if (!coord->f2) { | 221 | if (!coord->f2) { |
175 | input_report_abs(dev, ABS_PRESSURE, 0); | 222 | input_report_abs(dev, ABS_PRESSURE, 0); |
176 | input_report_key(dev, BTN_TOUCH, 0); | 223 | input_report_key(dev, BTN_TOUCH, 0); |
@@ -180,8 +227,21 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | |||
180 | input_sync(dev); | 227 | input_sync(dev); |
181 | w8001->type = BTN_TOOL_PEN; | 228 | w8001->type = BTN_TOOL_PEN; |
182 | } | 229 | } |
183 | } else { | 230 | break; |
231 | |||
232 | case BTN_TOOL_FINGER: | ||
233 | input_report_key(dev, BTN_TOUCH, 0); | ||
234 | input_report_key(dev, BTN_TOOL_FINGER, 0); | ||
235 | input_sync(dev); | ||
236 | /* fall through */ | ||
237 | |||
238 | case KEY_RESERVED: | ||
239 | w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
240 | break; | ||
241 | |||
242 | default: | ||
184 | input_report_key(dev, BTN_STYLUS2, coord->f2); | 243 | input_report_key(dev, BTN_STYLUS2, coord->f2); |
244 | break; | ||
185 | } | 245 | } |
186 | 246 | ||
187 | input_report_abs(dev, ABS_X, coord->x); | 247 | input_report_abs(dev, ABS_X, coord->x); |
@@ -193,7 +253,26 @@ static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) | |||
193 | input_sync(dev); | 253 | input_sync(dev); |
194 | 254 | ||
195 | if (!coord->rdy) | 255 | if (!coord->rdy) |
196 | w8001->type = 0; | 256 | w8001->type = KEY_RESERVED; |
257 | } | ||
258 | |||
259 | static void report_single_touch(struct w8001 *w8001, struct w8001_coord *coord) | ||
260 | { | ||
261 | struct input_dev *dev = w8001->dev; | ||
262 | unsigned int x = coord->x; | ||
263 | unsigned int y = coord->y; | ||
264 | |||
265 | /* scale to pen maximum */ | ||
266 | scale_touch_coordinates(w8001, &x, &y); | ||
267 | |||
268 | input_report_abs(dev, ABS_X, x); | ||
269 | input_report_abs(dev, ABS_Y, y); | ||
270 | input_report_key(dev, BTN_TOUCH, coord->tsw); | ||
271 | input_report_key(dev, BTN_TOOL_FINGER, coord->tsw); | ||
272 | |||
273 | input_sync(dev); | ||
274 | |||
275 | w8001->type = coord->tsw ? BTN_TOOL_FINGER : KEY_RESERVED; | ||
197 | } | 276 | } |
198 | 277 | ||
199 | static irqreturn_t w8001_interrupt(struct serio *serio, | 278 | static irqreturn_t w8001_interrupt(struct serio *serio, |
@@ -214,9 +293,18 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
214 | 293 | ||
215 | case W8001_PKTLEN_TOUCH93 - 1: | 294 | case W8001_PKTLEN_TOUCH93 - 1: |
216 | case W8001_PKTLEN_TOUCH9A - 1: | 295 | case W8001_PKTLEN_TOUCH9A - 1: |
217 | /* ignore one-finger touch packet. */ | 296 | tmp = w8001->data[0] & W8001_TOUCH_BYTE; |
218 | if (w8001->pktlen == w8001->idx) | 297 | if (tmp != W8001_TOUCH_BYTE) |
298 | break; | ||
299 | |||
300 | if (w8001->pktlen == w8001->idx) { | ||
219 | w8001->idx = 0; | 301 | w8001->idx = 0; |
302 | if (w8001->type != BTN_TOOL_PEN && | ||
303 | w8001->type != BTN_TOOL_RUBBER) { | ||
304 | parse_single_touch(w8001->data, &coord); | ||
305 | report_single_touch(w8001, &coord); | ||
306 | } | ||
307 | } | ||
220 | break; | 308 | break; |
221 | 309 | ||
222 | /* Pen coordinates packet */ | 310 | /* Pen coordinates packet */ |
@@ -225,18 +313,18 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
225 | if (unlikely(tmp == W8001_TAB_BYTE)) | 313 | if (unlikely(tmp == W8001_TAB_BYTE)) |
226 | break; | 314 | break; |
227 | 315 | ||
228 | tmp = (w8001->data[0] & W8001_TOUCH_BYTE); | 316 | tmp = w8001->data[0] & W8001_TOUCH_BYTE; |
229 | if (tmp == W8001_TOUCH_BYTE) | 317 | if (tmp == W8001_TOUCH_BYTE) |
230 | break; | 318 | break; |
231 | 319 | ||
232 | w8001->idx = 0; | 320 | w8001->idx = 0; |
233 | parse_data(w8001->data, &coord); | 321 | parse_pen_data(w8001->data, &coord); |
234 | report_pen_events(w8001, &coord); | 322 | report_pen_events(w8001, &coord); |
235 | break; | 323 | break; |
236 | 324 | ||
237 | /* control packet */ | 325 | /* control packet */ |
238 | case W8001_PKTLEN_TPCCTL - 1: | 326 | case W8001_PKTLEN_TPCCTL - 1: |
239 | tmp = (w8001->data[0] & W8001_TOUCH_MASK); | 327 | tmp = w8001->data[0] & W8001_TOUCH_MASK; |
240 | if (tmp == W8001_TOUCH_BYTE) | 328 | if (tmp == W8001_TOUCH_BYTE) |
241 | break; | 329 | break; |
242 | 330 | ||
@@ -249,7 +337,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio, | |||
249 | /* 2 finger touch packet */ | 337 | /* 2 finger touch packet */ |
250 | case W8001_PKTLEN_TOUCH2FG - 1: | 338 | case W8001_PKTLEN_TOUCH2FG - 1: |
251 | w8001->idx = 0; | 339 | w8001->idx = 0; |
252 | parse_touch(w8001); | 340 | parse_multi_touch(w8001); |
253 | break; | 341 | break; |
254 | } | 342 | } |
255 | 343 | ||
@@ -279,6 +367,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
279 | { | 367 | { |
280 | struct input_dev *dev = w8001->dev; | 368 | struct input_dev *dev = w8001->dev; |
281 | struct w8001_coord coord; | 369 | struct w8001_coord coord; |
370 | struct w8001_touch_query touch; | ||
282 | int error; | 371 | int error; |
283 | 372 | ||
284 | error = w8001_command(w8001, W8001_CMD_STOP, false); | 373 | error = w8001_command(w8001, W8001_CMD_STOP, false); |
@@ -287,14 +376,21 @@ static int w8001_setup(struct w8001 *w8001) | |||
287 | 376 | ||
288 | msleep(250); /* wait 250ms before querying the device */ | 377 | msleep(250); /* wait 250ms before querying the device */ |
289 | 378 | ||
379 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
380 | strlcat(w8001->name, "Wacom Serial", sizeof(w8001->name)); | ||
381 | |||
290 | /* penabled? */ | 382 | /* penabled? */ |
291 | error = w8001_command(w8001, W8001_CMD_QUERY, true); | 383 | error = w8001_command(w8001, W8001_CMD_QUERY, true); |
292 | if (!error) { | 384 | if (!error) { |
385 | __set_bit(BTN_TOUCH, dev->keybit); | ||
293 | __set_bit(BTN_TOOL_PEN, dev->keybit); | 386 | __set_bit(BTN_TOOL_PEN, dev->keybit); |
294 | __set_bit(BTN_TOOL_RUBBER, dev->keybit); | 387 | __set_bit(BTN_TOOL_RUBBER, dev->keybit); |
295 | __set_bit(BTN_STYLUS, dev->keybit); | 388 | __set_bit(BTN_STYLUS, dev->keybit); |
296 | __set_bit(BTN_STYLUS2, dev->keybit); | 389 | __set_bit(BTN_STYLUS2, dev->keybit); |
297 | parse_data(w8001->response, &coord); | 390 | |
391 | parse_pen_data(w8001->response, &coord); | ||
392 | w8001->max_pen_x = coord.x; | ||
393 | w8001->max_pen_y = coord.y; | ||
298 | 394 | ||
299 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | 395 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); |
300 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | 396 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); |
@@ -303,6 +399,8 @@ static int w8001_setup(struct w8001 *w8001) | |||
303 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | 399 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); |
304 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | 400 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); |
305 | } | 401 | } |
402 | w8001->id = 0x90; | ||
403 | strlcat(w8001->name, " Penabled", sizeof(w8001->name)); | ||
306 | } | 404 | } |
307 | 405 | ||
308 | /* Touch enabled? */ | 406 | /* Touch enabled? */ |
@@ -313,24 +411,38 @@ static int w8001_setup(struct w8001 *w8001) | |||
313 | * second byte is empty, which indicates touch is not supported. | 411 | * second byte is empty, which indicates touch is not supported. |
314 | */ | 412 | */ |
315 | if (!error && w8001->response[1]) { | 413 | if (!error && w8001->response[1]) { |
316 | struct w8001_touch_query touch; | 414 | __set_bit(BTN_TOUCH, dev->keybit); |
415 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | ||
317 | 416 | ||
318 | parse_touchquery(w8001->response, &touch); | 417 | parse_touchquery(w8001->response, &touch); |
418 | w8001->max_touch_x = touch.x; | ||
419 | w8001->max_touch_y = touch.y; | ||
420 | |||
421 | /* scale to pen maximum */ | ||
422 | if (w8001->max_pen_x && w8001->max_pen_y) { | ||
423 | touch.x = w8001->max_pen_x; | ||
424 | touch.y = w8001->max_pen_y; | ||
425 | } | ||
319 | 426 | ||
320 | input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); | 427 | input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); |
321 | input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); | 428 | input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); |
322 | __set_bit(BTN_TOOL_FINGER, dev->keybit); | ||
323 | 429 | ||
324 | switch (touch.sensor_id) { | 430 | switch (touch.sensor_id) { |
325 | case 0: | 431 | case 0: |
326 | case 2: | 432 | case 2: |
327 | w8001->pktlen = W8001_PKTLEN_TOUCH93; | 433 | w8001->pktlen = W8001_PKTLEN_TOUCH93; |
434 | w8001->id = 0x93; | ||
435 | strlcat(w8001->name, " 1FG", sizeof(w8001->name)); | ||
328 | break; | 436 | break; |
437 | |||
329 | case 1: | 438 | case 1: |
330 | case 3: | 439 | case 3: |
331 | case 4: | 440 | case 4: |
332 | w8001->pktlen = W8001_PKTLEN_TOUCH9A; | 441 | w8001->pktlen = W8001_PKTLEN_TOUCH9A; |
442 | strlcat(w8001->name, " 1FG", sizeof(w8001->name)); | ||
443 | w8001->id = 0x9a; | ||
333 | break; | 444 | break; |
445 | |||
334 | case 5: | 446 | case 5: |
335 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; | 447 | w8001->pktlen = W8001_PKTLEN_TOUCH2FG; |
336 | 448 | ||
@@ -341,10 +453,18 @@ static int w8001_setup(struct w8001 *w8001) | |||
341 | 0, touch.y, 0, 0); | 453 | 0, touch.y, 0, 0); |
342 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, | 454 | input_set_abs_params(dev, ABS_MT_TOOL_TYPE, |
343 | 0, MT_TOOL_MAX, 0, 0); | 455 | 0, MT_TOOL_MAX, 0, 0); |
456 | |||
457 | strlcat(w8001->name, " 2FG", sizeof(w8001->name)); | ||
458 | if (w8001->max_pen_x && w8001->max_pen_y) | ||
459 | w8001->id = 0xE3; | ||
460 | else | ||
461 | w8001->id = 0xE2; | ||
344 | break; | 462 | break; |
345 | } | 463 | } |
346 | } | 464 | } |
347 | 465 | ||
466 | strlcat(w8001->name, " Touchscreen", sizeof(w8001->name)); | ||
467 | |||
348 | return w8001_command(w8001, W8001_CMD_START, false); | 468 | return w8001_command(w8001, W8001_CMD_START, false); |
349 | } | 469 | } |
350 | 470 | ||
@@ -384,22 +504,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
384 | } | 504 | } |
385 | 505 | ||
386 | w8001->serio = serio; | 506 | w8001->serio = serio; |
387 | w8001->id = serio->id.id; | ||
388 | w8001->dev = input_dev; | 507 | w8001->dev = input_dev; |
389 | init_completion(&w8001->cmd_done); | 508 | init_completion(&w8001->cmd_done); |
390 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 509 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
391 | 510 | ||
392 | input_dev->name = "Wacom W8001 Penabled Serial TouchScreen"; | ||
393 | input_dev->phys = w8001->phys; | ||
394 | input_dev->id.bustype = BUS_RS232; | ||
395 | input_dev->id.vendor = SERIO_W8001; | ||
396 | input_dev->id.product = w8001->id; | ||
397 | input_dev->id.version = 0x0100; | ||
398 | input_dev->dev.parent = &serio->dev; | ||
399 | |||
400 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
401 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
402 | |||
403 | serio_set_drvdata(serio, w8001); | 511 | serio_set_drvdata(serio, w8001); |
404 | err = serio_open(serio, drv); | 512 | err = serio_open(serio, drv); |
405 | if (err) | 513 | if (err) |
@@ -409,6 +517,14 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
409 | if (err) | 517 | if (err) |
410 | goto fail3; | 518 | goto fail3; |
411 | 519 | ||
520 | input_dev->name = w8001->name; | ||
521 | input_dev->phys = w8001->phys; | ||
522 | input_dev->id.product = w8001->id; | ||
523 | input_dev->id.bustype = BUS_RS232; | ||
524 | input_dev->id.vendor = 0x056a; | ||
525 | input_dev->id.version = 0x0100; | ||
526 | input_dev->dev.parent = &serio->dev; | ||
527 | |||
412 | err = input_register_device(w8001->dev); | 528 | err = input_register_device(w8001->dev); |
413 | if (err) | 529 | if (err) |
414 | goto fail3; | 530 | goto fail3; |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 178942a2ee61..8a3c5cfc4fea 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -2318,7 +2318,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2318 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2318 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2319 | le16_to_cpu(udev->descriptor.idProduct)); | 2319 | le16_to_cpu(udev->descriptor.idProduct)); |
2320 | 2320 | ||
2321 | /* allocate memory for our device state and intialize it */ | 2321 | /* allocate memory for our device state and initialize it */ |
2322 | cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, | 2322 | cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, |
2323 | GIGASET_MODULENAME); | 2323 | GIGASET_MODULENAME); |
2324 | if (!cs) | 2324 | if (!cs) |
@@ -2576,7 +2576,7 @@ static int __init bas_gigaset_init(void) | |||
2576 | { | 2576 | { |
2577 | int result; | 2577 | int result; |
2578 | 2578 | ||
2579 | /* allocate memory for our driver state and intialize it */ | 2579 | /* allocate memory for our driver state and initialize it */ |
2580 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 2580 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
2581 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 2581 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
2582 | &gigops, THIS_MODULE); | 2582 | &gigops, THIS_MODULE); |
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index d151dcbf770d..0ef09d0eb96b 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c | |||
@@ -513,7 +513,7 @@ gigaset_tty_open(struct tty_struct *tty) | |||
513 | return -ENODEV; | 513 | return -ENODEV; |
514 | } | 514 | } |
515 | 515 | ||
516 | /* allocate memory for our device state and intialize it */ | 516 | /* allocate memory for our device state and initialize it */ |
517 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); | 517 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
518 | if (!cs) | 518 | if (!cs) |
519 | goto error; | 519 | goto error; |
@@ -771,7 +771,7 @@ static int __init ser_gigaset_init(void) | |||
771 | return rc; | 771 | return rc; |
772 | } | 772 | } |
773 | 773 | ||
774 | /* allocate memory for our driver state and intialize it */ | 774 | /* allocate memory for our driver state and initialize it */ |
775 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 775 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
776 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 776 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
777 | &ops, THIS_MODULE); | 777 | &ops, THIS_MODULE); |
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4a66338f4e7d..5e3300d8a2a5 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -695,7 +695,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
695 | 695 | ||
696 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); | 696 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); |
697 | 697 | ||
698 | /* allocate memory for our device state and intialize it */ | 698 | /* allocate memory for our device state and initialize it */ |
699 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); | 699 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
700 | if (!cs) | 700 | if (!cs) |
701 | return -ENODEV; | 701 | return -ENODEV; |
@@ -894,7 +894,7 @@ static int __init usb_gigaset_init(void) | |||
894 | { | 894 | { |
895 | int result; | 895 | int result; |
896 | 896 | ||
897 | /* allocate memory for our driver state and intialize it */ | 897 | /* allocate memory for our driver state and initialize it */ |
898 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 898 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
899 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 899 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
900 | &ops, THIS_MODULE); | 900 | &ops, THIS_MODULE); |
diff --git a/drivers/isdn/hardware/mISDN/ipac.h b/drivers/isdn/hardware/mISDN/ipac.h index 74a6ccf9065c..8121e046b739 100644 --- a/drivers/isdn/hardware/mISDN/ipac.h +++ b/drivers/isdn/hardware/mISDN/ipac.h | |||
@@ -29,7 +29,7 @@ struct isac_hw { | |||
29 | u32 type; | 29 | u32 type; |
30 | u32 off; /* offset to isac regs */ | 30 | u32 off; /* offset to isac regs */ |
31 | char *name; | 31 | char *name; |
32 | spinlock_t *hwlock; /* lock HW acccess */ | 32 | spinlock_t *hwlock; /* lock HW access */ |
33 | read_reg_func *read_reg; | 33 | read_reg_func *read_reg; |
34 | write_reg_func *write_reg; | 34 | write_reg_func *write_reg; |
35 | fifo_func *read_fifo; | 35 | fifo_func *read_fifo; |
@@ -70,7 +70,7 @@ struct ipac_hw { | |||
70 | struct hscx_hw hscx[2]; | 70 | struct hscx_hw hscx[2]; |
71 | char *name; | 71 | char *name; |
72 | void *hw; | 72 | void *hw; |
73 | spinlock_t *hwlock; /* lock HW acccess */ | 73 | spinlock_t *hwlock; /* lock HW access */ |
74 | struct module *owner; | 74 | struct module *owner; |
75 | u32 type; | 75 | u32 type; |
76 | read_reg_func *read_reg; | 76 | read_reg_func *read_reg; |
diff --git a/drivers/isdn/hardware/mISDN/isar.h b/drivers/isdn/hardware/mISDN/isar.h index 4a134acd44d0..9962bdf699c7 100644 --- a/drivers/isdn/hardware/mISDN/isar.h +++ b/drivers/isdn/hardware/mISDN/isar.h | |||
@@ -44,7 +44,7 @@ struct isar_ch { | |||
44 | struct isar_hw { | 44 | struct isar_hw { |
45 | struct isar_ch ch[2]; | 45 | struct isar_ch ch[2]; |
46 | void *hw; | 46 | void *hw; |
47 | spinlock_t *hwlock; /* lock HW acccess */ | 47 | spinlock_t *hwlock; /* lock HW access */ |
48 | char *name; | 48 | char *name; |
49 | struct module *owner; | 49 | struct module *owner; |
50 | read_reg_func *read_reg; | 50 | read_reg_func *read_reg; |
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 76d9e673b4e1..309bacf1fadc 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c | |||
@@ -112,7 +112,7 @@ | |||
112 | * Disable rx-data: | 112 | * Disable rx-data: |
113 | * If cmx is realized in hardware, rx data will be disabled if requested by | 113 | * If cmx is realized in hardware, rx data will be disabled if requested by |
114 | * the upper layer. If dtmf decoding is done by software and enabled, rx data | 114 | * the upper layer. If dtmf decoding is done by software and enabled, rx data |
115 | * will not be diabled but blocked to the upper layer. | 115 | * will not be disabled but blocked to the upper layer. |
116 | * | 116 | * |
117 | * HFC conference engine: | 117 | * HFC conference engine: |
118 | * If it is possible to realize all features using hardware, hardware will be | 118 | * If it is possible to realize all features using hardware, hardware will be |
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 33facd0c45d1..80a3ae3c00b9 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c | |||
@@ -98,7 +98,6 @@ | |||
98 | #define LP5521_EXT_CLK_USED 0x08 | 98 | #define LP5521_EXT_CLK_USED 0x08 |
99 | 99 | ||
100 | struct lp5521_engine { | 100 | struct lp5521_engine { |
101 | const struct attribute_group *attributes; | ||
102 | int id; | 101 | int id; |
103 | u8 mode; | 102 | u8 mode; |
104 | u8 prog_page; | 103 | u8 prog_page; |
@@ -225,25 +224,22 @@ static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr) | |||
225 | curr); | 224 | curr); |
226 | } | 225 | } |
227 | 226 | ||
228 | static void lp5521_init_engine(struct lp5521_chip *chip, | 227 | static void lp5521_init_engine(struct lp5521_chip *chip) |
229 | const struct attribute_group *attr_group) | ||
230 | { | 228 | { |
231 | int i; | 229 | int i; |
232 | for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { | 230 | for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { |
233 | chip->engines[i].id = i + 1; | 231 | chip->engines[i].id = i + 1; |
234 | chip->engines[i].engine_mask = LP5521_ENG_MASK_BASE >> (i * 2); | 232 | chip->engines[i].engine_mask = LP5521_ENG_MASK_BASE >> (i * 2); |
235 | chip->engines[i].prog_page = i; | 233 | chip->engines[i].prog_page = i; |
236 | chip->engines[i].attributes = &attr_group[i]; | ||
237 | } | 234 | } |
238 | } | 235 | } |
239 | 236 | ||
240 | static int lp5521_configure(struct i2c_client *client, | 237 | static int lp5521_configure(struct i2c_client *client) |
241 | const struct attribute_group *attr_group) | ||
242 | { | 238 | { |
243 | struct lp5521_chip *chip = i2c_get_clientdata(client); | 239 | struct lp5521_chip *chip = i2c_get_clientdata(client); |
244 | int ret; | 240 | int ret; |
245 | 241 | ||
246 | lp5521_init_engine(chip, attr_group); | 242 | lp5521_init_engine(chip); |
247 | 243 | ||
248 | /* Set all PWMs to direct control mode */ | 244 | /* Set all PWMs to direct control mode */ |
249 | ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F); | 245 | ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F); |
@@ -329,9 +325,6 @@ static int lp5521_detect(struct i2c_client *client) | |||
329 | /* Set engine mode and create appropriate sysfs attributes, if required. */ | 325 | /* Set engine mode and create appropriate sysfs attributes, if required. */ |
330 | static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode) | 326 | static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode) |
331 | { | 327 | { |
332 | struct lp5521_chip *chip = engine_to_lp5521(engine); | ||
333 | struct i2c_client *client = chip->client; | ||
334 | struct device *dev = &client->dev; | ||
335 | int ret = 0; | 328 | int ret = 0; |
336 | 329 | ||
337 | /* if in that mode already do nothing, except for run */ | 330 | /* if in that mode already do nothing, except for run */ |
@@ -343,18 +336,10 @@ static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode) | |||
343 | } else if (mode == LP5521_CMD_LOAD) { | 336 | } else if (mode == LP5521_CMD_LOAD) { |
344 | lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED); | 337 | lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED); |
345 | lp5521_set_engine_mode(engine, LP5521_CMD_LOAD); | 338 | lp5521_set_engine_mode(engine, LP5521_CMD_LOAD); |
346 | |||
347 | ret = sysfs_create_group(&dev->kobj, engine->attributes); | ||
348 | if (ret) | ||
349 | return ret; | ||
350 | } else if (mode == LP5521_CMD_DISABLED) { | 339 | } else if (mode == LP5521_CMD_DISABLED) { |
351 | lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED); | 340 | lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED); |
352 | } | 341 | } |
353 | 342 | ||
354 | /* remove load attribute from sysfs if not in load mode */ | ||
355 | if (engine->mode == LP5521_CMD_LOAD && mode != LP5521_CMD_LOAD) | ||
356 | sysfs_remove_group(&dev->kobj, engine->attributes); | ||
357 | |||
358 | engine->mode = mode; | 343 | engine->mode = mode; |
359 | 344 | ||
360 | return ret; | 345 | return ret; |
@@ -373,6 +358,8 @@ static int lp5521_do_store_load(struct lp5521_engine *engine, | |||
373 | while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) { | 358 | while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) { |
374 | /* separate sscanfs because length is working only for %s */ | 359 | /* separate sscanfs because length is working only for %s */ |
375 | ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); | 360 | ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); |
361 | if (ret != 2) | ||
362 | goto fail; | ||
376 | ret = sscanf(c, "%2x", &cmd); | 363 | ret = sscanf(c, "%2x", &cmd); |
377 | if (ret != 1) | 364 | if (ret != 1) |
378 | goto fail; | 365 | goto fail; |
@@ -387,7 +374,10 @@ static int lp5521_do_store_load(struct lp5521_engine *engine, | |||
387 | goto fail; | 374 | goto fail; |
388 | 375 | ||
389 | mutex_lock(&chip->lock); | 376 | mutex_lock(&chip->lock); |
390 | ret = lp5521_load_program(engine, pattern); | 377 | if (engine->mode == LP5521_CMD_LOAD) |
378 | ret = lp5521_load_program(engine, pattern); | ||
379 | else | ||
380 | ret = -EINVAL; | ||
391 | mutex_unlock(&chip->lock); | 381 | mutex_unlock(&chip->lock); |
392 | 382 | ||
393 | if (ret) { | 383 | if (ret) { |
@@ -574,20 +564,8 @@ static struct attribute *lp5521_attributes[] = { | |||
574 | &dev_attr_engine2_mode.attr, | 564 | &dev_attr_engine2_mode.attr, |
575 | &dev_attr_engine3_mode.attr, | 565 | &dev_attr_engine3_mode.attr, |
576 | &dev_attr_selftest.attr, | 566 | &dev_attr_selftest.attr, |
577 | NULL | ||
578 | }; | ||
579 | |||
580 | static struct attribute *lp5521_engine1_attributes[] = { | ||
581 | &dev_attr_engine1_load.attr, | 567 | &dev_attr_engine1_load.attr, |
582 | NULL | ||
583 | }; | ||
584 | |||
585 | static struct attribute *lp5521_engine2_attributes[] = { | ||
586 | &dev_attr_engine2_load.attr, | 568 | &dev_attr_engine2_load.attr, |
587 | NULL | ||
588 | }; | ||
589 | |||
590 | static struct attribute *lp5521_engine3_attributes[] = { | ||
591 | &dev_attr_engine3_load.attr, | 569 | &dev_attr_engine3_load.attr, |
592 | NULL | 570 | NULL |
593 | }; | 571 | }; |
@@ -596,12 +574,6 @@ static const struct attribute_group lp5521_group = { | |||
596 | .attrs = lp5521_attributes, | 574 | .attrs = lp5521_attributes, |
597 | }; | 575 | }; |
598 | 576 | ||
599 | static const struct attribute_group lp5521_engine_group[] = { | ||
600 | {.attrs = lp5521_engine1_attributes }, | ||
601 | {.attrs = lp5521_engine2_attributes }, | ||
602 | {.attrs = lp5521_engine3_attributes }, | ||
603 | }; | ||
604 | |||
605 | static int lp5521_register_sysfs(struct i2c_client *client) | 577 | static int lp5521_register_sysfs(struct i2c_client *client) |
606 | { | 578 | { |
607 | struct device *dev = &client->dev; | 579 | struct device *dev = &client->dev; |
@@ -616,12 +588,6 @@ static void lp5521_unregister_sysfs(struct i2c_client *client) | |||
616 | 588 | ||
617 | sysfs_remove_group(&dev->kobj, &lp5521_group); | 589 | sysfs_remove_group(&dev->kobj, &lp5521_group); |
618 | 590 | ||
619 | for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { | ||
620 | if (chip->engines[i].mode == LP5521_CMD_LOAD) | ||
621 | sysfs_remove_group(&dev->kobj, | ||
622 | chip->engines[i].attributes); | ||
623 | } | ||
624 | |||
625 | for (i = 0; i < chip->num_leds; i++) | 591 | for (i = 0; i < chip->num_leds; i++) |
626 | sysfs_remove_group(&chip->leds[i].cdev.dev->kobj, | 592 | sysfs_remove_group(&chip->leds[i].cdev.dev->kobj, |
627 | &lp5521_led_attribute_group); | 593 | &lp5521_led_attribute_group); |
@@ -651,7 +617,8 @@ static int __init lp5521_init_led(struct lp5521_led *led, | |||
651 | return -EINVAL; | 617 | return -EINVAL; |
652 | } | 618 | } |
653 | 619 | ||
654 | snprintf(name, sizeof(name), "%s:channel%d", client->name, chan); | 620 | snprintf(name, sizeof(name), "%s:channel%d", |
621 | pdata->label ?: client->name, chan); | ||
655 | led->cdev.brightness_set = lp5521_set_brightness; | 622 | led->cdev.brightness_set = lp5521_set_brightness; |
656 | led->cdev.name = name; | 623 | led->cdev.name = name; |
657 | res = led_classdev_register(dev, &led->cdev); | 624 | res = led_classdev_register(dev, &led->cdev); |
@@ -723,7 +690,7 @@ static int lp5521_probe(struct i2c_client *client, | |||
723 | 690 | ||
724 | dev_info(&client->dev, "%s programmable led chip found\n", id->name); | 691 | dev_info(&client->dev, "%s programmable led chip found\n", id->name); |
725 | 692 | ||
726 | ret = lp5521_configure(client, lp5521_engine_group); | 693 | ret = lp5521_configure(client); |
727 | if (ret < 0) { | 694 | if (ret < 0) { |
728 | dev_err(&client->dev, "error configuring chip\n"); | 695 | dev_err(&client->dev, "error configuring chip\n"); |
729 | goto fail2; | 696 | goto fail2; |
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 0cc4ead2fd8b..d0c4068ecddd 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c | |||
@@ -105,7 +105,6 @@ | |||
105 | #define SHIFT_MASK(id) (((id) - 1) * 2) | 105 | #define SHIFT_MASK(id) (((id) - 1) * 2) |
106 | 106 | ||
107 | struct lp5523_engine { | 107 | struct lp5523_engine { |
108 | const struct attribute_group *attributes; | ||
109 | int id; | 108 | int id; |
110 | u8 mode; | 109 | u8 mode; |
111 | u8 prog_page; | 110 | u8 prog_page; |
@@ -403,14 +402,23 @@ static ssize_t store_engine_leds(struct device *dev, | |||
403 | struct i2c_client *client = to_i2c_client(dev); | 402 | struct i2c_client *client = to_i2c_client(dev); |
404 | struct lp5523_chip *chip = i2c_get_clientdata(client); | 403 | struct lp5523_chip *chip = i2c_get_clientdata(client); |
405 | u16 mux = 0; | 404 | u16 mux = 0; |
405 | ssize_t ret; | ||
406 | 406 | ||
407 | if (lp5523_mux_parse(buf, &mux, len)) | 407 | if (lp5523_mux_parse(buf, &mux, len)) |
408 | return -EINVAL; | 408 | return -EINVAL; |
409 | 409 | ||
410 | mutex_lock(&chip->lock); | ||
411 | ret = -EINVAL; | ||
412 | if (chip->engines[nr - 1].mode != LP5523_CMD_LOAD) | ||
413 | goto leave; | ||
414 | |||
410 | if (lp5523_load_mux(&chip->engines[nr - 1], mux)) | 415 | if (lp5523_load_mux(&chip->engines[nr - 1], mux)) |
411 | return -EINVAL; | 416 | goto leave; |
412 | 417 | ||
413 | return len; | 418 | ret = len; |
419 | leave: | ||
420 | mutex_unlock(&chip->lock); | ||
421 | return ret; | ||
414 | } | 422 | } |
415 | 423 | ||
416 | #define store_leds(nr) \ | 424 | #define store_leds(nr) \ |
@@ -556,7 +564,11 @@ static int lp5523_do_store_load(struct lp5523_engine *engine, | |||
556 | 564 | ||
557 | mutex_lock(&chip->lock); | 565 | mutex_lock(&chip->lock); |
558 | 566 | ||
559 | ret = lp5523_load_program(engine, pattern); | 567 | if (engine->mode == LP5523_CMD_LOAD) |
568 | ret = lp5523_load_program(engine, pattern); | ||
569 | else | ||
570 | ret = -EINVAL; | ||
571 | |||
560 | mutex_unlock(&chip->lock); | 572 | mutex_unlock(&chip->lock); |
561 | 573 | ||
562 | if (ret) { | 574 | if (ret) { |
@@ -737,37 +749,18 @@ static struct attribute *lp5523_attributes[] = { | |||
737 | &dev_attr_engine2_mode.attr, | 749 | &dev_attr_engine2_mode.attr, |
738 | &dev_attr_engine3_mode.attr, | 750 | &dev_attr_engine3_mode.attr, |
739 | &dev_attr_selftest.attr, | 751 | &dev_attr_selftest.attr, |
740 | NULL | ||
741 | }; | ||
742 | |||
743 | static struct attribute *lp5523_engine1_attributes[] = { | ||
744 | &dev_attr_engine1_load.attr, | 752 | &dev_attr_engine1_load.attr, |
745 | &dev_attr_engine1_leds.attr, | 753 | &dev_attr_engine1_leds.attr, |
746 | NULL | ||
747 | }; | ||
748 | |||
749 | static struct attribute *lp5523_engine2_attributes[] = { | ||
750 | &dev_attr_engine2_load.attr, | 754 | &dev_attr_engine2_load.attr, |
751 | &dev_attr_engine2_leds.attr, | 755 | &dev_attr_engine2_leds.attr, |
752 | NULL | ||
753 | }; | ||
754 | |||
755 | static struct attribute *lp5523_engine3_attributes[] = { | ||
756 | &dev_attr_engine3_load.attr, | 756 | &dev_attr_engine3_load.attr, |
757 | &dev_attr_engine3_leds.attr, | 757 | &dev_attr_engine3_leds.attr, |
758 | NULL | ||
759 | }; | 758 | }; |
760 | 759 | ||
761 | static const struct attribute_group lp5523_group = { | 760 | static const struct attribute_group lp5523_group = { |
762 | .attrs = lp5523_attributes, | 761 | .attrs = lp5523_attributes, |
763 | }; | 762 | }; |
764 | 763 | ||
765 | static const struct attribute_group lp5523_engine_group[] = { | ||
766 | {.attrs = lp5523_engine1_attributes }, | ||
767 | {.attrs = lp5523_engine2_attributes }, | ||
768 | {.attrs = lp5523_engine3_attributes }, | ||
769 | }; | ||
770 | |||
771 | static int lp5523_register_sysfs(struct i2c_client *client) | 764 | static int lp5523_register_sysfs(struct i2c_client *client) |
772 | { | 765 | { |
773 | struct device *dev = &client->dev; | 766 | struct device *dev = &client->dev; |
@@ -788,10 +781,6 @@ static void lp5523_unregister_sysfs(struct i2c_client *client) | |||
788 | 781 | ||
789 | sysfs_remove_group(&dev->kobj, &lp5523_group); | 782 | sysfs_remove_group(&dev->kobj, &lp5523_group); |
790 | 783 | ||
791 | for (i = 0; i < ARRAY_SIZE(chip->engines); i++) | ||
792 | if (chip->engines[i].mode == LP5523_CMD_LOAD) | ||
793 | sysfs_remove_group(&dev->kobj, &lp5523_engine_group[i]); | ||
794 | |||
795 | for (i = 0; i < chip->num_leds; i++) | 784 | for (i = 0; i < chip->num_leds; i++) |
796 | sysfs_remove_group(&chip->leds[i].cdev.dev->kobj, | 785 | sysfs_remove_group(&chip->leds[i].cdev.dev->kobj, |
797 | &lp5523_led_attribute_group); | 786 | &lp5523_led_attribute_group); |
@@ -802,10 +791,6 @@ static void lp5523_unregister_sysfs(struct i2c_client *client) | |||
802 | /*--------------------------------------------------------------*/ | 791 | /*--------------------------------------------------------------*/ |
803 | static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode) | 792 | static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode) |
804 | { | 793 | { |
805 | /* engine to chip */ | ||
806 | struct lp5523_chip *chip = engine_to_lp5523(engine); | ||
807 | struct i2c_client *client = chip->client; | ||
808 | struct device *dev = &client->dev; | ||
809 | int ret = 0; | 794 | int ret = 0; |
810 | 795 | ||
811 | /* if in that mode already do nothing, except for run */ | 796 | /* if in that mode already do nothing, except for run */ |
@@ -817,18 +802,10 @@ static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode) | |||
817 | } else if (mode == LP5523_CMD_LOAD) { | 802 | } else if (mode == LP5523_CMD_LOAD) { |
818 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); | 803 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); |
819 | lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); | 804 | lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); |
820 | |||
821 | ret = sysfs_create_group(&dev->kobj, engine->attributes); | ||
822 | if (ret) | ||
823 | return ret; | ||
824 | } else if (mode == LP5523_CMD_DISABLED) { | 805 | } else if (mode == LP5523_CMD_DISABLED) { |
825 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); | 806 | lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); |
826 | } | 807 | } |
827 | 808 | ||
828 | /* remove load attribute from sysfs if not in load mode */ | ||
829 | if (engine->mode == LP5523_CMD_LOAD && mode != LP5523_CMD_LOAD) | ||
830 | sysfs_remove_group(&dev->kobj, engine->attributes); | ||
831 | |||
832 | engine->mode = mode; | 809 | engine->mode = mode; |
833 | 810 | ||
834 | return ret; | 811 | return ret; |
@@ -845,7 +822,6 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id) | |||
845 | engine->engine_mask = LP5523_ENG_MASK_BASE >> SHIFT_MASK(id); | 822 | engine->engine_mask = LP5523_ENG_MASK_BASE >> SHIFT_MASK(id); |
846 | engine->prog_page = id - 1; | 823 | engine->prog_page = id - 1; |
847 | engine->mux_page = id + 2; | 824 | engine->mux_page = id + 2; |
848 | engine->attributes = &lp5523_engine_group[id - 1]; | ||
849 | 825 | ||
850 | return 0; | 826 | return 0; |
851 | } | 827 | } |
@@ -870,7 +846,8 @@ static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev, | |||
870 | return -EINVAL; | 846 | return -EINVAL; |
871 | } | 847 | } |
872 | 848 | ||
873 | snprintf(name, 32, "lp5523:channel%d", chan); | 849 | snprintf(name, sizeof(name), "%s:channel%d", |
850 | pdata->label ?: "lp5523", chan); | ||
874 | 851 | ||
875 | led->cdev.name = name; | 852 | led->cdev.name = name; |
876 | led->cdev.brightness_set = lp5523_set_brightness; | 853 | led->cdev.brightness_set = lp5523_set_brightness; |
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 43d08756d823..afac338d5025 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c | |||
@@ -200,6 +200,32 @@ static void pca9532_led_work(struct work_struct *work) | |||
200 | pca9532_setled(led); | 200 | pca9532_setled(led); |
201 | } | 201 | } |
202 | 202 | ||
203 | static void pca9532_destroy_devices(struct pca9532_data *data, int n_devs) | ||
204 | { | ||
205 | int i = n_devs; | ||
206 | |||
207 | if (!data) | ||
208 | return; | ||
209 | |||
210 | while (--i >= 0) { | ||
211 | switch (data->leds[i].type) { | ||
212 | case PCA9532_TYPE_NONE: | ||
213 | break; | ||
214 | case PCA9532_TYPE_LED: | ||
215 | led_classdev_unregister(&data->leds[i].ldev); | ||
216 | cancel_work_sync(&data->leds[i].work); | ||
217 | break; | ||
218 | case PCA9532_TYPE_N2100_BEEP: | ||
219 | if (data->idev != NULL) { | ||
220 | input_unregister_device(data->idev); | ||
221 | cancel_work_sync(&data->work); | ||
222 | data->idev = NULL; | ||
223 | } | ||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | |||
203 | static int pca9532_configure(struct i2c_client *client, | 229 | static int pca9532_configure(struct i2c_client *client, |
204 | struct pca9532_data *data, struct pca9532_platform_data *pdata) | 230 | struct pca9532_data *data, struct pca9532_platform_data *pdata) |
205 | { | 231 | { |
@@ -274,25 +300,7 @@ static int pca9532_configure(struct i2c_client *client, | |||
274 | return 0; | 300 | return 0; |
275 | 301 | ||
276 | exit: | 302 | exit: |
277 | if (i > 0) | 303 | pca9532_destroy_devices(data, i); |
278 | for (i = i - 1; i >= 0; i--) | ||
279 | switch (data->leds[i].type) { | ||
280 | case PCA9532_TYPE_NONE: | ||
281 | break; | ||
282 | case PCA9532_TYPE_LED: | ||
283 | led_classdev_unregister(&data->leds[i].ldev); | ||
284 | cancel_work_sync(&data->leds[i].work); | ||
285 | break; | ||
286 | case PCA9532_TYPE_N2100_BEEP: | ||
287 | if (data->idev != NULL) { | ||
288 | input_unregister_device(data->idev); | ||
289 | input_free_device(data->idev); | ||
290 | cancel_work_sync(&data->work); | ||
291 | data->idev = NULL; | ||
292 | } | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | return err; | 304 | return err; |
297 | } | 305 | } |
298 | 306 | ||
@@ -329,25 +337,7 @@ static int pca9532_probe(struct i2c_client *client, | |||
329 | static int pca9532_remove(struct i2c_client *client) | 337 | static int pca9532_remove(struct i2c_client *client) |
330 | { | 338 | { |
331 | struct pca9532_data *data = i2c_get_clientdata(client); | 339 | struct pca9532_data *data = i2c_get_clientdata(client); |
332 | int i; | 340 | pca9532_destroy_devices(data, 16); |
333 | for (i = 0; i < 16; i++) | ||
334 | switch (data->leds[i].type) { | ||
335 | case PCA9532_TYPE_NONE: | ||
336 | break; | ||
337 | case PCA9532_TYPE_LED: | ||
338 | led_classdev_unregister(&data->leds[i].ldev); | ||
339 | cancel_work_sync(&data->leds[i].work); | ||
340 | break; | ||
341 | case PCA9532_TYPE_N2100_BEEP: | ||
342 | if (data->idev != NULL) { | ||
343 | input_unregister_device(data->idev); | ||
344 | input_free_device(data->idev); | ||
345 | cancel_work_sync(&data->work); | ||
346 | data->idev = NULL; | ||
347 | } | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | kfree(data); | 341 | kfree(data); |
352 | return 0; | 342 | return 0; |
353 | } | 343 | } |
diff --git a/drivers/leds/ledtrig-backlight.c b/drivers/leds/ledtrig-backlight.c index f948e57bd9b8..2b513a2ad7de 100644 --- a/drivers/leds/ledtrig-backlight.c +++ b/drivers/leds/ledtrig-backlight.c | |||
@@ -26,6 +26,7 @@ struct bl_trig_notifier { | |||
26 | int brightness; | 26 | int brightness; |
27 | int old_status; | 27 | int old_status; |
28 | struct notifier_block notifier; | 28 | struct notifier_block notifier; |
29 | unsigned invert; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | static int fb_notifier_callback(struct notifier_block *p, | 32 | static int fb_notifier_callback(struct notifier_block *p, |
@@ -36,23 +37,64 @@ static int fb_notifier_callback(struct notifier_block *p, | |||
36 | struct led_classdev *led = n->led; | 37 | struct led_classdev *led = n->led; |
37 | struct fb_event *fb_event = data; | 38 | struct fb_event *fb_event = data; |
38 | int *blank = fb_event->data; | 39 | int *blank = fb_event->data; |
40 | int new_status = *blank ? BLANK : UNBLANK; | ||
39 | 41 | ||
40 | switch (event) { | 42 | switch (event) { |
41 | case FB_EVENT_BLANK : | 43 | case FB_EVENT_BLANK : |
42 | if (*blank && n->old_status == UNBLANK) { | 44 | if (new_status == n->old_status) |
45 | break; | ||
46 | |||
47 | if ((n->old_status == UNBLANK) ^ n->invert) { | ||
43 | n->brightness = led->brightness; | 48 | n->brightness = led->brightness; |
44 | led_set_brightness(led, LED_OFF); | 49 | led_set_brightness(led, LED_OFF); |
45 | n->old_status = BLANK; | 50 | } else { |
46 | } else if (!*blank && n->old_status == BLANK) { | ||
47 | led_set_brightness(led, n->brightness); | 51 | led_set_brightness(led, n->brightness); |
48 | n->old_status = UNBLANK; | ||
49 | } | 52 | } |
53 | |||
54 | n->old_status = new_status; | ||
55 | |||
50 | break; | 56 | break; |
51 | } | 57 | } |
52 | 58 | ||
53 | return 0; | 59 | return 0; |
54 | } | 60 | } |
55 | 61 | ||
62 | static ssize_t bl_trig_invert_show(struct device *dev, | ||
63 | struct device_attribute *attr, char *buf) | ||
64 | { | ||
65 | struct led_classdev *led = dev_get_drvdata(dev); | ||
66 | struct bl_trig_notifier *n = led->trigger_data; | ||
67 | |||
68 | return sprintf(buf, "%u\n", n->invert); | ||
69 | } | ||
70 | |||
71 | static ssize_t bl_trig_invert_store(struct device *dev, | ||
72 | struct device_attribute *attr, const char *buf, size_t num) | ||
73 | { | ||
74 | struct led_classdev *led = dev_get_drvdata(dev); | ||
75 | struct bl_trig_notifier *n = led->trigger_data; | ||
76 | unsigned long invert; | ||
77 | int ret; | ||
78 | |||
79 | ret = strict_strtoul(buf, 10, &invert); | ||
80 | if (ret < 0) | ||
81 | return ret; | ||
82 | |||
83 | if (invert > 1) | ||
84 | return -EINVAL; | ||
85 | |||
86 | n->invert = invert; | ||
87 | |||
88 | /* After inverting, we need to update the LED. */ | ||
89 | if ((n->old_status == BLANK) ^ n->invert) | ||
90 | led_set_brightness(led, LED_OFF); | ||
91 | else | ||
92 | led_set_brightness(led, n->brightness); | ||
93 | |||
94 | return num; | ||
95 | } | ||
96 | static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store); | ||
97 | |||
56 | static void bl_trig_activate(struct led_classdev *led) | 98 | static void bl_trig_activate(struct led_classdev *led) |
57 | { | 99 | { |
58 | int ret; | 100 | int ret; |
@@ -66,6 +108,10 @@ static void bl_trig_activate(struct led_classdev *led) | |||
66 | return; | 108 | return; |
67 | } | 109 | } |
68 | 110 | ||
111 | ret = device_create_file(led->dev, &dev_attr_inverted); | ||
112 | if (ret) | ||
113 | goto err_invert; | ||
114 | |||
69 | n->led = led; | 115 | n->led = led; |
70 | n->brightness = led->brightness; | 116 | n->brightness = led->brightness; |
71 | n->old_status = UNBLANK; | 117 | n->old_status = UNBLANK; |
@@ -74,6 +120,12 @@ static void bl_trig_activate(struct led_classdev *led) | |||
74 | ret = fb_register_client(&n->notifier); | 120 | ret = fb_register_client(&n->notifier); |
75 | if (ret) | 121 | if (ret) |
76 | dev_err(led->dev, "unable to register backlight trigger\n"); | 122 | dev_err(led->dev, "unable to register backlight trigger\n"); |
123 | |||
124 | return; | ||
125 | |||
126 | err_invert: | ||
127 | led->trigger_data = NULL; | ||
128 | kfree(n); | ||
77 | } | 129 | } |
78 | 130 | ||
79 | static void bl_trig_deactivate(struct led_classdev *led) | 131 | static void bl_trig_deactivate(struct led_classdev *led) |
@@ -82,6 +134,7 @@ static void bl_trig_deactivate(struct led_classdev *led) | |||
82 | (struct bl_trig_notifier *) led->trigger_data; | 134 | (struct bl_trig_notifier *) led->trigger_data; |
83 | 135 | ||
84 | if (n) { | 136 | if (n) { |
137 | device_remove_file(led->dev, &dev_attr_inverted); | ||
85 | fb_unregister_client(&n->notifier); | 138 | fb_unregister_client(&n->notifier); |
86 | kfree(n); | 139 | kfree(n); |
87 | } | 140 | } |
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c index 1cec02f6c431..ade1e656bfb2 100644 --- a/drivers/macintosh/via-pmu-backlight.c +++ b/drivers/macintosh/via-pmu-backlight.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #define MAX_PMU_LEVEL 0xFF | 16 | #define MAX_PMU_LEVEL 0xFF |
17 | 17 | ||
18 | static struct backlight_ops pmu_backlight_data; | 18 | static const struct backlight_ops pmu_backlight_data; |
19 | static DEFINE_SPINLOCK(pmu_backlight_lock); | 19 | static DEFINE_SPINLOCK(pmu_backlight_lock); |
20 | static int sleeping, uses_pmu_bl; | 20 | static int sleeping, uses_pmu_bl; |
21 | static u8 bl_curve[FB_BACKLIGHT_LEVELS]; | 21 | static u8 bl_curve[FB_BACKLIGHT_LEVELS]; |
@@ -115,7 +115,7 @@ static int pmu_backlight_get_brightness(struct backlight_device *bd) | |||
115 | return bd->props.brightness; | 115 | return bd->props.brightness; |
116 | } | 116 | } |
117 | 117 | ||
118 | static struct backlight_ops pmu_backlight_data = { | 118 | static const struct backlight_ops pmu_backlight_data = { |
119 | .get_brightness = pmu_backlight_get_brightness, | 119 | .get_brightness = pmu_backlight_get_brightness, |
120 | .update_status = pmu_backlight_update_status, | 120 | .update_status = pmu_backlight_update_status, |
121 | 121 | ||
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index cd29c8248386..8b021eb0d48c 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -2257,7 +2257,7 @@ static int pmu_sleep_valid(suspend_state_t state) | |||
2257 | && (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0); | 2257 | && (pmac_call_feature(PMAC_FTR_SLEEP_STATE, NULL, 0, -1) >= 0); |
2258 | } | 2258 | } |
2259 | 2259 | ||
2260 | static struct platform_suspend_ops pmu_pm_ops = { | 2260 | static const struct platform_suspend_ops pmu_pm_ops = { |
2261 | .enter = powerbook_sleep, | 2261 | .enter = powerbook_sleep, |
2262 | .valid = pmu_sleep_valid, | 2262 | .valid = pmu_sleep_valid, |
2263 | }; | 2263 | }; |
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h index 2c00980acfcb..7e40035028d2 100644 --- a/drivers/media/video/cx18/cx23418.h +++ b/drivers/media/video/cx18/cx23418.h | |||
@@ -177,7 +177,7 @@ | |||
177 | IN[0] - Task handle. | 177 | IN[0] - Task handle. |
178 | IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only, | 178 | IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only, |
179 | 3 = 2D H/V separable, 4 = 2D symmetric non-separable | 179 | 3 = 2D H/V separable, 4 = 2D symmetric non-separable |
180 | IN[2] - chroma type: 0 - diable, 1 = 1D horizontal | 180 | IN[2] - chroma type: 0 - disable, 1 = 1D horizontal |
181 | ReturnCode - One of the ERR_CAPTURE_... */ | 181 | ReturnCode - One of the ERR_CAPTURE_... */ |
182 | #define CX18_CPU_SET_SPATIAL_FILTER_TYPE (CPU_CMD_MASK_CAPTURE | 0x000C) | 182 | #define CX18_CPU_SET_SPATIAL_FILTER_TYPE (CPU_CMD_MASK_CAPTURE | 0x000C) |
183 | 183 | ||
diff --git a/drivers/media/video/cx25840/cx25840-ir.c b/drivers/media/video/cx25840/cx25840-ir.c index 627926f6bde8..7eb79af28aa3 100644 --- a/drivers/media/video/cx25840/cx25840-ir.c +++ b/drivers/media/video/cx25840/cx25840-ir.c | |||
@@ -261,7 +261,7 @@ static u16 ns_to_pulse_width_count(u32 ns, u16 divider) | |||
261 | u32 rem; | 261 | u32 rem; |
262 | 262 | ||
263 | /* | 263 | /* |
264 | * The 2 lsb's of the pulse width timer count are not accessable, hence | 264 | * The 2 lsb's of the pulse width timer count are not accessible, hence |
265 | * the (1 << 2) | 265 | * the (1 << 2) |
266 | */ | 266 | */ |
267 | n = ((u64) ns) * CX25840_IR_REFCLK_FREQ / 1000000; /* millicycles */ | 267 | n = ((u64) ns) * CX25840_IR_REFCLK_FREQ / 1000000; /* millicycles */ |
diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h index 188841b476e0..ebd5c4338ebb 100644 --- a/drivers/media/video/davinci/vpif.h +++ b/drivers/media/video/davinci/vpif.h | |||
@@ -33,7 +33,7 @@ extern spinlock_t vpif_lock; | |||
33 | #define regr(reg) readl((reg) + vpif_base) | 33 | #define regr(reg) readl((reg) + vpif_base) |
34 | #define regw(value, reg) writel(value, (reg + vpif_base)) | 34 | #define regw(value, reg) writel(value, (reg + vpif_base)) |
35 | 35 | ||
36 | /* Register Addresss Offsets */ | 36 | /* Register Address Offsets */ |
37 | #define VPIF_PID (0x0000) | 37 | #define VPIF_PID (0x0000) |
38 | #define VPIF_CH0_CTRL (0x0004) | 38 | #define VPIF_CH0_CTRL (0x0004) |
39 | #define VPIF_CH1_CTRL (0x0008) | 39 | #define VPIF_CH1_CTRL (0x0008) |
diff --git a/drivers/media/video/davinci/vpss.c b/drivers/media/video/davinci/vpss.c index 7918680917d0..3e5cf27ec2b2 100644 --- a/drivers/media/video/davinci/vpss.c +++ b/drivers/media/video/davinci/vpss.c | |||
@@ -85,7 +85,7 @@ enum vpss_platform_type { | |||
85 | /* | 85 | /* |
86 | * vpss operations. Depends on platform. Not all functions are available | 86 | * vpss operations. Depends on platform. Not all functions are available |
87 | * on all platforms. The api, first check if a functio is available before | 87 | * on all platforms. The api, first check if a functio is available before |
88 | * invoking it. In the probe, the function ptrs are intialized based on | 88 | * invoking it. In the probe, the function ptrs are initialized based on |
89 | * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc. | 89 | * vpss name. vpss name can be "dm355_vpss", "dm644x_vpss" etc. |
90 | */ | 90 | */ |
91 | struct vpss_hw_ops { | 91 | struct vpss_hw_ops { |
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 83de97ad971e..029a4babfd61 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -1286,7 +1286,7 @@ static int omap_vout_release(struct file *file) | |||
1286 | videobuf_mmap_free(q); | 1286 | videobuf_mmap_free(q); |
1287 | 1287 | ||
1288 | /* Even if apply changes fails we should continue | 1288 | /* Even if apply changes fails we should continue |
1289 | freeing allocated memeory */ | 1289 | freeing allocated memory */ |
1290 | if (vout->streaming) { | 1290 | if (vout->streaming) { |
1291 | u32 mask = 0; | 1291 | u32 mask = 0; |
1292 | 1292 | ||
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c index d6bf3f82cc34..58af67f2278b 100644 --- a/drivers/media/video/saa7164/saa7164-core.c +++ b/drivers/media/video/saa7164/saa7164-core.c | |||
@@ -655,8 +655,8 @@ static irqreturn_t saa7164_irq(int irq, void *dev_id) | |||
655 | goto out; | 655 | goto out; |
656 | } | 656 | } |
657 | 657 | ||
658 | /* Check that the hardware is accessable. If the status bytes are | 658 | /* Check that the hardware is accessible. If the status bytes are |
659 | * 0xFF then the device is not accessable, the the IRQ belongs | 659 | * 0xFF then the device is not accessible, the the IRQ belongs |
660 | * to another driver. | 660 | * to another driver. |
661 | * 4 x u32 interrupt registers. | 661 | * 4 x u32 interrupt registers. |
662 | */ | 662 | */ |
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h index 494957b10bac..7f38549715b6 100644 --- a/drivers/media/video/sn9c102/sn9c102_sensor.h +++ b/drivers/media/video/sn9c102/sn9c102_sensor.h | |||
@@ -147,7 +147,7 @@ enum sn9c102_i2c_interface { | |||
147 | 147 | ||
148 | struct sn9c102_sensor { | 148 | struct sn9c102_sensor { |
149 | char name[32], /* sensor name */ | 149 | char name[32], /* sensor name */ |
150 | maintainer[64]; /* name of the mantainer <email> */ | 150 | maintainer[64]; /* name of the maintainer <email> */ |
151 | 151 | ||
152 | enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */ | 152 | enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */ |
153 | 153 | ||
diff --git a/drivers/media/video/tvp7002.c b/drivers/media/video/tvp7002.c index e63b40f5a706..c799e4eb6fcd 100644 --- a/drivers/media/video/tvp7002.c +++ b/drivers/media/video/tvp7002.c | |||
@@ -789,7 +789,7 @@ static int tvp7002_query_dv_preset(struct v4l2_subdev *sd, | |||
789 | * Get the value of a TVP7002 decoder device register. | 789 | * Get the value of a TVP7002 decoder device register. |
790 | * Returns zero when successful, -EINVAL if register read fails or | 790 | * Returns zero when successful, -EINVAL if register read fails or |
791 | * access to I2C client fails, -EPERM if the call is not allowed | 791 | * access to I2C client fails, -EPERM if the call is not allowed |
792 | * by diabled CAP_SYS_ADMIN. | 792 | * by disabled CAP_SYS_ADMIN. |
793 | */ | 793 | */ |
794 | static int tvp7002_g_register(struct v4l2_subdev *sd, | 794 | static int tvp7002_g_register(struct v4l2_subdev *sd, |
795 | struct v4l2_dbg_register *reg) | 795 | struct v4l2_dbg_register *reg) |
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index e25aca5759fb..2f973cd56408 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c | |||
@@ -13,14 +13,12 @@ | |||
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/pci.h> | ||
17 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
18 | #include <linux/videodev2.h> | 17 | #include <linux/videodev2.h> |
19 | #include <media/v4l2-device.h> | 18 | #include <media/v4l2-device.h> |
20 | #include <media/v4l2-ioctl.h> | 19 | #include <media/v4l2-ioctl.h> |
21 | #include <media/v4l2-chip-ident.h> | 20 | #include <media/v4l2-chip-ident.h> |
22 | #include <media/videobuf-dma-sg.h> | 21 | #include <media/videobuf-dma-sg.h> |
23 | #include <linux/device.h> | ||
24 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
25 | #include <linux/dma-mapping.h> | 23 | #include <linux/dma-mapping.h> |
26 | #include <linux/pm_qos_params.h> | 24 | #include <linux/pm_qos_params.h> |
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index c00fe8253c51..e9a3eab7b0cf 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c | |||
@@ -465,6 +465,7 @@ static void memstick_check(struct work_struct *work) | |||
465 | if (!host->card) { | 465 | if (!host->card) { |
466 | host->card = card; | 466 | host->card = card; |
467 | if (device_register(&card->dev)) { | 467 | if (device_register(&card->dev)) { |
468 | put_device(&card->dev); | ||
468 | kfree(host->card); | 469 | kfree(host->card); |
469 | host->card = NULL; | 470 | host->card = NULL; |
470 | } | 471 | } |
@@ -510,14 +511,18 @@ int memstick_add_host(struct memstick_host *host) | |||
510 | { | 511 | { |
511 | int rc; | 512 | int rc; |
512 | 513 | ||
513 | if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL)) | 514 | while (1) { |
514 | return -ENOMEM; | 515 | if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL)) |
516 | return -ENOMEM; | ||
515 | 517 | ||
516 | spin_lock(&memstick_host_lock); | 518 | spin_lock(&memstick_host_lock); |
517 | rc = idr_get_new(&memstick_host_idr, host, &host->id); | 519 | rc = idr_get_new(&memstick_host_idr, host, &host->id); |
518 | spin_unlock(&memstick_host_lock); | 520 | spin_unlock(&memstick_host_lock); |
519 | if (rc) | 521 | if (!rc) |
520 | return rc; | 522 | break; |
523 | else if (rc != -EAGAIN) | ||
524 | return rc; | ||
525 | } | ||
521 | 526 | ||
522 | dev_set_name(&host->dev, "memstick%u", host->id); | 527 | dev_set_name(&host->dev, "memstick%u", host->id); |
523 | 528 | ||
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 02362eccc588..57b42bfc7d23 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #define DRIVER_NAME "mspro_block" | 24 | #define DRIVER_NAME "mspro_block" |
25 | 25 | ||
26 | static DEFINE_MUTEX(mspro_block_mutex); | ||
27 | static int major; | 26 | static int major; |
28 | module_param(major, int, 0644); | 27 | module_param(major, int, 0644); |
29 | 28 | ||
@@ -160,6 +159,13 @@ struct mspro_block_data { | |||
160 | int (*mrq_handler)(struct memstick_dev *card, | 159 | int (*mrq_handler)(struct memstick_dev *card, |
161 | struct memstick_request **mrq); | 160 | struct memstick_request **mrq); |
162 | 161 | ||
162 | |||
163 | /* Default request setup function for data access method preferred by | ||
164 | * this host instance. | ||
165 | */ | ||
166 | void (*setup_transfer)(struct memstick_dev *card, | ||
167 | u64 offset, size_t length); | ||
168 | |||
163 | struct attribute_group attr_group; | 169 | struct attribute_group attr_group; |
164 | 170 | ||
165 | struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; | 171 | struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS]; |
@@ -181,7 +187,6 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) | |||
181 | struct mspro_block_data *msb = disk->private_data; | 187 | struct mspro_block_data *msb = disk->private_data; |
182 | int rc = -ENXIO; | 188 | int rc = -ENXIO; |
183 | 189 | ||
184 | mutex_lock(&mspro_block_mutex); | ||
185 | mutex_lock(&mspro_block_disk_lock); | 190 | mutex_lock(&mspro_block_disk_lock); |
186 | 191 | ||
187 | if (msb && msb->card) { | 192 | if (msb && msb->card) { |
@@ -193,7 +198,6 @@ static int mspro_block_bd_open(struct block_device *bdev, fmode_t mode) | |||
193 | } | 198 | } |
194 | 199 | ||
195 | mutex_unlock(&mspro_block_disk_lock); | 200 | mutex_unlock(&mspro_block_disk_lock); |
196 | mutex_unlock(&mspro_block_mutex); | ||
197 | 201 | ||
198 | return rc; | 202 | return rc; |
199 | } | 203 | } |
@@ -225,11 +229,7 @@ static int mspro_block_disk_release(struct gendisk *disk) | |||
225 | 229 | ||
226 | static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode) | 230 | static int mspro_block_bd_release(struct gendisk *disk, fmode_t mode) |
227 | { | 231 | { |
228 | int ret; | 232 | return mspro_block_disk_release(disk); |
229 | mutex_lock(&mspro_block_mutex); | ||
230 | ret = mspro_block_disk_release(disk); | ||
231 | mutex_unlock(&mspro_block_mutex); | ||
232 | return ret; | ||
233 | } | 233 | } |
234 | 234 | ||
235 | static int mspro_block_bd_getgeo(struct block_device *bdev, | 235 | static int mspro_block_bd_getgeo(struct block_device *bdev, |
@@ -663,14 +663,43 @@ has_int_reg: | |||
663 | } | 663 | } |
664 | } | 664 | } |
665 | 665 | ||
666 | /*** Transfer setup functions for different access methods. ***/ | ||
667 | |||
668 | /** Setup data transfer request for SET_CMD TPC with arguments in card | ||
669 | * registers. | ||
670 | * | ||
671 | * @card Current media instance | ||
672 | * @offset Target data offset in bytes | ||
673 | * @length Required transfer length in bytes. | ||
674 | */ | ||
675 | static void h_mspro_block_setup_cmd(struct memstick_dev *card, u64 offset, | ||
676 | size_t length) | ||
677 | { | ||
678 | struct mspro_block_data *msb = memstick_get_drvdata(card); | ||
679 | struct mspro_param_register param = { | ||
680 | .system = msb->system, | ||
681 | .data_count = cpu_to_be16((uint16_t)(length / msb->page_size)), | ||
682 | /* ISO C90 warning precludes direct initialization for now. */ | ||
683 | .data_address = 0, | ||
684 | .tpc_param = 0 | ||
685 | }; | ||
686 | |||
687 | do_div(offset, msb->page_size); | ||
688 | param.data_address = cpu_to_be32((uint32_t)offset); | ||
689 | |||
690 | card->next_request = h_mspro_block_req_init; | ||
691 | msb->mrq_handler = h_mspro_block_transfer_data; | ||
692 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, | ||
693 | ¶m, sizeof(param)); | ||
694 | } | ||
695 | |||
666 | /*** Data transfer ***/ | 696 | /*** Data transfer ***/ |
667 | 697 | ||
668 | static int mspro_block_issue_req(struct memstick_dev *card, int chunk) | 698 | static int mspro_block_issue_req(struct memstick_dev *card, int chunk) |
669 | { | 699 | { |
670 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 700 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
671 | sector_t t_sec; | 701 | u64 t_off; |
672 | unsigned int count; | 702 | unsigned int count; |
673 | struct mspro_param_register param; | ||
674 | 703 | ||
675 | try_again: | 704 | try_again: |
676 | while (chunk) { | 705 | while (chunk) { |
@@ -685,30 +714,17 @@ try_again: | |||
685 | continue; | 714 | continue; |
686 | } | 715 | } |
687 | 716 | ||
688 | t_sec = blk_rq_pos(msb->block_req) << 9; | 717 | t_off = blk_rq_pos(msb->block_req); |
689 | sector_div(t_sec, msb->page_size); | 718 | t_off <<= 9; |
690 | |||
691 | count = blk_rq_bytes(msb->block_req); | 719 | count = blk_rq_bytes(msb->block_req); |
692 | count /= msb->page_size; | ||
693 | 720 | ||
694 | param.system = msb->system; | 721 | msb->setup_transfer(card, t_off, count); |
695 | param.data_count = cpu_to_be16(count); | ||
696 | param.data_address = cpu_to_be32((uint32_t)t_sec); | ||
697 | param.tpc_param = 0; | ||
698 | 722 | ||
699 | msb->data_dir = rq_data_dir(msb->block_req); | 723 | msb->data_dir = rq_data_dir(msb->block_req); |
700 | msb->transfer_cmd = msb->data_dir == READ | 724 | msb->transfer_cmd = msb->data_dir == READ |
701 | ? MSPRO_CMD_READ_DATA | 725 | ? MSPRO_CMD_READ_DATA |
702 | : MSPRO_CMD_WRITE_DATA; | 726 | : MSPRO_CMD_WRITE_DATA; |
703 | 727 | ||
704 | dev_dbg(&card->dev, "data transfer: cmd %x, " | ||
705 | "lba %x, count %x\n", msb->transfer_cmd, | ||
706 | be32_to_cpu(param.data_address), count); | ||
707 | |||
708 | card->next_request = h_mspro_block_req_init; | ||
709 | msb->mrq_handler = h_mspro_block_transfer_data; | ||
710 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, | ||
711 | ¶m, sizeof(param)); | ||
712 | memstick_new_req(card->host); | 728 | memstick_new_req(card->host); |
713 | return 0; | 729 | return 0; |
714 | } | 730 | } |
@@ -963,18 +979,16 @@ try_again: | |||
963 | static int mspro_block_read_attributes(struct memstick_dev *card) | 979 | static int mspro_block_read_attributes(struct memstick_dev *card) |
964 | { | 980 | { |
965 | struct mspro_block_data *msb = memstick_get_drvdata(card); | 981 | struct mspro_block_data *msb = memstick_get_drvdata(card); |
966 | struct mspro_param_register param = { | ||
967 | .system = msb->system, | ||
968 | .data_count = cpu_to_be16(1), | ||
969 | .data_address = 0, | ||
970 | .tpc_param = 0 | ||
971 | }; | ||
972 | struct mspro_attribute *attr = NULL; | 982 | struct mspro_attribute *attr = NULL; |
973 | struct mspro_sys_attr *s_attr = NULL; | 983 | struct mspro_sys_attr *s_attr = NULL; |
974 | unsigned char *buffer = NULL; | 984 | unsigned char *buffer = NULL; |
975 | int cnt, rc, attr_count; | 985 | int cnt, rc, attr_count; |
976 | unsigned int addr; | 986 | /* While normally physical device offsets, represented here by |
977 | unsigned short page_count; | 987 | * attr_offset and attr_len will be of large numeric types, we can be |
988 | * sure, that attributes are close enough to the beginning of the | ||
989 | * device, to save ourselves some trouble. | ||
990 | */ | ||
991 | unsigned int addr, attr_offset = 0, attr_len = msb->page_size; | ||
978 | 992 | ||
979 | attr = kmalloc(msb->page_size, GFP_KERNEL); | 993 | attr = kmalloc(msb->page_size, GFP_KERNEL); |
980 | if (!attr) | 994 | if (!attr) |
@@ -987,10 +1001,8 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
987 | msb->data_dir = READ; | 1001 | msb->data_dir = READ; |
988 | msb->transfer_cmd = MSPRO_CMD_READ_ATRB; | 1002 | msb->transfer_cmd = MSPRO_CMD_READ_ATRB; |
989 | 1003 | ||
990 | card->next_request = h_mspro_block_req_init; | 1004 | msb->setup_transfer(card, attr_offset, attr_len); |
991 | msb->mrq_handler = h_mspro_block_transfer_data; | 1005 | |
992 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m, | ||
993 | sizeof(param)); | ||
994 | memstick_new_req(card->host); | 1006 | memstick_new_req(card->host); |
995 | wait_for_completion(&card->mrq_complete); | 1007 | wait_for_completion(&card->mrq_complete); |
996 | if (card->current_mrq.error) { | 1008 | if (card->current_mrq.error) { |
@@ -1021,13 +1033,12 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
1021 | } | 1033 | } |
1022 | msb->attr_group.name = "media_attributes"; | 1034 | msb->attr_group.name = "media_attributes"; |
1023 | 1035 | ||
1024 | buffer = kmalloc(msb->page_size, GFP_KERNEL); | 1036 | buffer = kmalloc(attr_len, GFP_KERNEL); |
1025 | if (!buffer) { | 1037 | if (!buffer) { |
1026 | rc = -ENOMEM; | 1038 | rc = -ENOMEM; |
1027 | goto out_free_attr; | 1039 | goto out_free_attr; |
1028 | } | 1040 | } |
1029 | memcpy(buffer, (char *)attr, msb->page_size); | 1041 | memcpy(buffer, (char *)attr, attr_len); |
1030 | page_count = 1; | ||
1031 | 1042 | ||
1032 | for (cnt = 0; cnt < attr_count; ++cnt) { | 1043 | for (cnt = 0; cnt < attr_count; ++cnt) { |
1033 | s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL); | 1044 | s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL); |
@@ -1038,9 +1049,10 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
1038 | 1049 | ||
1039 | msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr; | 1050 | msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr; |
1040 | addr = be32_to_cpu(attr->entries[cnt].address); | 1051 | addr = be32_to_cpu(attr->entries[cnt].address); |
1041 | rc = be32_to_cpu(attr->entries[cnt].size); | 1052 | s_attr->size = be32_to_cpu(attr->entries[cnt].size); |
1042 | dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, " | 1053 | dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, " |
1043 | "size %x\n", cnt, attr->entries[cnt].id, addr, rc); | 1054 | "size %zx\n", cnt, attr->entries[cnt].id, addr, |
1055 | s_attr->size); | ||
1044 | s_attr->id = attr->entries[cnt].id; | 1056 | s_attr->id = attr->entries[cnt].id; |
1045 | if (mspro_block_attr_name(s_attr->id)) | 1057 | if (mspro_block_attr_name(s_attr->id)) |
1046 | snprintf(s_attr->name, sizeof(s_attr->name), "%s", | 1058 | snprintf(s_attr->name, sizeof(s_attr->name), "%s", |
@@ -1054,57 +1066,47 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
1054 | s_attr->dev_attr.attr.mode = S_IRUGO; | 1066 | s_attr->dev_attr.attr.mode = S_IRUGO; |
1055 | s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); | 1067 | s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id); |
1056 | 1068 | ||
1057 | if (!rc) | 1069 | if (!s_attr->size) |
1058 | continue; | 1070 | continue; |
1059 | 1071 | ||
1060 | s_attr->size = rc; | 1072 | s_attr->data = kmalloc(s_attr->size, GFP_KERNEL); |
1061 | s_attr->data = kmalloc(rc, GFP_KERNEL); | ||
1062 | if (!s_attr->data) { | 1073 | if (!s_attr->data) { |
1063 | rc = -ENOMEM; | 1074 | rc = -ENOMEM; |
1064 | goto out_free_buffer; | 1075 | goto out_free_buffer; |
1065 | } | 1076 | } |
1066 | 1077 | ||
1067 | if (((addr / msb->page_size) | 1078 | if (((addr / msb->page_size) == (attr_offset / msb->page_size)) |
1068 | == be32_to_cpu(param.data_address)) | 1079 | && (((addr + s_attr->size - 1) / msb->page_size) |
1069 | && (((addr + rc - 1) / msb->page_size) | 1080 | == (attr_offset / msb->page_size))) { |
1070 | == be32_to_cpu(param.data_address))) { | ||
1071 | memcpy(s_attr->data, buffer + addr % msb->page_size, | 1081 | memcpy(s_attr->data, buffer + addr % msb->page_size, |
1072 | rc); | 1082 | s_attr->size); |
1073 | continue; | 1083 | continue; |
1074 | } | 1084 | } |
1075 | 1085 | ||
1076 | if (page_count <= (rc / msb->page_size)) { | 1086 | attr_offset = (addr / msb->page_size) * msb->page_size; |
1087 | |||
1088 | if ((attr_offset + attr_len) < (addr + s_attr->size)) { | ||
1077 | kfree(buffer); | 1089 | kfree(buffer); |
1078 | page_count = (rc / msb->page_size) + 1; | 1090 | attr_len = (((addr + s_attr->size) / msb->page_size) |
1079 | buffer = kmalloc(page_count * msb->page_size, | 1091 | + 1 ) * msb->page_size - attr_offset; |
1080 | GFP_KERNEL); | 1092 | buffer = kmalloc(attr_len, GFP_KERNEL); |
1081 | if (!buffer) { | 1093 | if (!buffer) { |
1082 | rc = -ENOMEM; | 1094 | rc = -ENOMEM; |
1083 | goto out_free_attr; | 1095 | goto out_free_attr; |
1084 | } | 1096 | } |
1085 | } | 1097 | } |
1086 | 1098 | ||
1087 | param.system = msb->system; | 1099 | sg_init_one(&msb->req_sg[0], buffer, attr_len); |
1088 | param.data_count = cpu_to_be16((rc / msb->page_size) + 1); | ||
1089 | param.data_address = cpu_to_be32(addr / msb->page_size); | ||
1090 | param.tpc_param = 0; | ||
1091 | |||
1092 | sg_init_one(&msb->req_sg[0], buffer, | ||
1093 | be16_to_cpu(param.data_count) * msb->page_size); | ||
1094 | msb->seg_count = 1; | 1100 | msb->seg_count = 1; |
1095 | msb->current_seg = 0; | 1101 | msb->current_seg = 0; |
1096 | msb->current_page = 0; | 1102 | msb->current_page = 0; |
1097 | msb->data_dir = READ; | 1103 | msb->data_dir = READ; |
1098 | msb->transfer_cmd = MSPRO_CMD_READ_ATRB; | 1104 | msb->transfer_cmd = MSPRO_CMD_READ_ATRB; |
1099 | 1105 | ||
1100 | dev_dbg(&card->dev, "reading attribute pages %x, %x\n", | 1106 | dev_dbg(&card->dev, "reading attribute range %x, %x\n", |
1101 | be32_to_cpu(param.data_address), | 1107 | attr_offset, attr_len); |
1102 | be16_to_cpu(param.data_count)); | ||
1103 | 1108 | ||
1104 | card->next_request = h_mspro_block_req_init; | 1109 | msb->setup_transfer(card, attr_offset, attr_len); |
1105 | msb->mrq_handler = h_mspro_block_transfer_data; | ||
1106 | memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, | ||
1107 | (char *)¶m, sizeof(param)); | ||
1108 | memstick_new_req(card->host); | 1110 | memstick_new_req(card->host); |
1109 | wait_for_completion(&card->mrq_complete); | 1111 | wait_for_completion(&card->mrq_complete); |
1110 | if (card->current_mrq.error) { | 1112 | if (card->current_mrq.error) { |
@@ -1112,7 +1114,8 @@ static int mspro_block_read_attributes(struct memstick_dev *card) | |||
1112 | goto out_free_buffer; | 1114 | goto out_free_buffer; |
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | memcpy(s_attr->data, buffer + addr % msb->page_size, rc); | 1117 | memcpy(s_attr->data, buffer + addr % msb->page_size, |
1118 | s_attr->size); | ||
1116 | } | 1119 | } |
1117 | 1120 | ||
1118 | rc = 0; | 1121 | rc = 0; |
@@ -1130,6 +1133,8 @@ static int mspro_block_init_card(struct memstick_dev *card) | |||
1130 | int rc = 0; | 1133 | int rc = 0; |
1131 | 1134 | ||
1132 | msb->system = MEMSTICK_SYS_SERIAL; | 1135 | msb->system = MEMSTICK_SYS_SERIAL; |
1136 | msb->setup_transfer = h_mspro_block_setup_cmd; | ||
1137 | |||
1133 | card->reg_addr.r_offset = offsetof(struct mspro_register, status); | 1138 | card->reg_addr.r_offset = offsetof(struct mspro_register, status); |
1134 | card->reg_addr.r_length = sizeof(struct ms_status_register); | 1139 | card->reg_addr.r_length = sizeof(struct ms_status_register); |
1135 | card->reg_addr.w_offset = offsetof(struct mspro_register, param); | 1140 | card->reg_addr.w_offset = offsetof(struct mspro_register, param); |
@@ -1206,10 +1211,12 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
1206 | 1211 | ||
1207 | msb->page_size = be16_to_cpu(sys_info->unit_size); | 1212 | msb->page_size = be16_to_cpu(sys_info->unit_size); |
1208 | 1213 | ||
1209 | if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) | 1214 | mutex_lock(&mspro_block_disk_lock); |
1215 | if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL)) { | ||
1216 | mutex_unlock(&mspro_block_disk_lock); | ||
1210 | return -ENOMEM; | 1217 | return -ENOMEM; |
1218 | } | ||
1211 | 1219 | ||
1212 | mutex_lock(&mspro_block_disk_lock); | ||
1213 | rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); | 1220 | rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id); |
1214 | mutex_unlock(&mspro_block_disk_lock); | 1221 | mutex_unlock(&mspro_block_disk_lock); |
1215 | 1222 | ||
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index f2b894cd8b02..d89d925caecf 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c | |||
@@ -61,6 +61,7 @@ struct jmb38x_ms_host { | |||
61 | struct memstick_request *req; | 61 | struct memstick_request *req; |
62 | unsigned char cmd_flags; | 62 | unsigned char cmd_flags; |
63 | unsigned char io_pos; | 63 | unsigned char io_pos; |
64 | unsigned char ifmode; | ||
64 | unsigned int io_word[2]; | 65 | unsigned int io_word[2]; |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -136,15 +137,14 @@ struct jmb38x_ms { | |||
136 | #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 | 137 | #define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000 |
137 | #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 | 138 | #define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000 |
138 | 139 | ||
140 | #define CLOCK_CONTROL_BY_MMIO 0x00000008 | ||
139 | #define CLOCK_CONTROL_40MHZ 0x00000001 | 141 | #define CLOCK_CONTROL_40MHZ 0x00000001 |
140 | #define CLOCK_CONTROL_50MHZ 0x0000000a | 142 | #define CLOCK_CONTROL_50MHZ 0x00000002 |
141 | #define CLOCK_CONTROL_60MHZ 0x00000008 | 143 | #define CLOCK_CONTROL_60MHZ 0x00000010 |
142 | #define CLOCK_CONTROL_62_5MHZ 0x0000000c | 144 | #define CLOCK_CONTROL_62_5MHZ 0x00000004 |
143 | #define CLOCK_CONTROL_OFF 0x00000000 | 145 | #define CLOCK_CONTROL_OFF 0x00000000 |
144 | 146 | ||
145 | #define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0 | 147 | #define PCI_CTL_CLOCK_DLY_ADDR 0x000000b0 |
146 | #define PCI_CTL_CLOCK_DLY_MASK_A 0x00000f00 | ||
147 | #define PCI_CTL_CLOCK_DLY_MASK_B 0x0000f000 | ||
148 | 148 | ||
149 | enum { | 149 | enum { |
150 | CMD_READY = 0x01, | 150 | CMD_READY = 0x01, |
@@ -390,8 +390,13 @@ static int jmb38x_ms_issue_cmd(struct memstick_host *msh) | |||
390 | 390 | ||
391 | if (host->req->data_dir == READ) | 391 | if (host->req->data_dir == READ) |
392 | cmd |= TPC_DIR; | 392 | cmd |= TPC_DIR; |
393 | if (host->req->need_card_int) | 393 | |
394 | cmd |= TPC_WAIT_INT; | 394 | if (host->req->need_card_int) { |
395 | if (host->ifmode == MEMSTICK_SERIAL) | ||
396 | cmd |= TPC_GET_INT; | ||
397 | else | ||
398 | cmd |= TPC_WAIT_INT; | ||
399 | } | ||
395 | 400 | ||
396 | data = host->req->data; | 401 | data = host->req->data; |
397 | 402 | ||
@@ -529,7 +534,10 @@ static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id) | |||
529 | if (irq_status & INT_STATUS_ANY_ERR) { | 534 | if (irq_status & INT_STATUS_ANY_ERR) { |
530 | if (irq_status & INT_STATUS_CRC_ERR) | 535 | if (irq_status & INT_STATUS_CRC_ERR) |
531 | host->req->error = -EILSEQ; | 536 | host->req->error = -EILSEQ; |
532 | else | 537 | else if (irq_status & INT_STATUS_TPC_ERR) { |
538 | dev_dbg(&host->chip->pdev->dev, "TPC_ERR\n"); | ||
539 | jmb38x_ms_complete_cmd(msh, 0); | ||
540 | } else | ||
533 | host->req->error = -ETIME; | 541 | host->req->error = -ETIME; |
534 | } else { | 542 | } else { |
535 | if (host->cmd_flags & DMA_DATA) { | 543 | if (host->cmd_flags & DMA_DATA) { |
@@ -644,7 +652,6 @@ static int jmb38x_ms_reset(struct jmb38x_ms_host *host) | |||
644 | ndelay(20); | 652 | ndelay(20); |
645 | } | 653 | } |
646 | dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); | 654 | dev_dbg(&host->chip->pdev->dev, "reset_req timeout\n"); |
647 | /* return -EIO; */ | ||
648 | 655 | ||
649 | reset_next: | 656 | reset_next: |
650 | writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN | 657 | writel(HOST_CONTROL_RESET | HOST_CONTROL_CLOCK_EN |
@@ -675,7 +682,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, | |||
675 | { | 682 | { |
676 | struct jmb38x_ms_host *host = memstick_priv(msh); | 683 | struct jmb38x_ms_host *host = memstick_priv(msh); |
677 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); | 684 | unsigned int host_ctl = readl(host->addr + HOST_CONTROL); |
678 | unsigned int clock_ctl = CLOCK_CONTROL_40MHZ, clock_delay = 0; | 685 | unsigned int clock_ctl = CLOCK_CONTROL_BY_MMIO, clock_delay = 0; |
679 | int rc = 0; | 686 | int rc = 0; |
680 | 687 | ||
681 | switch (param) { | 688 | switch (param) { |
@@ -687,9 +694,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, | |||
687 | 694 | ||
688 | host_ctl = 7; | 695 | host_ctl = 7; |
689 | host_ctl |= HOST_CONTROL_POWER_EN | 696 | host_ctl |= HOST_CONTROL_POWER_EN |
690 | | HOST_CONTROL_CLOCK_EN | 697 | | HOST_CONTROL_CLOCK_EN; |
691 | | HOST_CONTROL_HW_OC_P | ||
692 | | HOST_CONTROL_TDELAY_EN; | ||
693 | writel(host_ctl, host->addr + HOST_CONTROL); | 698 | writel(host_ctl, host->addr + HOST_CONTROL); |
694 | 699 | ||
695 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 | 700 | writel(host->id ? PAD_PU_PD_ON_MS_SOCK1 |
@@ -712,46 +717,88 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, | |||
712 | return -EINVAL; | 717 | return -EINVAL; |
713 | break; | 718 | break; |
714 | case MEMSTICK_INTERFACE: | 719 | case MEMSTICK_INTERFACE: |
720 | dev_dbg(&host->chip->pdev->dev, | ||
721 | "Set Host Interface Mode to %d\n", value); | ||
722 | host_ctl &= ~(HOST_CONTROL_FAST_CLK | HOST_CONTROL_REI | | ||
723 | HOST_CONTROL_REO); | ||
724 | host_ctl |= HOST_CONTROL_TDELAY_EN | HOST_CONTROL_HW_OC_P; | ||
715 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); | 725 | host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT); |
716 | pci_read_config_dword(host->chip->pdev, | ||
717 | PCI_CTL_CLOCK_DLY_ADDR, | ||
718 | &clock_delay); | ||
719 | clock_delay &= host->id ? ~PCI_CTL_CLOCK_DLY_MASK_B | ||
720 | : ~PCI_CTL_CLOCK_DLY_MASK_A; | ||
721 | 726 | ||
722 | if (value == MEMSTICK_SERIAL) { | 727 | if (value == MEMSTICK_SERIAL) { |
723 | host_ctl &= ~HOST_CONTROL_FAST_CLK; | ||
724 | host_ctl &= ~HOST_CONTROL_REO; | ||
725 | host_ctl |= HOST_CONTROL_IF_SERIAL | 728 | host_ctl |= HOST_CONTROL_IF_SERIAL |
726 | << HOST_CONTROL_IF_SHIFT; | 729 | << HOST_CONTROL_IF_SHIFT; |
727 | host_ctl |= HOST_CONTROL_REI; | 730 | host_ctl |= HOST_CONTROL_REI; |
728 | clock_ctl = CLOCK_CONTROL_40MHZ; | 731 | clock_ctl |= CLOCK_CONTROL_40MHZ; |
732 | clock_delay = 0; | ||
729 | } else if (value == MEMSTICK_PAR4) { | 733 | } else if (value == MEMSTICK_PAR4) { |
730 | host_ctl |= HOST_CONTROL_FAST_CLK | HOST_CONTROL_REO; | 734 | host_ctl |= HOST_CONTROL_FAST_CLK; |
731 | host_ctl |= HOST_CONTROL_IF_PAR4 | 735 | host_ctl |= HOST_CONTROL_IF_PAR4 |
732 | << HOST_CONTROL_IF_SHIFT; | 736 | << HOST_CONTROL_IF_SHIFT; |
733 | host_ctl &= ~HOST_CONTROL_REI; | 737 | host_ctl |= HOST_CONTROL_REO; |
734 | clock_ctl = CLOCK_CONTROL_40MHZ; | 738 | clock_ctl |= CLOCK_CONTROL_40MHZ; |
735 | clock_delay |= host->id ? (4 << 12) : (4 << 8); | 739 | clock_delay = 4; |
736 | } else if (value == MEMSTICK_PAR8) { | 740 | } else if (value == MEMSTICK_PAR8) { |
737 | host_ctl |= HOST_CONTROL_FAST_CLK; | 741 | host_ctl |= HOST_CONTROL_FAST_CLK; |
738 | host_ctl |= HOST_CONTROL_IF_PAR8 | 742 | host_ctl |= HOST_CONTROL_IF_PAR8 |
739 | << HOST_CONTROL_IF_SHIFT; | 743 | << HOST_CONTROL_IF_SHIFT; |
740 | host_ctl &= ~(HOST_CONTROL_REI | HOST_CONTROL_REO); | 744 | clock_ctl |= CLOCK_CONTROL_50MHZ; |
741 | clock_ctl = CLOCK_CONTROL_50MHZ; | 745 | clock_delay = 0; |
742 | } else | 746 | } else |
743 | return -EINVAL; | 747 | return -EINVAL; |
744 | 748 | ||
745 | writel(host_ctl, host->addr + HOST_CONTROL); | 749 | writel(host_ctl, host->addr + HOST_CONTROL); |
750 | writel(CLOCK_CONTROL_OFF, host->addr + CLOCK_CONTROL); | ||
746 | writel(clock_ctl, host->addr + CLOCK_CONTROL); | 751 | writel(clock_ctl, host->addr + CLOCK_CONTROL); |
747 | pci_write_config_dword(host->chip->pdev, | 752 | pci_write_config_byte(host->chip->pdev, |
748 | PCI_CTL_CLOCK_DLY_ADDR, | 753 | PCI_CTL_CLOCK_DLY_ADDR + 1, |
749 | clock_delay); | 754 | clock_delay); |
755 | host->ifmode = value; | ||
750 | break; | 756 | break; |
751 | }; | 757 | }; |
752 | return 0; | 758 | return 0; |
753 | } | 759 | } |
754 | 760 | ||
761 | #define PCI_PMOS0_CONTROL 0xae | ||
762 | #define PMOS0_ENABLE 0x01 | ||
763 | #define PMOS0_OVERCURRENT_LEVEL_2_4V 0x06 | ||
764 | #define PMOS0_EN_OVERCURRENT_DEBOUNCE 0x40 | ||
765 | #define PMOS0_SW_LED_POLARITY_ENABLE 0x80 | ||
766 | #define PMOS0_ACTIVE_BITS (PMOS0_ENABLE | PMOS0_EN_OVERCURRENT_DEBOUNCE | \ | ||
767 | PMOS0_OVERCURRENT_LEVEL_2_4V) | ||
768 | #define PCI_PMOS1_CONTROL 0xbd | ||
769 | #define PMOS1_ACTIVE_BITS 0x4a | ||
770 | #define PCI_CLOCK_CTL 0xb9 | ||
771 | |||
772 | static int jmb38x_ms_pmos(struct pci_dev *pdev, int flag) | ||
773 | { | ||
774 | unsigned char val; | ||
775 | |||
776 | pci_read_config_byte(pdev, PCI_PMOS0_CONTROL, &val); | ||
777 | if (flag) | ||
778 | val |= PMOS0_ACTIVE_BITS; | ||
779 | else | ||
780 | val &= ~PMOS0_ACTIVE_BITS; | ||
781 | pci_write_config_byte(pdev, PCI_PMOS0_CONTROL, val); | ||
782 | dev_dbg(&pdev->dev, "JMB38x: set PMOS0 val 0x%x\n", val); | ||
783 | |||
784 | if (pci_resource_flags(pdev, 1)) { | ||
785 | pci_read_config_byte(pdev, PCI_PMOS1_CONTROL, &val); | ||
786 | if (flag) | ||
787 | val |= PMOS1_ACTIVE_BITS; | ||
788 | else | ||
789 | val &= ~PMOS1_ACTIVE_BITS; | ||
790 | pci_write_config_byte(pdev, PCI_PMOS1_CONTROL, val); | ||
791 | dev_dbg(&pdev->dev, "JMB38x: set PMOS1 val 0x%x\n", val); | ||
792 | } | ||
793 | |||
794 | pci_read_config_byte(pdev, PCI_CLOCK_CTL, &val); | ||
795 | pci_write_config_byte(pdev, PCI_CLOCK_CTL, val & ~0x0f); | ||
796 | pci_write_config_byte(pdev, PCI_CLOCK_CTL, val | 0x01); | ||
797 | dev_dbg(&pdev->dev, "Clock Control by PCI config is disabled!\n"); | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
755 | #ifdef CONFIG_PM | 802 | #ifdef CONFIG_PM |
756 | 803 | ||
757 | static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state) | 804 | static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state) |
@@ -784,8 +831,7 @@ static int jmb38x_ms_resume(struct pci_dev *dev) | |||
784 | return rc; | 831 | return rc; |
785 | pci_set_master(dev); | 832 | pci_set_master(dev); |
786 | 833 | ||
787 | pci_read_config_dword(dev, 0xac, &rc); | 834 | jmb38x_ms_pmos(dev, 1); |
788 | pci_write_config_dword(dev, 0xac, rc | 0x00470000); | ||
789 | 835 | ||
790 | for (rc = 0; rc < jm->host_cnt; ++rc) { | 836 | for (rc = 0; rc < jm->host_cnt; ++rc) { |
791 | if (!jm->hosts[rc]) | 837 | if (!jm->hosts[rc]) |
@@ -894,8 +940,7 @@ static int jmb38x_ms_probe(struct pci_dev *pdev, | |||
894 | goto err_out; | 940 | goto err_out; |
895 | } | 941 | } |
896 | 942 | ||
897 | pci_read_config_dword(pdev, 0xac, &rc); | 943 | jmb38x_ms_pmos(pdev, 1); |
898 | pci_write_config_dword(pdev, 0xac, rc | 0x00470000); | ||
899 | 944 | ||
900 | cnt = jmb38x_ms_count_slots(pdev); | 945 | cnt = jmb38x_ms_count_slots(pdev); |
901 | if (!cnt) { | 946 | if (!cnt) { |
@@ -976,6 +1021,8 @@ static void jmb38x_ms_remove(struct pci_dev *dev) | |||
976 | jmb38x_ms_free_host(jm->hosts[cnt]); | 1021 | jmb38x_ms_free_host(jm->hosts[cnt]); |
977 | } | 1022 | } |
978 | 1023 | ||
1024 | jmb38x_ms_pmos(dev, 0); | ||
1025 | |||
979 | pci_set_drvdata(dev, NULL); | 1026 | pci_set_drvdata(dev, NULL); |
980 | pci_release_regions(dev); | 1027 | pci_release_regions(dev); |
981 | pci_disable_device(dev); | 1028 | pci_disable_device(dev); |
@@ -983,8 +1030,9 @@ static void jmb38x_ms_remove(struct pci_dev *dev) | |||
983 | } | 1030 | } |
984 | 1031 | ||
985 | static struct pci_device_id jmb38x_ms_id_tbl [] = { | 1032 | static struct pci_device_id jmb38x_ms_id_tbl [] = { |
986 | { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID, | 1033 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS) }, |
987 | PCI_ANY_ID, 0, 0, 0 }, | 1034 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB385_MS) }, |
1035 | { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB390_MS) }, | ||
988 | { } | 1036 | { } |
989 | }; | 1037 | }; |
990 | 1038 | ||
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 691620dbedd2..8b04810df469 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h | |||
@@ -268,7 +268,7 @@ | |||
268 | 268 | ||
269 | /* Compatibility Error : IR Disabled */ | 269 | /* Compatibility Error : IR Disabled */ |
270 | #define IR_LOGINFO_COMPAT_ERROR_RAID_DISABLED (0x00010030) | 270 | #define IR_LOGINFO_COMPAT_ERROR_RAID_DISABLED (0x00010030) |
271 | /* Compatibility Error : Inquiry Comand failed */ | 271 | /* Compatibility Error : Inquiry Command failed */ |
272 | #define IR_LOGINFO_COMPAT_ERROR_INQUIRY_FAILED (0x00010031) | 272 | #define IR_LOGINFO_COMPAT_ERROR_INQUIRY_FAILED (0x00010031) |
273 | /* Compatibility Error : Device not direct access device */ | 273 | /* Compatibility Error : Device not direct access device */ |
274 | #define IR_LOGINFO_COMPAT_ERROR_NOT_DIRECT_ACCESS (0x00010032) | 274 | #define IR_LOGINFO_COMPAT_ERROR_NOT_DIRECT_ACCESS (0x00010032) |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 3e57b61ca446..3358c0af3466 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -7977,7 +7977,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) | |||
7977 | NULL, /* 2Eh */ | 7977 | NULL, /* 2Eh */ |
7978 | NULL, /* 2Fh */ | 7978 | NULL, /* 2Fh */ |
7979 | "Compatibility Error: IR Disabled", /* 30h */ | 7979 | "Compatibility Error: IR Disabled", /* 30h */ |
7980 | "Compatibility Error: Inquiry Comand Failed", /* 31h */ | 7980 | "Compatibility Error: Inquiry Command Failed", /* 31h */ |
7981 | "Compatibility Error: Device not Direct Access " | 7981 | "Compatibility Error: Device not Direct Access " |
7982 | "Device ", /* 32h */ | 7982 | "Device ", /* 32h */ |
7983 | "Compatibility Error: Removable Device Found", /* 33h */ | 7983 | "Compatibility Error: Removable Device Found", /* 33h */ |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index d48c2c6058e1..8aefb1829fcd 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -1146,7 +1146,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, | |||
1146 | * | 1146 | * |
1147 | * This function will delete scheduled target reset from the list and | 1147 | * This function will delete scheduled target reset from the list and |
1148 | * try to send next target reset. This will be called from completion | 1148 | * try to send next target reset. This will be called from completion |
1149 | * context of any Task managment command. | 1149 | * context of any Task management command. |
1150 | */ | 1150 | */ |
1151 | 1151 | ||
1152 | void | 1152 | void |
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index f87a9d405a5e..ae7cad185898 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c | |||
@@ -309,7 +309,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) | |||
309 | * @ireq: I2O block request | 309 | * @ireq: I2O block request |
310 | * @mptr: message body pointer | 310 | * @mptr: message body pointer |
311 | * | 311 | * |
312 | * Builds the SG list and map it to be accessable by the controller. | 312 | * Builds the SG list and map it to be accessible by the controller. |
313 | * | 313 | * |
314 | * Returns 0 on failure or 1 on success. | 314 | * Returns 0 on failure or 1 on success. |
315 | */ | 315 | */ |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index b3b2aaf89dbe..8d221ba5e38d 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -218,6 +218,18 @@ static const char *wm8994_main_supplies[] = { | |||
218 | "SPKVDD2", | 218 | "SPKVDD2", |
219 | }; | 219 | }; |
220 | 220 | ||
221 | static const char *wm8958_main_supplies[] = { | ||
222 | "DBVDD1", | ||
223 | "DBVDD2", | ||
224 | "DBVDD3", | ||
225 | "DCVDD", | ||
226 | "AVDD1", | ||
227 | "AVDD2", | ||
228 | "CPVDD", | ||
229 | "SPKVDD1", | ||
230 | "SPKVDD2", | ||
231 | }; | ||
232 | |||
221 | #ifdef CONFIG_PM | 233 | #ifdef CONFIG_PM |
222 | static int wm8994_device_suspend(struct device *dev) | 234 | static int wm8994_device_suspend(struct device *dev) |
223 | { | 235 | { |
@@ -239,7 +251,7 @@ static int wm8994_device_suspend(struct device *dev) | |||
239 | if (ret < 0) | 251 | if (ret < 0) |
240 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); | 252 | dev_err(dev, "Failed to save LDO registers: %d\n", ret); |
241 | 253 | ||
242 | ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 254 | ret = regulator_bulk_disable(wm8994->num_supplies, |
243 | wm8994->supplies); | 255 | wm8994->supplies); |
244 | if (ret != 0) { | 256 | if (ret != 0) { |
245 | dev_err(dev, "Failed to disable supplies: %d\n", ret); | 257 | dev_err(dev, "Failed to disable supplies: %d\n", ret); |
@@ -254,7 +266,7 @@ static int wm8994_device_resume(struct device *dev) | |||
254 | struct wm8994 *wm8994 = dev_get_drvdata(dev); | 266 | struct wm8994 *wm8994 = dev_get_drvdata(dev); |
255 | int ret; | 267 | int ret; |
256 | 268 | ||
257 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies), | 269 | ret = regulator_bulk_enable(wm8994->num_supplies, |
258 | wm8994->supplies); | 270 | wm8994->supplies); |
259 | if (ret != 0) { | 271 | if (ret != 0) { |
260 | dev_err(dev, "Failed to enable supplies: %d\n", ret); | 272 | dev_err(dev, "Failed to enable supplies: %d\n", ret); |
@@ -305,9 +317,10 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) | |||
305 | /* | 317 | /* |
306 | * Instantiate the generic non-control parts of the device. | 318 | * Instantiate the generic non-control parts of the device. |
307 | */ | 319 | */ |
308 | static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | 320 | static int wm8994_device_init(struct wm8994 *wm8994, int irq) |
309 | { | 321 | { |
310 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; | 322 | struct wm8994_pdata *pdata = wm8994->dev->platform_data; |
323 | const char *devname; | ||
311 | int ret, i; | 324 | int ret, i; |
312 | 325 | ||
313 | mutex_init(&wm8994->io_lock); | 326 | mutex_init(&wm8994->io_lock); |
@@ -323,25 +336,48 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
323 | goto err; | 336 | goto err; |
324 | } | 337 | } |
325 | 338 | ||
339 | switch (wm8994->type) { | ||
340 | case WM8994: | ||
341 | wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); | ||
342 | break; | ||
343 | case WM8958: | ||
344 | wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies); | ||
345 | break; | ||
346 | default: | ||
347 | BUG(); | ||
348 | return -EINVAL; | ||
349 | } | ||
350 | |||
326 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * | 351 | wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) * |
327 | ARRAY_SIZE(wm8994_main_supplies), | 352 | wm8994->num_supplies, |
328 | GFP_KERNEL); | 353 | GFP_KERNEL); |
329 | if (!wm8994->supplies) { | 354 | if (!wm8994->supplies) { |
330 | ret = -ENOMEM; | 355 | ret = -ENOMEM; |
331 | goto err; | 356 | goto err; |
332 | } | 357 | } |
333 | 358 | ||
334 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | 359 | switch (wm8994->type) { |
335 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; | 360 | case WM8994: |
336 | 361 | for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++) | |
337 | ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies), | 362 | wm8994->supplies[i].supply = wm8994_main_supplies[i]; |
363 | break; | ||
364 | case WM8958: | ||
365 | for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++) | ||
366 | wm8994->supplies[i].supply = wm8958_main_supplies[i]; | ||
367 | break; | ||
368 | default: | ||
369 | BUG(); | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | |||
373 | ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies, | ||
338 | wm8994->supplies); | 374 | wm8994->supplies); |
339 | if (ret != 0) { | 375 | if (ret != 0) { |
340 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); | 376 | dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret); |
341 | goto err_supplies; | 377 | goto err_supplies; |
342 | } | 378 | } |
343 | 379 | ||
344 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies), | 380 | ret = regulator_bulk_enable(wm8994->num_supplies, |
345 | wm8994->supplies); | 381 | wm8994->supplies); |
346 | if (ret != 0) { | 382 | if (ret != 0) { |
347 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); | 383 | dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret); |
@@ -353,7 +389,22 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
353 | dev_err(wm8994->dev, "Failed to read ID register\n"); | 389 | dev_err(wm8994->dev, "Failed to read ID register\n"); |
354 | goto err_enable; | 390 | goto err_enable; |
355 | } | 391 | } |
356 | if (ret != 0x8994) { | 392 | switch (ret) { |
393 | case 0x8994: | ||
394 | devname = "WM8994"; | ||
395 | if (wm8994->type != WM8994) | ||
396 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
397 | wm8994->type); | ||
398 | wm8994->type = WM8994; | ||
399 | break; | ||
400 | case 0x8958: | ||
401 | devname = "WM8958"; | ||
402 | if (wm8994->type != WM8958) | ||
403 | dev_warn(wm8994->dev, "Device registered as type %d\n", | ||
404 | wm8994->type); | ||
405 | wm8994->type = WM8958; | ||
406 | break; | ||
407 | default: | ||
357 | dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", | 408 | dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n", |
358 | ret); | 409 | ret); |
359 | ret = -EINVAL; | 410 | ret = -EINVAL; |
@@ -370,14 +421,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
370 | switch (ret) { | 421 | switch (ret) { |
371 | case 0: | 422 | case 0: |
372 | case 1: | 423 | case 1: |
373 | dev_warn(wm8994->dev, "revision %c not fully supported\n", | 424 | if (wm8994->type == WM8994) |
374 | 'A' + ret); | 425 | dev_warn(wm8994->dev, |
426 | "revision %c not fully supported\n", | ||
427 | 'A' + ret); | ||
375 | break; | 428 | break; |
376 | default: | 429 | default: |
377 | dev_info(wm8994->dev, "revision %c\n", 'A' + ret); | ||
378 | break; | 430 | break; |
379 | } | 431 | } |
380 | 432 | ||
433 | dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret); | ||
381 | 434 | ||
382 | if (pdata) { | 435 | if (pdata) { |
383 | wm8994->irq_base = pdata->irq_base; | 436 | wm8994->irq_base = pdata->irq_base; |
@@ -423,10 +476,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq) | |||
423 | err_irq: | 476 | err_irq: |
424 | wm8994_irq_exit(wm8994); | 477 | wm8994_irq_exit(wm8994); |
425 | err_enable: | 478 | err_enable: |
426 | regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 479 | regulator_bulk_disable(wm8994->num_supplies, |
427 | wm8994->supplies); | 480 | wm8994->supplies); |
428 | err_get: | 481 | err_get: |
429 | regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); | 482 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
430 | err_supplies: | 483 | err_supplies: |
431 | kfree(wm8994->supplies); | 484 | kfree(wm8994->supplies); |
432 | err: | 485 | err: |
@@ -439,9 +492,9 @@ static void wm8994_device_exit(struct wm8994 *wm8994) | |||
439 | { | 492 | { |
440 | mfd_remove_devices(wm8994->dev); | 493 | mfd_remove_devices(wm8994->dev); |
441 | wm8994_irq_exit(wm8994); | 494 | wm8994_irq_exit(wm8994); |
442 | regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies), | 495 | regulator_bulk_disable(wm8994->num_supplies, |
443 | wm8994->supplies); | 496 | wm8994->supplies); |
444 | regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies); | 497 | regulator_bulk_free(wm8994->num_supplies, wm8994->supplies); |
445 | kfree(wm8994->supplies); | 498 | kfree(wm8994->supplies); |
446 | kfree(wm8994); | 499 | kfree(wm8994); |
447 | } | 500 | } |
@@ -506,8 +559,9 @@ static int wm8994_i2c_probe(struct i2c_client *i2c, | |||
506 | wm8994->read_dev = wm8994_i2c_read_device; | 559 | wm8994->read_dev = wm8994_i2c_read_device; |
507 | wm8994->write_dev = wm8994_i2c_write_device; | 560 | wm8994->write_dev = wm8994_i2c_write_device; |
508 | wm8994->irq = i2c->irq; | 561 | wm8994->irq = i2c->irq; |
562 | wm8994->type = id->driver_data; | ||
509 | 563 | ||
510 | return wm8994_device_init(wm8994, id->driver_data, i2c->irq); | 564 | return wm8994_device_init(wm8994, i2c->irq); |
511 | } | 565 | } |
512 | 566 | ||
513 | static int wm8994_i2c_remove(struct i2c_client *i2c) | 567 | static int wm8994_i2c_remove(struct i2c_client *i2c) |
@@ -535,7 +589,8 @@ static int wm8994_i2c_resume(struct i2c_client *i2c) | |||
535 | #endif | 589 | #endif |
536 | 590 | ||
537 | static const struct i2c_device_id wm8994_i2c_id[] = { | 591 | static const struct i2c_device_id wm8994_i2c_id[] = { |
538 | { "wm8994", 0 }, | 592 | { "wm8994", WM8994 }, |
593 | { "wm8958", WM8958 }, | ||
539 | { } | 594 | { } |
540 | }; | 595 | }; |
541 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); | 596 | MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id); |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4d073f1e4502..1e1a4be8eb6c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -402,7 +402,7 @@ config TI_DAC7512 | |||
402 | DAC7512 16-bit digital-to-analog converter. | 402 | DAC7512 16-bit digital-to-analog converter. |
403 | 403 | ||
404 | This driver can also be built as a module. If so, the module | 404 | This driver can also be built as a module. If so, the module |
405 | will be calles ti_dac7512. | 405 | will be called ti_dac7512. |
406 | 406 | ||
407 | config VMWARE_BALLOON | 407 | config VMWARE_BALLOON |
408 | tristate "VMware Balloon Driver" | 408 | tristate "VMware Balloon Driver" |
diff --git a/drivers/misc/arm-charlcd.c b/drivers/misc/arm-charlcd.c index 9e3879ef58f2..fe8616a8d287 100644 --- a/drivers/misc/arm-charlcd.c +++ b/drivers/misc/arm-charlcd.c | |||
@@ -313,7 +313,7 @@ static int __init charlcd_probe(struct platform_device *pdev) | |||
313 | INIT_DELAYED_WORK(&lcd->init_work, charlcd_init_work); | 313 | INIT_DELAYED_WORK(&lcd->init_work, charlcd_init_work); |
314 | schedule_delayed_work(&lcd->init_work, 0); | 314 | schedule_delayed_work(&lcd->init_work, 0); |
315 | 315 | ||
316 | dev_info(&pdev->dev, "initalized ARM character LCD at %08x\n", | 316 | dev_info(&pdev->dev, "initialized ARM character LCD at %08x\n", |
317 | lcd->phybase); | 317 | lcd->phybase); |
318 | 318 | ||
319 | return 0; | 319 | return 0; |
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c index 2a1e804a71aa..4d2ea8e80140 100644 --- a/drivers/misc/vmw_balloon.c +++ b/drivers/misc/vmw_balloon.c | |||
@@ -45,7 +45,7 @@ | |||
45 | 45 | ||
46 | MODULE_AUTHOR("VMware, Inc."); | 46 | MODULE_AUTHOR("VMware, Inc."); |
47 | MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); | 47 | MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); |
48 | MODULE_VERSION("1.2.1.1-k"); | 48 | MODULE_VERSION("1.2.1.2-k"); |
49 | MODULE_ALIAS("dmi:*:svnVMware*:*"); | 49 | MODULE_ALIAS("dmi:*:svnVMware*:*"); |
50 | MODULE_ALIAS("vmware_vmmemctl"); | 50 | MODULE_ALIAS("vmware_vmmemctl"); |
51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
@@ -315,7 +315,8 @@ static bool vmballoon_send_get_target(struct vmballoon *b, u32 *new_target) | |||
315 | * fear that guest will need it. Host may reject some pages, we need to | 315 | * fear that guest will need it. Host may reject some pages, we need to |
316 | * check the return value and maybe submit a different page. | 316 | * check the return value and maybe submit a different page. |
317 | */ | 317 | */ |
318 | static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn) | 318 | static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn, |
319 | unsigned int *hv_status) | ||
319 | { | 320 | { |
320 | unsigned long status, dummy; | 321 | unsigned long status, dummy; |
321 | u32 pfn32; | 322 | u32 pfn32; |
@@ -326,7 +327,7 @@ static bool vmballoon_send_lock_page(struct vmballoon *b, unsigned long pfn) | |||
326 | 327 | ||
327 | STATS_INC(b->stats.lock); | 328 | STATS_INC(b->stats.lock); |
328 | 329 | ||
329 | status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy); | 330 | *hv_status = status = VMWARE_BALLOON_CMD(LOCK, pfn, dummy); |
330 | if (vmballoon_check_status(b, status)) | 331 | if (vmballoon_check_status(b, status)) |
331 | return true; | 332 | return true; |
332 | 333 | ||
@@ -410,6 +411,7 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep) | |||
410 | { | 411 | { |
411 | struct page *page; | 412 | struct page *page; |
412 | gfp_t flags; | 413 | gfp_t flags; |
414 | unsigned int hv_status; | ||
413 | bool locked = false; | 415 | bool locked = false; |
414 | 416 | ||
415 | do { | 417 | do { |
@@ -429,11 +431,12 @@ static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep) | |||
429 | } | 431 | } |
430 | 432 | ||
431 | /* inform monitor */ | 433 | /* inform monitor */ |
432 | locked = vmballoon_send_lock_page(b, page_to_pfn(page)); | 434 | locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status); |
433 | if (!locked) { | 435 | if (!locked) { |
434 | STATS_INC(b->stats.refused_alloc); | 436 | STATS_INC(b->stats.refused_alloc); |
435 | 437 | ||
436 | if (b->reset_required) { | 438 | if (hv_status == VMW_BALLOON_ERROR_RESET || |
439 | hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) { | ||
437 | __free_page(page); | 440 | __free_page(page); |
438 | return -EIO; | 441 | return -EIO; |
439 | } | 442 | } |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 217f82037fc1..bfc8a8ae55df 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -257,7 +257,7 @@ static u32 get_card_status(struct mmc_card *card, struct request *req) | |||
257 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; | 257 | cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; |
258 | err = mmc_wait_for_cmd(card->host, &cmd, 0); | 258 | err = mmc_wait_for_cmd(card->host, &cmd, 0); |
259 | if (err) | 259 | if (err) |
260 | printk(KERN_ERR "%s: error %d sending status comand", | 260 | printk(KERN_ERR "%s: error %d sending status command", |
261 | req->rq_disk->disk_name, err); | 261 | req->rq_disk->disk_name, err); |
262 | return cmd.resp[0]; | 262 | return cmd.resp[0]; |
263 | } | 263 | } |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index c22a4c039988..afe8c6fa166a 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -501,7 +501,7 @@ config MMC_SH_MMCIF | |||
501 | tristate "SuperH Internal MMCIF support" | 501 | tristate "SuperH Internal MMCIF support" |
502 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) | 502 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) |
503 | help | 503 | help |
504 | This selects the MMC Host Interface controler (MMCIF). | 504 | This selects the MMC Host Interface controller (MMCIF). |
505 | 505 | ||
506 | This driver supports MMCIF in sh7724/sh7757/sh7372. | 506 | This driver supports MMCIF in sh7724/sh7757/sh7372. |
507 | 507 | ||
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 41e5a60493ad..ef72e874ca36 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
@@ -192,7 +192,7 @@ static inline void SEND_STOP(struct au1xmmc_host *host) | |||
192 | au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host)); | 192 | au_writel(config2 | SD_CONFIG2_DF, HOST_CONFIG2(host)); |
193 | au_sync(); | 193 | au_sync(); |
194 | 194 | ||
195 | /* Send the stop commmand */ | 195 | /* Send the stop command */ |
196 | au_writel(STOP_CMD, HOST_CMD(host)); | 196 | au_writel(STOP_CMD, HOST_CMD(host)); |
197 | } | 197 | } |
198 | 198 | ||
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index f472c2714eb8..bbc298fd2a15 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c | |||
@@ -446,7 +446,7 @@ static int sdricoh_init_mmc(struct pci_dev *pci_dev, | |||
446 | mmc->max_seg_size = 1024 * 512; | 446 | mmc->max_seg_size = 1024 * 512; |
447 | mmc->max_blk_size = 512; | 447 | mmc->max_blk_size = 512; |
448 | 448 | ||
449 | /* reset the controler */ | 449 | /* reset the controller */ |
450 | if (sdricoh_reset(host)) { | 450 | if (sdricoh_reset(host)) { |
451 | dev_dbg(dev, "could not reset\n"); | 451 | dev_dbg(dev, "could not reset\n"); |
452 | result = -EIO; | 452 | result = -EIO; |
@@ -478,7 +478,7 @@ static int sdricoh_pcmcia_probe(struct pcmcia_device *pcmcia_dev) | |||
478 | dev_info(&pcmcia_dev->dev, "Searching MMC controller for pcmcia device" | 478 | dev_info(&pcmcia_dev->dev, "Searching MMC controller for pcmcia device" |
479 | " %s %s ...\n", pcmcia_dev->prod_id[0], pcmcia_dev->prod_id[1]); | 479 | " %s %s ...\n", pcmcia_dev->prod_id[0], pcmcia_dev->prod_id[1]); |
480 | 480 | ||
481 | /* search pci cardbus bridge that contains the mmc controler */ | 481 | /* search pci cardbus bridge that contains the mmc controller */ |
482 | /* the io region is already claimed by yenta_socket... */ | 482 | /* the io region is already claimed by yenta_socket... */ |
483 | while ((pci_dev = | 483 | while ((pci_dev = |
484 | pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, | 484 | pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index f511dd15fd31..ee4bb3330bdf 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -1134,7 +1134,7 @@ static const struct file_operations mtd_fops = { | |||
1134 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, | 1134 | static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type, |
1135 | int flags, const char *dev_name, void *data) | 1135 | int flags, const char *dev_name, void *data) |
1136 | { | 1136 | { |
1137 | return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC); | 1137 | return mount_pseudo(fs_type, "mtd_inode:", NULL, NULL, MTD_INODE_FS_MAGIC); |
1138 | } | 1138 | } |
1139 | 1139 | ||
1140 | static struct file_system_type mtd_inodefs_type = { | 1140 | static struct file_system_type mtd_inodefs_type = { |
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index 1ee72f3f0512..c948150079be 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c | |||
@@ -307,6 +307,11 @@ static void mtdoops_do_dump(struct kmsg_dumper *dumper, | |||
307 | unsigned long l1_cpy, l2_cpy; | 307 | unsigned long l1_cpy, l2_cpy; |
308 | char *dst; | 308 | char *dst; |
309 | 309 | ||
310 | if (reason != KMSG_DUMP_OOPS && | ||
311 | reason != KMSG_DUMP_PANIC && | ||
312 | reason != KMSG_DUMP_KEXEC) | ||
313 | return; | ||
314 | |||
310 | /* Only dump oopses if dump_oops is set */ | 315 | /* Only dump oopses if dump_oops is set */ |
311 | if (reason == KMSG_DUMP_OOPS && !dump_oops) | 316 | if (reason == KMSG_DUMP_OOPS && !dump_oops) |
312 | return; | 317 | return; |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 1f75a1b1f7c3..31bf376b82a0 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -821,7 +821,7 @@ retry: | |||
821 | * | 821 | * |
822 | * Wait for command done. This is a helper function for nand_wait used when | 822 | * Wait for command done. This is a helper function for nand_wait used when |
823 | * we are in interrupt context. May happen when in panic and trying to write | 823 | * we are in interrupt context. May happen when in panic and trying to write |
824 | * an oops trough mtdoops. | 824 | * an oops through mtdoops. |
825 | */ | 825 | */ |
826 | static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, | 826 | static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip, |
827 | unsigned long timeo) | 827 | unsigned long timeo) |
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 6a858a29db56..a6cd335c9436 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h | |||
@@ -1415,12 +1415,12 @@ struct bnx2x_func_init_params { | |||
1415 | else | 1415 | else |
1416 | 1416 | ||
1417 | /* skip rx queue | 1417 | /* skip rx queue |
1418 | * if FCOE l2 support is diabled and this is the fcoe L2 queue | 1418 | * if FCOE l2 support is disabled and this is the fcoe L2 queue |
1419 | */ | 1419 | */ |
1420 | #define skip_rx_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx)) | 1420 | #define skip_rx_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx)) |
1421 | 1421 | ||
1422 | /* skip tx queue | 1422 | /* skip tx queue |
1423 | * if FCOE l2 support is diabled and this is the fcoe L2 queue | 1423 | * if FCOE l2 support is disabled and this is the fcoe L2 queue |
1424 | */ | 1424 | */ |
1425 | #define skip_tx_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx)) | 1425 | #define skip_tx_queue(bp, idx) (NO_FCOE(bp) && IS_FCOE_IDX(idx)) |
1426 | 1426 | ||
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 84e1af4d65e1..8cdcf5b39d1e 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c | |||
@@ -5037,7 +5037,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code) | |||
5037 | memset(&ilt_cli, 0, sizeof(struct ilt_client_info)); | 5037 | memset(&ilt_cli, 0, sizeof(struct ilt_client_info)); |
5038 | memset(&ilt, 0, sizeof(struct bnx2x_ilt)); | 5038 | memset(&ilt, 0, sizeof(struct bnx2x_ilt)); |
5039 | 5039 | ||
5040 | /* initalize dummy TM client */ | 5040 | /* initialize dummy TM client */ |
5041 | ilt_cli.start = 0; | 5041 | ilt_cli.start = 0; |
5042 | ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1; | 5042 | ilt_cli.end = ILT_NUM_PAGE_ENTRIES - 1; |
5043 | ilt_cli.client_num = ILT_CLIENT_TM; | 5043 | ilt_cli.client_num = ILT_CLIENT_TM; |
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index 38ef7ca9f21d..c939683e3d61 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h | |||
@@ -1633,7 +1633,7 @@ | |||
1633 | (~misc_registers_sw_timer_cfg_4.sw_timer_cfg_4[1] ) is set */ | 1633 | (~misc_registers_sw_timer_cfg_4.sw_timer_cfg_4[1] ) is set */ |
1634 | #define MISC_REG_SW_TIMER_RELOAD_VAL_4 0xa2fc | 1634 | #define MISC_REG_SW_TIMER_RELOAD_VAL_4 0xa2fc |
1635 | /* [RW 32] the value of the counter for sw timers1-8. there are 8 addresses | 1635 | /* [RW 32] the value of the counter for sw timers1-8. there are 8 addresses |
1636 | in this register. addres 0 - timer 1; address 1 - timer 2, ... address 7 - | 1636 | in this register. address 0 - timer 1; address 1 - timer 2, ... address 7 - |
1637 | timer 8 */ | 1637 | timer 8 */ |
1638 | #define MISC_REG_SW_TIMER_VAL 0xa5c0 | 1638 | #define MISC_REG_SW_TIMER_VAL 0xa5c0 |
1639 | /* [RW 1] Set by the MCP to remember if one or more of the drivers is/are | 1639 | /* [RW 1] Set by the MCP to remember if one or more of the drivers is/are |
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 48cf24ff4e6f..171782e2bb39 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -840,7 +840,7 @@ static int ad_lacpdu_send(struct port *port) | |||
840 | lacpdu_header = (struct lacpdu_header *)skb_put(skb, length); | 840 | lacpdu_header = (struct lacpdu_header *)skb_put(skb, length); |
841 | 841 | ||
842 | memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); | 842 | memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); |
843 | /* Note: source addres is set to be the member's PERMANENT address, | 843 | /* Note: source address is set to be the member's PERMANENT address, |
844 | because we use it to identify loopback lacpdus in receive. */ | 844 | because we use it to identify loopback lacpdus in receive. */ |
845 | memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); | 845 | memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); |
846 | lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU; | 846 | lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU; |
@@ -881,7 +881,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker) | |||
881 | marker_header = (struct bond_marker_header *)skb_put(skb, length); | 881 | marker_header = (struct bond_marker_header *)skb_put(skb, length); |
882 | 882 | ||
883 | memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); | 883 | memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); |
884 | /* Note: source addres is set to be the member's PERMANENT address, | 884 | /* Note: source address is set to be the member's PERMANENT address, |
885 | because we use it to identify loopback MARKERs in receive. */ | 885 | because we use it to identify loopback MARKERs in receive. */ |
886 | memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); | 886 | memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); |
887 | marker_header->hdr.h_proto = PKT_TYPE_LACPDU; | 887 | marker_header->hdr.h_proto = PKT_TYPE_LACPDU; |
@@ -1916,7 +1916,7 @@ int bond_3ad_bind_slave(struct slave *slave) | |||
1916 | return -1; | 1916 | return -1; |
1917 | } | 1917 | } |
1918 | 1918 | ||
1919 | //check that the slave has not been intialized yet. | 1919 | //check that the slave has not been initialized yet. |
1920 | if (SLAVE_AD_INFO(slave).port.slave != slave) { | 1920 | if (SLAVE_AD_INFO(slave).port.slave != slave) { |
1921 | 1921 | ||
1922 | // port initialization | 1922 | // port initialization |
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 63ebf76d2390..8a43c7e19701 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c | |||
@@ -556,7 +556,7 @@ struct chelsio_vpd_t { | |||
556 | #define EEPROM_MAX_POLL 4 | 556 | #define EEPROM_MAX_POLL 4 |
557 | 557 | ||
558 | /* | 558 | /* |
559 | * Read SEEPROM. A zero is written to the flag register when the addres is | 559 | * Read SEEPROM. A zero is written to the flag register when the address is |
560 | * written to the Control register. The hardware device will set the flag to a | 560 | * written to the Control register. The hardware device will set the flag to a |
561 | * one when 4B have been transferred to the Data register. | 561 | * one when 4B have been transferred to the Data register. |
562 | */ | 562 | */ |
diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c index a8766fb2f9ab..e13b7fe9d082 100644 --- a/drivers/net/cxgb3/mc5.c +++ b/drivers/net/cxgb3/mc5.c | |||
@@ -318,7 +318,7 @@ static void mc5_dbgi_mode_disable(const struct mc5 *mc5) | |||
318 | 318 | ||
319 | /* | 319 | /* |
320 | * Initialization that requires the OS and protocol layers to already | 320 | * Initialization that requires the OS and protocol layers to already |
321 | * be intialized goes here. | 321 | * be initialized goes here. |
322 | */ | 322 | */ |
323 | int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, | 323 | int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters, |
324 | unsigned int nroutes) | 324 | unsigned int nroutes) |
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index ec8579a0a808..d55db6b38e7b 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
@@ -607,7 +607,7 @@ struct t3_vpd { | |||
607 | * | 607 | * |
608 | * Read a 32-bit word from a location in VPD EEPROM using the card's PCI | 608 | * Read a 32-bit word from a location in VPD EEPROM using the card's PCI |
609 | * VPD ROM capability. A zero is written to the flag bit when the | 609 | * VPD ROM capability. A zero is written to the flag bit when the |
610 | * addres is written to the control register. The hardware device will | 610 | * address is written to the control register. The hardware device will |
611 | * set the flag to 1 when 4 bytes have been read into the data register. | 611 | * set the flag to 1 when 4 bytes have been read into the data register. |
612 | */ | 612 | */ |
613 | int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data) | 613 | int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data) |
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index f5514a0d5be6..196eeda2dd6c 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h | |||
@@ -41,7 +41,7 @@ struct e1000_hw; | |||
41 | struct e1000_hw_stats; | 41 | struct e1000_hw_stats; |
42 | 42 | ||
43 | /* Enumerated types specific to the e1000 hardware */ | 43 | /* Enumerated types specific to the e1000 hardware */ |
44 | /* Media Access Controlers */ | 44 | /* Media Access Controllers */ |
45 | typedef enum { | 45 | typedef enum { |
46 | e1000_undefined = 0, | 46 | e1000_undefined = 0, |
47 | e1000_82542_rev2_0, | 47 | e1000_82542_rev2_0, |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 4ff88a683f61..de69c54301c1 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2233,7 +2233,7 @@ static void e1000_set_rx_mode(struct net_device *netdev) | |||
2233 | * addresses take precedence to avoid disabling unicast filtering | 2233 | * addresses take precedence to avoid disabling unicast filtering |
2234 | * when possible. | 2234 | * when possible. |
2235 | * | 2235 | * |
2236 | * RAR 0 is used for the station MAC adddress | 2236 | * RAR 0 is used for the station MAC address |
2237 | * if there are not 14 addresses, go ahead and clear the filters | 2237 | * if there are not 14 addresses, go ahead and clear the filters |
2238 | */ | 2238 | */ |
2239 | i = 1; | 2239 | i = 1; |
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index cb6c7b1c1fb8..1397da118f0d 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c | |||
@@ -328,7 +328,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter) | |||
328 | 328 | ||
329 | /* | 329 | /* |
330 | * Ensure that the inter-port SWSM.SMBI lock bit is clear before | 330 | * Ensure that the inter-port SWSM.SMBI lock bit is clear before |
331 | * first NVM or PHY acess. This should be done for single-port | 331 | * first NVM or PHY access. This should be done for single-port |
332 | * devices, and for one port only on dual-port devices so that | 332 | * devices, and for one port only on dual-port devices so that |
333 | * for those devices we can still use the SMBI lock to synchronize | 333 | * for those devices we can still use the SMBI lock to synchronize |
334 | * inter-port accesses to the PHY & NVM. | 334 | * inter-port accesses to the PHY & NVM. |
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 5328a2927731..5bb65b7382db 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -321,7 +321,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) | |||
321 | } | 321 | } |
322 | 322 | ||
323 | /* | 323 | /* |
324 | * Reset the PHY before any acccess to it. Doing so, ensures that | 324 | * Reset the PHY before any access to it. Doing so, ensures that |
325 | * the PHY is in a known good state before we read/write PHY registers. | 325 | * the PHY is in a known good state before we read/write PHY registers. |
326 | * The generic reset is sufficient here, because we haven't determined | 326 | * The generic reset is sufficient here, because we haven't determined |
327 | * the PHY type yet. | 327 | * the PHY type yet. |
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index a640f1c369ae..00f89e8a9fa0 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c | |||
@@ -2986,7 +2986,7 @@ s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) | |||
2986 | } | 2986 | } |
2987 | 2987 | ||
2988 | /** | 2988 | /** |
2989 | * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page | 2989 | * e1000_get_phy_addr_for_hv_page - Get PHY address based on page |
2990 | * @page: page to be accessed | 2990 | * @page: page to be accessed |
2991 | **/ | 2991 | **/ |
2992 | static u32 e1000_get_phy_addr_for_hv_page(u32 page) | 2992 | static u32 e1000_get_phy_addr_for_hv_page(u32 page) |
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c index 4fa8d2a4aef3..eb35951a2442 100644 --- a/drivers/net/eepro.c +++ b/drivers/net/eepro.c | |||
@@ -1761,7 +1761,7 @@ module_param_array(io, int, NULL, 0); | |||
1761 | module_param_array(irq, int, NULL, 0); | 1761 | module_param_array(irq, int, NULL, 0); |
1762 | module_param_array(mem, int, NULL, 0); | 1762 | module_param_array(mem, int, NULL, 0); |
1763 | module_param(autodetect, int, 0); | 1763 | module_param(autodetect, int, 0); |
1764 | MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)"); | 1764 | MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base address(es)"); |
1765 | MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)"); | 1765 | MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)"); |
1766 | MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)"); | 1766 | MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)"); |
1767 | MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)"); | 1767 | MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)"); |
diff --git a/drivers/net/irda/donauboe.h b/drivers/net/irda/donauboe.h index 4dc39e5f0156..77fcf4459161 100644 --- a/drivers/net/irda/donauboe.h +++ b/drivers/net/irda/donauboe.h | |||
@@ -30,7 +30,7 @@ | |||
30 | * or the type-DO IR port. | 30 | * or the type-DO IR port. |
31 | * | 31 | * |
32 | * IrDA chip set list from Toshiba Computer Engineering Corp. | 32 | * IrDA chip set list from Toshiba Computer Engineering Corp. |
33 | * model method maker controler Version | 33 | * model method maker controller Version |
34 | * Portege 320CT FIR,SIR Toshiba Oboe(Triangle) | 34 | * Portege 320CT FIR,SIR Toshiba Oboe(Triangle) |
35 | * Portege 3010CT FIR,SIR Toshiba Oboe(Sydney) | 35 | * Portege 3010CT FIR,SIR Toshiba Oboe(Sydney) |
36 | * Portege 3015CT FIR,SIR Toshiba Oboe(Sydney) | 36 | * Portege 3015CT FIR,SIR Toshiba Oboe(Sydney) |
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 8d316d9cd29d..a21f5817685b 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c | |||
@@ -1079,7 +1079,7 @@ s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc) | |||
1079 | 1079 | ||
1080 | /* | 1080 | /* |
1081 | * The defaults in the HW for RX PB 1-7 are not zero and so should be | 1081 | * The defaults in the HW for RX PB 1-7 are not zero and so should be |
1082 | * intialized to zero for non DCB mode otherwise actual total RX PB | 1082 | * initialized to zero for non DCB mode otherwise actual total RX PB |
1083 | * would be bigger than programmed and filter space would run into | 1083 | * would be bigger than programmed and filter space would run into |
1084 | * the PB 0 region. | 1084 | * the PB 0 region. |
1085 | */ | 1085 | */ |
@@ -1167,7 +1167,7 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc) | |||
1167 | 1167 | ||
1168 | /* | 1168 | /* |
1169 | * The defaults in the HW for RX PB 1-7 are not zero and so should be | 1169 | * The defaults in the HW for RX PB 1-7 are not zero and so should be |
1170 | * intialized to zero for non DCB mode otherwise actual total RX PB | 1170 | * initialized to zero for non DCB mode otherwise actual total RX PB |
1171 | * would be bigger than programmed and filter space would run into | 1171 | * would be bigger than programmed and filter space would run into |
1172 | * the PB 0 region. | 1172 | * the PB 0 region. |
1173 | */ | 1173 | */ |
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index 183765cb7f25..f35554d11441 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
@@ -238,7 +238,7 @@ static int temac_dma_bd_init(struct net_device *ndev) | |||
238 | goto out; | 238 | goto out; |
239 | } | 239 | } |
240 | /* allocate the tx and rx ring buffer descriptors. */ | 240 | /* allocate the tx and rx ring buffer descriptors. */ |
241 | /* returns a virtual addres and a physical address. */ | 241 | /* returns a virtual address and a physical address. */ |
242 | lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, | 242 | lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent, |
243 | sizeof(*lp->tx_bd_v) * TX_BD_NUM, | 243 | sizeof(*lp->tx_bd_v) * TX_BD_NUM, |
244 | &lp->tx_bd_p, GFP_KERNEL); | 244 | &lp->tx_bd_p, GFP_KERNEL); |
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 581836867098..5976d1d51df1 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c | |||
@@ -36,7 +36,7 @@ | |||
36 | Rev 1.07.06 Nov. 7 2000 Jeff Garzik <jgarzik@pobox.com> some bug fix and cleaning | 36 | Rev 1.07.06 Nov. 7 2000 Jeff Garzik <jgarzik@pobox.com> some bug fix and cleaning |
37 | Rev 1.07.05 Nov. 6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig | 37 | Rev 1.07.05 Nov. 6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig |
38 | Rev 1.07.04 Sep. 6 2000 Lei-Chun Chang added ICS1893 PHY support | 38 | Rev 1.07.04 Sep. 6 2000 Lei-Chun Chang added ICS1893 PHY support |
39 | Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E eqaulizer workaround rule | 39 | Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E equalizer workaround rule |
40 | Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update for SiS 630E and SiS 630E A1 | 40 | Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update for SiS 630E and SiS 630E A1 |
41 | Rev 1.07 Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring | 41 | Rev 1.07 Mar. 07 2000 Ollie Lho bug fix in Rx buffer ring |
42 | Rev 1.06.04 Feb. 11 2000 Jeff Garzik <jgarzik@pobox.com> softnet and init for kernel 2.4 | 42 | Rev 1.06.04 Feb. 11 2000 Jeff Garzik <jgarzik@pobox.com> softnet and init for kernel 2.4 |
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 296000bf5a25..3397618d4d96 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c | |||
@@ -12,7 +12,7 @@ | |||
12 | /* | 12 | /* |
13 | * RX HW/SW interaction overview | 13 | * RX HW/SW interaction overview |
14 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 14 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
15 | * There are 2 types of RX communication channels betwean driver and NIC. | 15 | * There are 2 types of RX communication channels between driver and NIC. |
16 | * 1) RX Free Fifo - RXF - holds descriptors of empty buffers to accept incoming | 16 | * 1) RX Free Fifo - RXF - holds descriptors of empty buffers to accept incoming |
17 | * traffic. This Fifo is filled by SW and is readen by HW. Each descriptor holds | 17 | * traffic. This Fifo is filled by SW and is readen by HW. Each descriptor holds |
18 | * info about buffer's location, size and ID. An ID field is used to identify a | 18 | * info about buffer's location, size and ID. An ID field is used to identify a |
@@ -821,7 +821,7 @@ static void bdx_setmulti(struct net_device *ndev) | |||
821 | } | 821 | } |
822 | 822 | ||
823 | /* use PMF to accept first MAC_MCST_NUM (15) addresses */ | 823 | /* use PMF to accept first MAC_MCST_NUM (15) addresses */ |
824 | /* TBD: sort addreses and write them in ascending order | 824 | /* TBD: sort addresses and write them in ascending order |
825 | * into RX_MAC_MCST regs. we skip this phase now and accept ALL | 825 | * into RX_MAC_MCST regs. we skip this phase now and accept ALL |
826 | * multicast frames throu IMF */ | 826 | * multicast frames throu IMF */ |
827 | /* accept the rest of addresses throu IMF */ | 827 | /* accept the rest of addresses throu IMF */ |
@@ -1346,7 +1346,7 @@ static void print_rxfd(struct rxf_desc *rxfd) | |||
1346 | /* | 1346 | /* |
1347 | * TX HW/SW interaction overview | 1347 | * TX HW/SW interaction overview |
1348 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 1348 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
1349 | * There are 2 types of TX communication channels betwean driver and NIC. | 1349 | * There are 2 types of TX communication channels between driver and NIC. |
1350 | * 1) TX Free Fifo - TXF - holds ack descriptors for sent packets | 1350 | * 1) TX Free Fifo - TXF - holds ack descriptors for sent packets |
1351 | * 2) TX Data Fifo - TXD - holds descriptors of full buffers. | 1351 | * 2) TX Data Fifo - TXD - holds descriptors of full buffers. |
1352 | * | 1352 | * |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7599c457abd1..b100bd50a0d7 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1309,7 +1309,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1309 | break; | 1309 | break; |
1310 | 1310 | ||
1311 | case SIOCGIFHWADDR: | 1311 | case SIOCGIFHWADDR: |
1312 | /* Get hw addres */ | 1312 | /* Get hw address */ |
1313 | memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); | 1313 | memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN); |
1314 | ifr.ifr_hwaddr.sa_family = tun->dev->type; | 1314 | ifr.ifr_hwaddr.sa_family = tun->dev->type; |
1315 | if (copy_to_user(argp, &ifr, ifreq_len)) | 1315 | if (copy_to_user(argp, &ifr, ifreq_len)) |
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index cab96ad49e60..09cac704fdd7 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
@@ -898,7 +898,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status) | |||
898 | set_mii_flow_control(vptr); | 898 | set_mii_flow_control(vptr); |
899 | 899 | ||
900 | /* | 900 | /* |
901 | Check if new status is consisent with current status | 901 | Check if new status is consistent with current status |
902 | if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE) || | 902 | if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE) || |
903 | (mii_status==curr_status)) { | 903 | (mii_status==curr_status)) { |
904 | vptr->mii_status=mii_check_media_mode(vptr->mac_regs); | 904 | vptr->mii_status=mii_check_media_mode(vptr->mac_regs); |
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 8c3103fb6442..d48486d6afa1 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h | |||
@@ -1695,7 +1695,7 @@ struct vxge_hw_device_stats_sw_err { | |||
1695 | * struct vxge_hw_device_stats - Contains HW per-device statistics, | 1695 | * struct vxge_hw_device_stats - Contains HW per-device statistics, |
1696 | * including hw. | 1696 | * including hw. |
1697 | * @devh: HW device handle. | 1697 | * @devh: HW device handle. |
1698 | * @dma_addr: DMA addres of the %hw_info. Given to device to fill-in the stats. | 1698 | * @dma_addr: DMA address of the %hw_info. Given to device to fill-in the stats. |
1699 | * @hw_info_dmah: DMA handle used to map hw statistics onto the device memory | 1699 | * @hw_info_dmah: DMA handle used to map hw statistics onto the device memory |
1700 | * space. | 1700 | * space. |
1701 | * @hw_info_dma_acch: One more DMA handle used subsequently to free the | 1701 | * @hw_info_dma_acch: One more DMA handle used subsequently to free the |
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 34cff6ce6d27..4578e5b4b411 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c | |||
@@ -125,7 +125,7 @@ static u32 dscc4_pci_config_store[16]; | |||
125 | /* Module parameters */ | 125 | /* Module parameters */ |
126 | 126 | ||
127 | MODULE_AUTHOR("Maintainer: Francois Romieu <romieu@cogenit.fr>"); | 127 | MODULE_AUTHOR("Maintainer: Francois Romieu <romieu@cogenit.fr>"); |
128 | MODULE_DESCRIPTION("Siemens PEB20534 PCI Controler"); | 128 | MODULE_DESCRIPTION("Siemens PEB20534 PCI Controller"); |
129 | MODULE_LICENSE("GPL"); | 129 | MODULE_LICENSE("GPL"); |
130 | module_param(debug, int, 0); | 130 | module_param(debug, int, 0); |
131 | MODULE_PARM_DESC(debug,"Enable/disable extra messages"); | 131 | MODULE_PARM_DESC(debug,"Enable/disable extra messages"); |
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index f0603327aafa..65bc334ed57b 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -232,7 +232,7 @@ int i2400m_check_mac_addr(struct i2400m *i2400m) | |||
232 | result); | 232 | result); |
233 | goto error; | 233 | goto error; |
234 | } | 234 | } |
235 | /* Extract MAC addresss */ | 235 | /* Extract MAC address */ |
236 | ddi = (void *) skb->data; | 236 | ddi = (void *) skb->data; |
237 | BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address)); | 237 | BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address)); |
238 | d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n", | 238 | d_printf(2, dev, "GET DEVICE INFO: mac addr %pM\n", |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 17ecaa41a807..030cbfd31704 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -186,7 +186,7 @@ enum { | |||
186 | * struct i2400m_poke_table - Hardware poke table for the Intel 2400m | 186 | * struct i2400m_poke_table - Hardware poke table for the Intel 2400m |
187 | * | 187 | * |
188 | * This structure will be used to create a device specific poke table | 188 | * This structure will be used to create a device specific poke table |
189 | * to put the device in a consistant state at boot time. | 189 | * to put the device in a consistent state at boot time. |
190 | * | 190 | * |
191 | * @address: The device address to poke | 191 | * @address: The device address to poke |
192 | * | 192 | * |
@@ -703,7 +703,7 @@ enum i2400m_bm_cmd_flags { | |||
703 | * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot | 703 | * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot |
704 | * rom after reading the MAC address. This is quite a dirty hack, | 704 | * rom after reading the MAC address. This is quite a dirty hack, |
705 | * if you ask me -- the device requires the bootrom to be | 705 | * if you ask me -- the device requires the bootrom to be |
706 | * intialized after reading the MAC address. | 706 | * initialized after reading the MAC address. |
707 | */ | 707 | */ |
708 | enum i2400m_bri { | 708 | enum i2400m_bri { |
709 | I2400M_BRI_SOFT = 1 << 1, | 709 | I2400M_BRI_SOFT = 1 << 1, |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 7ad05d401ab5..fd14b9103951 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -1064,7 +1064,7 @@ | |||
1064 | /* | 1064 | /* |
1065 | * EEPROM command register | 1065 | * EEPROM command register |
1066 | */ | 1066 | */ |
1067 | #define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ | 1067 | #define AR5K_EEPROM_CMD 0x6008 /* Register Address */ |
1068 | #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ | 1068 | #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ |
1069 | #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ | 1069 | #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ |
1070 | #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ | 1070 | #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ |
@@ -1084,7 +1084,7 @@ | |||
1084 | /* | 1084 | /* |
1085 | * EEPROM config register | 1085 | * EEPROM config register |
1086 | */ | 1086 | */ |
1087 | #define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ | 1087 | #define AR5K_EEPROM_CFG 0x6010 /* Register Address */ |
1088 | #define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ | 1088 | #define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ |
1089 | #define AR5K_EEPROM_CFG_SIZE_AUTO 0 | 1089 | #define AR5K_EEPROM_CFG_SIZE_AUTO 0 |
1090 | #define AR5K_EEPROM_CFG_SIZE_4KBIT 1 | 1090 | #define AR5K_EEPROM_CFG_SIZE_4KBIT 1 |
@@ -1126,7 +1126,7 @@ | |||
1126 | * Second station id register (Upper 16 bits of MAC address + PCU settings) | 1126 | * Second station id register (Upper 16 bits of MAC address + PCU settings) |
1127 | */ | 1127 | */ |
1128 | #define AR5K_STA_ID1 0x8004 /* Register Address */ | 1128 | #define AR5K_STA_ID1 0x8004 /* Register Address */ |
1129 | #define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */ | 1129 | #define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC address */ |
1130 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ | 1130 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ |
1131 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ | 1131 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ |
1132 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ | 1132 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ |
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 0dc33b65e86b..be4828167012 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c | |||
@@ -1919,7 +1919,7 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev) | |||
1919 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL); | 1919 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL); |
1920 | } | 1920 | } |
1921 | 1921 | ||
1922 | /* Intialize B/G PHY power control */ | 1922 | /* Initialize B/G PHY power control */ |
1923 | static void b43_phy_init_pctl(struct b43_wldev *dev) | 1923 | static void b43_phy_init_pctl(struct b43_wldev *dev) |
1924 | { | 1924 | { |
1925 | struct ssb_bus *bus = dev->dev->bus; | 1925 | struct ssb_bus *bus = dev->dev->bus; |
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 35033dd342ce..28e477d01587 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c | |||
@@ -153,7 +153,7 @@ void b43legacy_phy_calibrate(struct b43legacy_wldev *dev) | |||
153 | phy->calibrated = 1; | 153 | phy->calibrated = 1; |
154 | } | 154 | } |
155 | 155 | ||
156 | /* intialize B PHY power control | 156 | /* initialize B PHY power control |
157 | * as described in http://bcm-specs.sipsolutions.net/InitPowerControl | 157 | * as described in http://bcm-specs.sipsolutions.net/InitPowerControl |
158 | */ | 158 | */ |
159 | static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev) | 159 | static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index a5dbfea1bfad..b5cb3be0eb4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c | |||
@@ -197,7 +197,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
197 | 197 | ||
198 | none: | 198 | none: |
199 | /* re-enable interrupts here since we don't have anything to service. */ | 199 | /* re-enable interrupts here since we don't have anything to service. */ |
200 | /* only Re-enable if diabled by irq and no schedules tasklet. */ | 200 | /* only Re-enable if disabled by irq and no schedules tasklet. */ |
201 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | 201 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) |
202 | iwl_enable_interrupts(priv); | 202 | iwl_enable_interrupts(priv); |
203 | 203 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f13a83a7e62b..36335b1b54d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -1154,7 +1154,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | /* Re-enable all interrupts */ | 1156 | /* Re-enable all interrupts */ |
1157 | /* only Re-enable if diabled by irq */ | 1157 | /* only Re-enable if disabled by irq */ |
1158 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1158 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1159 | iwl_enable_interrupts(priv); | 1159 | iwl_enable_interrupts(priv); |
1160 | 1160 | ||
@@ -1368,7 +1368,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | /* Re-enable all interrupts */ | 1370 | /* Re-enable all interrupts */ |
1371 | /* only Re-enable if diabled by irq */ | 1371 | /* only Re-enable if disabled by irq */ |
1372 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1372 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1373 | iwl_enable_interrupts(priv); | 1373 | iwl_enable_interrupts(priv); |
1374 | } | 1374 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c index a08b4e56e6b1..bb1a742a98a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-legacy.c +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c | |||
@@ -619,7 +619,7 @@ unplugged: | |||
619 | 619 | ||
620 | none: | 620 | none: |
621 | /* re-enable interrupts here since we don't have anything to service. */ | 621 | /* re-enable interrupts here since we don't have anything to service. */ |
622 | /* only Re-enable if diabled by irq */ | 622 | /* only Re-enable if disabled by irq */ |
623 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 623 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
624 | iwl_enable_interrupts(priv); | 624 | iwl_enable_interrupts(priv); |
625 | spin_unlock_irqrestore(&priv->lock, flags); | 625 | spin_unlock_irqrestore(&priv->lock, flags); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 4776323b1eba..49493d176515 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -107,7 +107,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
107 | /* | 107 | /* |
108 | * XXX: The MAC address in the command buffer is often changed from | 108 | * XXX: The MAC address in the command buffer is often changed from |
109 | * the original sent to the device. That is, the MAC address | 109 | * the original sent to the device. That is, the MAC address |
110 | * written to the command buffer often is not the same MAC adress | 110 | * written to the command buffer often is not the same MAC address |
111 | * read from the command buffer when the command returns. This | 111 | * read from the command buffer when the command returns. This |
112 | * issue has not yet been resolved and this debugging is left to | 112 | * issue has not yet been resolved and this debugging is left to |
113 | * observe the problem. | 113 | * observe the problem. |
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 2c8cc954d1b6..ec2c75d77cea 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
@@ -630,7 +630,7 @@ islpci_alloc_memory(islpci_private *priv) | |||
630 | printk(KERN_DEBUG "islpci_alloc_memory\n"); | 630 | printk(KERN_DEBUG "islpci_alloc_memory\n"); |
631 | #endif | 631 | #endif |
632 | 632 | ||
633 | /* remap the PCI device base address to accessable */ | 633 | /* remap the PCI device base address to accessible */ |
634 | if (!(priv->device_base = | 634 | if (!(priv->device_base = |
635 | ioremap(pci_resource_start(priv->pdev, 0), | 635 | ioremap(pci_resource_start(priv->pdev, 0), |
636 | ISL38XX_PCI_MEM_SIZE))) { | 636 | ISL38XX_PCI_MEM_SIZE))) { |
@@ -709,7 +709,7 @@ islpci_alloc_memory(islpci_private *priv) | |||
709 | PCI_DMA_FROMDEVICE); | 709 | PCI_DMA_FROMDEVICE); |
710 | if (!priv->pci_map_rx_address[counter]) { | 710 | if (!priv->pci_map_rx_address[counter]) { |
711 | /* error mapping the buffer to device | 711 | /* error mapping the buffer to device |
712 | accessable memory address */ | 712 | accessible memory address */ |
713 | printk(KERN_ERR "failed to map skb DMA'able\n"); | 713 | printk(KERN_ERR "failed to map skb DMA'able\n"); |
714 | goto out_free; | 714 | goto out_free; |
715 | } | 715 | } |
@@ -773,7 +773,7 @@ islpci_free_memory(islpci_private *priv) | |||
773 | priv->data_low_rx[counter] = NULL; | 773 | priv->data_low_rx[counter] = NULL; |
774 | } | 774 | } |
775 | 775 | ||
776 | /* Free the acces control list and the WPA list */ | 776 | /* Free the access control list and the WPA list */ |
777 | prism54_acl_clean(&priv->acl); | 777 | prism54_acl_clean(&priv->acl); |
778 | prism54_wpa_bss_ie_clean(priv); | 778 | prism54_wpa_bss_ie_clean(priv); |
779 | mgt_clean(priv); | 779 | mgt_clean(priv); |
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 2fc52bc2d7dd..d44f8e20cce0 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c | |||
@@ -450,7 +450,7 @@ islpci_eth_receive(islpci_private *priv) | |||
450 | MAX_FRAGMENT_SIZE_RX + 2, | 450 | MAX_FRAGMENT_SIZE_RX + 2, |
451 | PCI_DMA_FROMDEVICE); | 451 | PCI_DMA_FROMDEVICE); |
452 | if (unlikely(!priv->pci_map_rx_address[index])) { | 452 | if (unlikely(!priv->pci_map_rx_address[index])) { |
453 | /* error mapping the buffer to device accessable memory address */ | 453 | /* error mapping the buffer to device accessible memory address */ |
454 | DEBUG(SHOW_ERROR_MESSAGES, | 454 | DEBUG(SHOW_ERROR_MESSAGES, |
455 | "Error mapping DMA address\n"); | 455 | "Error mapping DMA address\n"); |
456 | 456 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 658542d2efe1..f3da051df39e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -273,7 +273,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
273 | intf->beacon = entry; | 273 | intf->beacon = entry; |
274 | 274 | ||
275 | /* | 275 | /* |
276 | * The MAC adddress must be configured after the device | 276 | * The MAC address must be configured after the device |
277 | * has been initialized. Otherwise the device can reset | 277 | * has been initialized. Otherwise the device can reset |
278 | * the MAC registers. | 278 | * the MAC registers. |
279 | * The BSSID address must only be configured in AP mode, | 279 | * The BSSID address must only be configured in AP mode, |
diff --git a/drivers/net/wireless/wl1251/acx.h b/drivers/net/wireless/wl1251/acx.h index e54b21a4f8b1..efcc3aaca14f 100644 --- a/drivers/net/wireless/wl1251/acx.h +++ b/drivers/net/wireless/wl1251/acx.h | |||
@@ -1272,10 +1272,10 @@ struct wl1251_acx_tid_cfg { | |||
1272 | /* OBSOLETE */ | 1272 | /* OBSOLETE */ |
1273 | #define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6) | 1273 | #define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6) |
1274 | 1274 | ||
1275 | /* Trace meassge on MBOX #A */ | 1275 | /* Trace message on MBOX #A */ |
1276 | #define WL1251_ACX_INTR_TRACE_A BIT(7) | 1276 | #define WL1251_ACX_INTR_TRACE_A BIT(7) |
1277 | 1277 | ||
1278 | /* Trace meassge on MBOX #B */ | 1278 | /* Trace message on MBOX #B */ |
1279 | #define WL1251_ACX_INTR_TRACE_B BIT(8) | 1279 | #define WL1251_ACX_INTR_TRACE_B BIT(8) |
1280 | 1280 | ||
1281 | /* Command processing completion */ | 1281 | /* Command processing completion */ |
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index 13fbeeccf609..c0ce2c8b43b8 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h | |||
@@ -419,7 +419,7 @@ void wl1251_disable_interrupts(struct wl1251 *wl); | |||
419 | #define WL1251_FW_NAME "wl1251-fw.bin" | 419 | #define WL1251_FW_NAME "wl1251-fw.bin" |
420 | #define WL1251_NVS_NAME "wl1251-nvs.bin" | 420 | #define WL1251_NVS_NAME "wl1251-nvs.bin" |
421 | 421 | ||
422 | #define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */ | 422 | #define WL1251_POWER_ON_SLEEP 10 /* in milliseconds */ |
423 | 423 | ||
424 | #define WL1251_PART_DOWN_MEM_START 0x0 | 424 | #define WL1251_PART_DOWN_MEM_START 0x0 |
425 | #define WL1251_PART_DOWN_MEM_SIZE 0x16800 | 425 | #define WL1251_PART_DOWN_MEM_SIZE 0x16800 |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 9cbc3f40c8dd..7bd8e4db4a71 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -47,9 +47,9 @@ | |||
47 | #define WL1271_ACX_INTR_HW_AVAILABLE BIT(5) | 47 | #define WL1271_ACX_INTR_HW_AVAILABLE BIT(5) |
48 | /* The MISC bit is used for aggregation of RX, TxComplete and TX rate update */ | 48 | /* The MISC bit is used for aggregation of RX, TxComplete and TX rate update */ |
49 | #define WL1271_ACX_INTR_DATA BIT(6) | 49 | #define WL1271_ACX_INTR_DATA BIT(6) |
50 | /* Trace meassge on MBOX #A */ | 50 | /* Trace message on MBOX #A */ |
51 | #define WL1271_ACX_INTR_TRACE_A BIT(7) | 51 | #define WL1271_ACX_INTR_TRACE_A BIT(7) |
52 | /* Trace meassge on MBOX #B */ | 52 | /* Trace message on MBOX #B */ |
53 | #define WL1271_ACX_INTR_TRACE_B BIT(8) | 53 | #define WL1271_ACX_INTR_TRACE_B BIT(8) |
54 | 54 | ||
55 | #define WL1271_ACX_INTR_ALL 0xFFFFFFFF | 55 | #define WL1271_ACX_INTR_ALL 0xFFFFFFFF |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ce3d31f98c55..9050dd9b62d2 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -416,8 +416,8 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
416 | 416 | ||
417 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power | 417 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
418 | on in case is has been shut down shortly before */ | 418 | on in case is has been shut down shortly before */ |
419 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | 419 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */ |
420 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 420 | #define WL1271_POWER_ON_SLEEP 200 /* in milliseconds */ |
421 | 421 | ||
422 | /* Macros to handle wl1271.sta_rate_set */ | 422 | /* Macros to handle wl1271.sta_rate_set */ |
423 | #define HW_BG_RATES_MASK 0xffff | 423 | #define HW_BG_RATES_MASK 0xffff |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index ee82df62e646..3e5befe4d03b 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -192,7 +192,7 @@ static inline void wl3501_switch_page(struct wl3501_card *this, u8 page) | |||
192 | } | 192 | } |
193 | 193 | ||
194 | /* | 194 | /* |
195 | * Get Ethernet MAC addresss. | 195 | * Get Ethernet MAC address. |
196 | * | 196 | * |
197 | * WARNING: We switch to FPAGE0 and switc back again. | 197 | * WARNING: We switch to FPAGE0 and switc back again. |
198 | * Making sure there is no other WL function beening called by ISR. | 198 | * Making sure there is no other WL function beening called by ISR. |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig new file mode 100644 index 000000000000..ffedfd492754 --- /dev/null +++ b/drivers/nfc/Kconfig | |||
@@ -0,0 +1,30 @@ | |||
1 | # | ||
2 | # Near Field Communication (NFC) devices | ||
3 | # | ||
4 | |||
5 | menuconfig NFC_DEVICES | ||
6 | bool "NFC devices" | ||
7 | default n | ||
8 | ---help--- | ||
9 | You'll have to say Y if your computer contains an NFC device that | ||
10 | you want to use under Linux. | ||
11 | |||
12 | You can say N here if you don't have any Near Field Communication | ||
13 | devices connected to your computer. | ||
14 | |||
15 | if NFC_DEVICES | ||
16 | |||
17 | config PN544_NFC | ||
18 | tristate "PN544 NFC driver" | ||
19 | depends on I2C | ||
20 | select CRC_CCITT | ||
21 | default n | ||
22 | ---help--- | ||
23 | Say yes if you want PN544 Near Field Communication driver. | ||
24 | This is for i2c connected version. If unsure, say N here. | ||
25 | |||
26 | To compile this driver as a module, choose m here. The module will | ||
27 | be called pn544. | ||
28 | |||
29 | |||
30 | endif # NFC_DEVICES | ||
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile new file mode 100644 index 000000000000..a4efb164ec49 --- /dev/null +++ b/drivers/nfc/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for nfc devices | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PN544_NFC) += pn544.o | ||
diff --git a/drivers/nfc/pn544.c b/drivers/nfc/pn544.c new file mode 100644 index 000000000000..401c44b6eadb --- /dev/null +++ b/drivers/nfc/pn544.c | |||
@@ -0,0 +1,891 @@ | |||
1 | /* | ||
2 | * Driver for the PN544 NFC chip. | ||
3 | * | ||
4 | * Copyright (C) Nokia Corporation | ||
5 | * | ||
6 | * Author: Jari Vanhala <ext-jari.vanhala@nokia.com> | ||
7 | * Contact: Matti Aaltonen <matti.j.aaltonen@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/completion.h> | ||
24 | #include <linux/crc-ccitt.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/nfc/pn544.h> | ||
32 | #include <linux/poll.h> | ||
33 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/serial_core.h> /* for TCGETS */ | ||
35 | #include <linux/slab.h> | ||
36 | |||
37 | #define DRIVER_CARD "PN544 NFC" | ||
38 | #define DRIVER_DESC "NFC driver for PN544" | ||
39 | |||
40 | static struct i2c_device_id pn544_id_table[] = { | ||
41 | { PN544_DRIVER_NAME, 0 }, | ||
42 | { } | ||
43 | }; | ||
44 | MODULE_DEVICE_TABLE(i2c, pn544_id_table); | ||
45 | |||
46 | #define HCI_MODE 0 | ||
47 | #define FW_MODE 1 | ||
48 | |||
49 | enum pn544_state { | ||
50 | PN544_ST_COLD, | ||
51 | PN544_ST_FW_READY, | ||
52 | PN544_ST_READY, | ||
53 | }; | ||
54 | |||
55 | enum pn544_irq { | ||
56 | PN544_NONE, | ||
57 | PN544_INT, | ||
58 | }; | ||
59 | |||
60 | struct pn544_info { | ||
61 | struct miscdevice miscdev; | ||
62 | struct i2c_client *i2c_dev; | ||
63 | struct regulator_bulk_data regs[2]; | ||
64 | |||
65 | enum pn544_state state; | ||
66 | wait_queue_head_t read_wait; | ||
67 | loff_t read_offset; | ||
68 | enum pn544_irq read_irq; | ||
69 | struct mutex read_mutex; /* Serialize read_irq access */ | ||
70 | struct mutex mutex; /* Serialize info struct access */ | ||
71 | u8 *buf; | ||
72 | unsigned int buflen; | ||
73 | }; | ||
74 | |||
75 | static const char reg_vdd_io[] = "Vdd_IO"; | ||
76 | static const char reg_vbat[] = "VBat"; | ||
77 | |||
78 | /* sysfs interface */ | ||
79 | static ssize_t pn544_test(struct device *dev, | ||
80 | struct device_attribute *attr, char *buf) | ||
81 | { | ||
82 | struct pn544_info *info = dev_get_drvdata(dev); | ||
83 | struct i2c_client *client = info->i2c_dev; | ||
84 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
85 | |||
86 | return snprintf(buf, PAGE_SIZE, "%d\n", pdata->test()); | ||
87 | } | ||
88 | |||
89 | static int pn544_enable(struct pn544_info *info, int mode) | ||
90 | { | ||
91 | struct pn544_nfc_platform_data *pdata; | ||
92 | struct i2c_client *client = info->i2c_dev; | ||
93 | |||
94 | int r; | ||
95 | |||
96 | r = regulator_bulk_enable(ARRAY_SIZE(info->regs), info->regs); | ||
97 | if (r < 0) | ||
98 | return r; | ||
99 | |||
100 | pdata = client->dev.platform_data; | ||
101 | info->read_irq = PN544_NONE; | ||
102 | if (pdata->enable) | ||
103 | pdata->enable(mode); | ||
104 | |||
105 | if (mode) { | ||
106 | info->state = PN544_ST_FW_READY; | ||
107 | dev_dbg(&client->dev, "now in FW-mode\n"); | ||
108 | } else { | ||
109 | info->state = PN544_ST_READY; | ||
110 | dev_dbg(&client->dev, "now in HCI-mode\n"); | ||
111 | } | ||
112 | |||
113 | usleep_range(10000, 15000); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static void pn544_disable(struct pn544_info *info) | ||
119 | { | ||
120 | struct pn544_nfc_platform_data *pdata; | ||
121 | struct i2c_client *client = info->i2c_dev; | ||
122 | |||
123 | pdata = client->dev.platform_data; | ||
124 | if (pdata->disable) | ||
125 | pdata->disable(); | ||
126 | |||
127 | info->state = PN544_ST_COLD; | ||
128 | |||
129 | dev_dbg(&client->dev, "Now in OFF-mode\n"); | ||
130 | |||
131 | msleep(PN544_RESETVEN_TIME); | ||
132 | |||
133 | info->read_irq = PN544_NONE; | ||
134 | regulator_bulk_disable(ARRAY_SIZE(info->regs), info->regs); | ||
135 | } | ||
136 | |||
137 | static int check_crc(u8 *buf, int buflen) | ||
138 | { | ||
139 | u8 len; | ||
140 | u16 crc; | ||
141 | |||
142 | len = buf[0] + 1; | ||
143 | if (len < 4 || len != buflen || len > PN544_MSG_MAX_SIZE) { | ||
144 | pr_err(PN544_DRIVER_NAME | ||
145 | ": CRC; corrupt packet len %u (%d)\n", len, buflen); | ||
146 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
147 | 16, 2, buf, buflen, false); | ||
148 | return -EPERM; | ||
149 | } | ||
150 | crc = crc_ccitt(0xffff, buf, len - 2); | ||
151 | crc = ~crc; | ||
152 | |||
153 | if (buf[len-2] != (crc & 0xff) || buf[len-1] != (crc >> 8)) { | ||
154 | pr_err(PN544_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n", | ||
155 | crc, buf[len-1], buf[len-2]); | ||
156 | |||
157 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
158 | 16, 2, buf, buflen, false); | ||
159 | return -EPERM; | ||
160 | } | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static int pn544_i2c_write(struct i2c_client *client, u8 *buf, int len) | ||
165 | { | ||
166 | int r; | ||
167 | |||
168 | if (len < 4 || len != (buf[0] + 1)) { | ||
169 | dev_err(&client->dev, "%s: Illegal message length: %d\n", | ||
170 | __func__, len); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | if (check_crc(buf, len)) | ||
175 | return -EINVAL; | ||
176 | |||
177 | usleep_range(3000, 6000); | ||
178 | |||
179 | r = i2c_master_send(client, buf, len); | ||
180 | dev_dbg(&client->dev, "send: %d\n", r); | ||
181 | |||
182 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
183 | usleep_range(6000, 10000); | ||
184 | r = i2c_master_send(client, buf, len); | ||
185 | dev_dbg(&client->dev, "send2: %d\n", r); | ||
186 | } | ||
187 | |||
188 | if (r != len) | ||
189 | return -EREMOTEIO; | ||
190 | |||
191 | return r; | ||
192 | } | ||
193 | |||
194 | static int pn544_i2c_read(struct i2c_client *client, u8 *buf, int buflen) | ||
195 | { | ||
196 | int r; | ||
197 | u8 len; | ||
198 | |||
199 | /* | ||
200 | * You could read a packet in one go, but then you'd need to read | ||
201 | * max size and rest would be 0xff fill, so we do split reads. | ||
202 | */ | ||
203 | r = i2c_master_recv(client, &len, 1); | ||
204 | dev_dbg(&client->dev, "recv1: %d\n", r); | ||
205 | |||
206 | if (r != 1) | ||
207 | return -EREMOTEIO; | ||
208 | |||
209 | if (len < PN544_LLC_HCI_OVERHEAD) | ||
210 | len = PN544_LLC_HCI_OVERHEAD; | ||
211 | else if (len > (PN544_MSG_MAX_SIZE - 1)) | ||
212 | len = PN544_MSG_MAX_SIZE - 1; | ||
213 | |||
214 | if (1 + len > buflen) /* len+(data+crc16) */ | ||
215 | return -EMSGSIZE; | ||
216 | |||
217 | buf[0] = len; | ||
218 | |||
219 | r = i2c_master_recv(client, buf + 1, len); | ||
220 | dev_dbg(&client->dev, "recv2: %d\n", r); | ||
221 | |||
222 | if (r != len) | ||
223 | return -EREMOTEIO; | ||
224 | |||
225 | usleep_range(3000, 6000); | ||
226 | |||
227 | return r + 1; | ||
228 | } | ||
229 | |||
230 | static int pn544_fw_write(struct i2c_client *client, u8 *buf, int len) | ||
231 | { | ||
232 | int r; | ||
233 | |||
234 | dev_dbg(&client->dev, "%s\n", __func__); | ||
235 | |||
236 | if (len < PN544_FW_HEADER_SIZE || | ||
237 | (PN544_FW_HEADER_SIZE + (buf[1] << 8) + buf[2]) != len) | ||
238 | return -EINVAL; | ||
239 | |||
240 | r = i2c_master_send(client, buf, len); | ||
241 | dev_dbg(&client->dev, "fw send: %d\n", r); | ||
242 | |||
243 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
244 | usleep_range(6000, 10000); | ||
245 | r = i2c_master_send(client, buf, len); | ||
246 | dev_dbg(&client->dev, "fw send2: %d\n", r); | ||
247 | } | ||
248 | |||
249 | if (r != len) | ||
250 | return -EREMOTEIO; | ||
251 | |||
252 | return r; | ||
253 | } | ||
254 | |||
255 | static int pn544_fw_read(struct i2c_client *client, u8 *buf, int buflen) | ||
256 | { | ||
257 | int r, len; | ||
258 | |||
259 | if (buflen < PN544_FW_HEADER_SIZE) | ||
260 | return -EINVAL; | ||
261 | |||
262 | r = i2c_master_recv(client, buf, PN544_FW_HEADER_SIZE); | ||
263 | dev_dbg(&client->dev, "FW recv1: %d\n", r); | ||
264 | |||
265 | if (r < 0) | ||
266 | return r; | ||
267 | |||
268 | if (r < PN544_FW_HEADER_SIZE) | ||
269 | return -EINVAL; | ||
270 | |||
271 | len = (buf[1] << 8) + buf[2]; | ||
272 | if (len == 0) /* just header, no additional data */ | ||
273 | return r; | ||
274 | |||
275 | if (len > buflen - PN544_FW_HEADER_SIZE) | ||
276 | return -EMSGSIZE; | ||
277 | |||
278 | r = i2c_master_recv(client, buf + PN544_FW_HEADER_SIZE, len); | ||
279 | dev_dbg(&client->dev, "fw recv2: %d\n", r); | ||
280 | |||
281 | if (r != len) | ||
282 | return -EINVAL; | ||
283 | |||
284 | return r + PN544_FW_HEADER_SIZE; | ||
285 | } | ||
286 | |||
287 | static irqreturn_t pn544_irq_thread_fn(int irq, void *dev_id) | ||
288 | { | ||
289 | struct pn544_info *info = dev_id; | ||
290 | struct i2c_client *client = info->i2c_dev; | ||
291 | |||
292 | BUG_ON(!info); | ||
293 | BUG_ON(irq != info->i2c_dev->irq); | ||
294 | |||
295 | dev_dbg(&client->dev, "IRQ\n"); | ||
296 | |||
297 | mutex_lock(&info->read_mutex); | ||
298 | info->read_irq = PN544_INT; | ||
299 | mutex_unlock(&info->read_mutex); | ||
300 | |||
301 | wake_up_interruptible(&info->read_wait); | ||
302 | |||
303 | return IRQ_HANDLED; | ||
304 | } | ||
305 | |||
306 | static enum pn544_irq pn544_irq_state(struct pn544_info *info) | ||
307 | { | ||
308 | enum pn544_irq irq; | ||
309 | |||
310 | mutex_lock(&info->read_mutex); | ||
311 | irq = info->read_irq; | ||
312 | mutex_unlock(&info->read_mutex); | ||
313 | /* | ||
314 | * XXX: should we check GPIO-line status directly? | ||
315 | * return pdata->irq_status() ? PN544_INT : PN544_NONE; | ||
316 | */ | ||
317 | |||
318 | return irq; | ||
319 | } | ||
320 | |||
321 | static ssize_t pn544_read(struct file *file, char __user *buf, | ||
322 | size_t count, loff_t *offset) | ||
323 | { | ||
324 | struct pn544_info *info = container_of(file->private_data, | ||
325 | struct pn544_info, miscdev); | ||
326 | struct i2c_client *client = info->i2c_dev; | ||
327 | enum pn544_irq irq; | ||
328 | size_t len; | ||
329 | int r = 0; | ||
330 | |||
331 | dev_dbg(&client->dev, "%s: info: %p, count: %zu\n", __func__, | ||
332 | info, count); | ||
333 | |||
334 | mutex_lock(&info->mutex); | ||
335 | |||
336 | if (info->state == PN544_ST_COLD) { | ||
337 | r = -ENODEV; | ||
338 | goto out; | ||
339 | } | ||
340 | |||
341 | irq = pn544_irq_state(info); | ||
342 | if (irq == PN544_NONE) { | ||
343 | if (file->f_flags & O_NONBLOCK) { | ||
344 | r = -EAGAIN; | ||
345 | goto out; | ||
346 | } | ||
347 | |||
348 | if (wait_event_interruptible(info->read_wait, | ||
349 | (info->read_irq == PN544_INT))) { | ||
350 | r = -ERESTARTSYS; | ||
351 | goto out; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | if (info->state == PN544_ST_FW_READY) { | ||
356 | len = min(count, info->buflen); | ||
357 | |||
358 | mutex_lock(&info->read_mutex); | ||
359 | r = pn544_fw_read(info->i2c_dev, info->buf, len); | ||
360 | info->read_irq = PN544_NONE; | ||
361 | mutex_unlock(&info->read_mutex); | ||
362 | |||
363 | if (r < 0) { | ||
364 | dev_err(&info->i2c_dev->dev, "FW read failed: %d\n", r); | ||
365 | goto out; | ||
366 | } | ||
367 | |||
368 | print_hex_dump(KERN_DEBUG, "FW read: ", DUMP_PREFIX_NONE, | ||
369 | 16, 2, info->buf, r, false); | ||
370 | |||
371 | *offset += r; | ||
372 | if (copy_to_user(buf, info->buf, r)) { | ||
373 | r = -EFAULT; | ||
374 | goto out; | ||
375 | } | ||
376 | } else { | ||
377 | len = min(count, info->buflen); | ||
378 | |||
379 | mutex_lock(&info->read_mutex); | ||
380 | r = pn544_i2c_read(info->i2c_dev, info->buf, len); | ||
381 | info->read_irq = PN544_NONE; | ||
382 | mutex_unlock(&info->read_mutex); | ||
383 | |||
384 | if (r < 0) { | ||
385 | dev_err(&info->i2c_dev->dev, "read failed (%d)\n", r); | ||
386 | goto out; | ||
387 | } | ||
388 | print_hex_dump(KERN_DEBUG, "read: ", DUMP_PREFIX_NONE, | ||
389 | 16, 2, info->buf, r, false); | ||
390 | |||
391 | *offset += r; | ||
392 | if (copy_to_user(buf, info->buf, r)) { | ||
393 | r = -EFAULT; | ||
394 | goto out; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | out: | ||
399 | mutex_unlock(&info->mutex); | ||
400 | |||
401 | return r; | ||
402 | } | ||
403 | |||
404 | static unsigned int pn544_poll(struct file *file, poll_table *wait) | ||
405 | { | ||
406 | struct pn544_info *info = container_of(file->private_data, | ||
407 | struct pn544_info, miscdev); | ||
408 | struct i2c_client *client = info->i2c_dev; | ||
409 | int r = 0; | ||
410 | |||
411 | dev_dbg(&client->dev, "%s: info: %p\n", __func__, info); | ||
412 | |||
413 | mutex_lock(&info->mutex); | ||
414 | |||
415 | if (info->state == PN544_ST_COLD) { | ||
416 | r = -ENODEV; | ||
417 | goto out; | ||
418 | } | ||
419 | |||
420 | poll_wait(file, &info->read_wait, wait); | ||
421 | |||
422 | if (pn544_irq_state(info) == PN544_INT) { | ||
423 | r = POLLIN | POLLRDNORM; | ||
424 | goto out; | ||
425 | } | ||
426 | out: | ||
427 | mutex_unlock(&info->mutex); | ||
428 | |||
429 | return r; | ||
430 | } | ||
431 | |||
432 | static ssize_t pn544_write(struct file *file, const char __user *buf, | ||
433 | size_t count, loff_t *ppos) | ||
434 | { | ||
435 | struct pn544_info *info = container_of(file->private_data, | ||
436 | struct pn544_info, miscdev); | ||
437 | struct i2c_client *client = info->i2c_dev; | ||
438 | ssize_t len; | ||
439 | int r; | ||
440 | |||
441 | dev_dbg(&client->dev, "%s: info: %p, count %zu\n", __func__, | ||
442 | info, count); | ||
443 | |||
444 | mutex_lock(&info->mutex); | ||
445 | |||
446 | if (info->state == PN544_ST_COLD) { | ||
447 | r = -ENODEV; | ||
448 | goto out; | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * XXX: should we detect rset-writes and clean possible | ||
453 | * read_irq state | ||
454 | */ | ||
455 | if (info->state == PN544_ST_FW_READY) { | ||
456 | size_t fw_len; | ||
457 | |||
458 | if (count < PN544_FW_HEADER_SIZE) { | ||
459 | r = -EINVAL; | ||
460 | goto out; | ||
461 | } | ||
462 | |||
463 | len = min(count, info->buflen); | ||
464 | if (copy_from_user(info->buf, buf, len)) { | ||
465 | r = -EFAULT; | ||
466 | goto out; | ||
467 | } | ||
468 | |||
469 | print_hex_dump(KERN_DEBUG, "FW write: ", DUMP_PREFIX_NONE, | ||
470 | 16, 2, info->buf, len, false); | ||
471 | |||
472 | fw_len = PN544_FW_HEADER_SIZE + (info->buf[1] << 8) + | ||
473 | info->buf[2]; | ||
474 | |||
475 | if (len > fw_len) /* 1 msg at a time */ | ||
476 | len = fw_len; | ||
477 | |||
478 | r = pn544_fw_write(info->i2c_dev, info->buf, len); | ||
479 | } else { | ||
480 | if (count < PN544_LLC_MIN_SIZE) { | ||
481 | r = -EINVAL; | ||
482 | goto out; | ||
483 | } | ||
484 | |||
485 | len = min(count, info->buflen); | ||
486 | if (copy_from_user(info->buf, buf, len)) { | ||
487 | r = -EFAULT; | ||
488 | goto out; | ||
489 | } | ||
490 | |||
491 | print_hex_dump(KERN_DEBUG, "write: ", DUMP_PREFIX_NONE, | ||
492 | 16, 2, info->buf, len, false); | ||
493 | |||
494 | if (len > (info->buf[0] + 1)) /* 1 msg at a time */ | ||
495 | len = info->buf[0] + 1; | ||
496 | |||
497 | r = pn544_i2c_write(info->i2c_dev, info->buf, len); | ||
498 | } | ||
499 | out: | ||
500 | mutex_unlock(&info->mutex); | ||
501 | |||
502 | return r; | ||
503 | |||
504 | } | ||
505 | |||
506 | static long pn544_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
507 | { | ||
508 | struct pn544_info *info = container_of(file->private_data, | ||
509 | struct pn544_info, miscdev); | ||
510 | struct i2c_client *client = info->i2c_dev; | ||
511 | struct pn544_nfc_platform_data *pdata; | ||
512 | unsigned int val; | ||
513 | int r = 0; | ||
514 | |||
515 | dev_dbg(&client->dev, "%s: info: %p, cmd: 0x%x\n", __func__, info, cmd); | ||
516 | |||
517 | mutex_lock(&info->mutex); | ||
518 | |||
519 | if (info->state == PN544_ST_COLD) { | ||
520 | r = -ENODEV; | ||
521 | goto out; | ||
522 | } | ||
523 | |||
524 | pdata = info->i2c_dev->dev.platform_data; | ||
525 | switch (cmd) { | ||
526 | case PN544_GET_FW_MODE: | ||
527 | dev_dbg(&client->dev, "%s: PN544_GET_FW_MODE\n", __func__); | ||
528 | |||
529 | val = (info->state == PN544_ST_FW_READY); | ||
530 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) { | ||
531 | r = -EFAULT; | ||
532 | goto out; | ||
533 | } | ||
534 | |||
535 | break; | ||
536 | |||
537 | case PN544_SET_FW_MODE: | ||
538 | dev_dbg(&client->dev, "%s: PN544_SET_FW_MODE\n", __func__); | ||
539 | |||
540 | if (copy_from_user(&val, (void __user *)arg, sizeof(val))) { | ||
541 | r = -EFAULT; | ||
542 | goto out; | ||
543 | } | ||
544 | |||
545 | if (val) { | ||
546 | if (info->state == PN544_ST_FW_READY) | ||
547 | break; | ||
548 | |||
549 | pn544_disable(info); | ||
550 | r = pn544_enable(info, FW_MODE); | ||
551 | if (r < 0) | ||
552 | goto out; | ||
553 | } else { | ||
554 | if (info->state == PN544_ST_READY) | ||
555 | break; | ||
556 | pn544_disable(info); | ||
557 | r = pn544_enable(info, HCI_MODE); | ||
558 | if (r < 0) | ||
559 | goto out; | ||
560 | } | ||
561 | file->f_pos = info->read_offset; | ||
562 | break; | ||
563 | |||
564 | case TCGETS: | ||
565 | dev_dbg(&client->dev, "%s: TCGETS\n", __func__); | ||
566 | |||
567 | r = -ENOIOCTLCMD; | ||
568 | break; | ||
569 | |||
570 | default: | ||
571 | dev_err(&client->dev, "Unknown ioctl 0x%x\n", cmd); | ||
572 | r = -ENOIOCTLCMD; | ||
573 | break; | ||
574 | } | ||
575 | |||
576 | out: | ||
577 | mutex_unlock(&info->mutex); | ||
578 | |||
579 | return r; | ||
580 | } | ||
581 | |||
582 | static int pn544_open(struct inode *inode, struct file *file) | ||
583 | { | ||
584 | struct pn544_info *info = container_of(file->private_data, | ||
585 | struct pn544_info, miscdev); | ||
586 | struct i2c_client *client = info->i2c_dev; | ||
587 | int r = 0; | ||
588 | |||
589 | dev_dbg(&client->dev, "%s: info: %p, client %p\n", __func__, | ||
590 | info, info->i2c_dev); | ||
591 | |||
592 | mutex_lock(&info->mutex); | ||
593 | |||
594 | /* | ||
595 | * Only 1 at a time. | ||
596 | * XXX: maybe user (counter) would work better | ||
597 | */ | ||
598 | if (info->state != PN544_ST_COLD) { | ||
599 | r = -EBUSY; | ||
600 | goto out; | ||
601 | } | ||
602 | |||
603 | file->f_pos = info->read_offset; | ||
604 | r = pn544_enable(info, HCI_MODE); | ||
605 | |||
606 | out: | ||
607 | mutex_unlock(&info->mutex); | ||
608 | return r; | ||
609 | } | ||
610 | |||
611 | static int pn544_close(struct inode *inode, struct file *file) | ||
612 | { | ||
613 | struct pn544_info *info = container_of(file->private_data, | ||
614 | struct pn544_info, miscdev); | ||
615 | struct i2c_client *client = info->i2c_dev; | ||
616 | |||
617 | dev_dbg(&client->dev, "%s: info: %p, client %p\n", | ||
618 | __func__, info, info->i2c_dev); | ||
619 | |||
620 | mutex_lock(&info->mutex); | ||
621 | pn544_disable(info); | ||
622 | mutex_unlock(&info->mutex); | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static const struct file_operations pn544_fops = { | ||
628 | .owner = THIS_MODULE, | ||
629 | .llseek = no_llseek, | ||
630 | .read = pn544_read, | ||
631 | .write = pn544_write, | ||
632 | .poll = pn544_poll, | ||
633 | .open = pn544_open, | ||
634 | .release = pn544_close, | ||
635 | .unlocked_ioctl = pn544_ioctl, | ||
636 | }; | ||
637 | |||
638 | #ifdef CONFIG_PM | ||
639 | static int pn544_suspend(struct device *dev) | ||
640 | { | ||
641 | struct i2c_client *client = to_i2c_client(dev); | ||
642 | struct pn544_info *info; | ||
643 | int r = 0; | ||
644 | |||
645 | dev_info(&client->dev, "***\n%s: client %p\n***\n", __func__, client); | ||
646 | |||
647 | info = i2c_get_clientdata(client); | ||
648 | dev_info(&client->dev, "%s: info: %p, client %p\n", __func__, | ||
649 | info, client); | ||
650 | |||
651 | mutex_lock(&info->mutex); | ||
652 | |||
653 | switch (info->state) { | ||
654 | case PN544_ST_FW_READY: | ||
655 | /* Do not suspend while upgrading FW, please! */ | ||
656 | r = -EPERM; | ||
657 | break; | ||
658 | |||
659 | case PN544_ST_READY: | ||
660 | /* | ||
661 | * CHECK: Device should be in standby-mode. No way to check? | ||
662 | * Allowing low power mode for the regulator is potentially | ||
663 | * dangerous if pn544 does not go to suspension. | ||
664 | */ | ||
665 | break; | ||
666 | |||
667 | case PN544_ST_COLD: | ||
668 | break; | ||
669 | }; | ||
670 | |||
671 | mutex_unlock(&info->mutex); | ||
672 | return r; | ||
673 | } | ||
674 | |||
675 | static int pn544_resume(struct device *dev) | ||
676 | { | ||
677 | struct i2c_client *client = to_i2c_client(dev); | ||
678 | struct pn544_info *info = i2c_get_clientdata(client); | ||
679 | int r = 0; | ||
680 | |||
681 | dev_dbg(&client->dev, "%s: info: %p, client %p\n", __func__, | ||
682 | info, client); | ||
683 | |||
684 | mutex_lock(&info->mutex); | ||
685 | |||
686 | switch (info->state) { | ||
687 | case PN544_ST_READY: | ||
688 | /* | ||
689 | * CHECK: If regulator low power mode is allowed in | ||
690 | * pn544_suspend, we should go back to normal mode | ||
691 | * here. | ||
692 | */ | ||
693 | break; | ||
694 | |||
695 | case PN544_ST_COLD: | ||
696 | break; | ||
697 | |||
698 | case PN544_ST_FW_READY: | ||
699 | break; | ||
700 | }; | ||
701 | |||
702 | mutex_unlock(&info->mutex); | ||
703 | |||
704 | return r; | ||
705 | } | ||
706 | |||
707 | static SIMPLE_DEV_PM_OPS(pn544_pm_ops, pn544_suspend, pn544_resume); | ||
708 | #endif | ||
709 | |||
710 | static struct device_attribute pn544_attr = | ||
711 | __ATTR(nfc_test, S_IRUGO, pn544_test, NULL); | ||
712 | |||
713 | static int __devinit pn544_probe(struct i2c_client *client, | ||
714 | const struct i2c_device_id *id) | ||
715 | { | ||
716 | struct pn544_info *info; | ||
717 | struct pn544_nfc_platform_data *pdata; | ||
718 | int r = 0; | ||
719 | |||
720 | dev_dbg(&client->dev, "%s\n", __func__); | ||
721 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
722 | |||
723 | /* private data allocation */ | ||
724 | info = kzalloc(sizeof(struct pn544_info), GFP_KERNEL); | ||
725 | if (!info) { | ||
726 | dev_err(&client->dev, | ||
727 | "Cannot allocate memory for pn544_info.\n"); | ||
728 | r = -ENOMEM; | ||
729 | goto err_info_alloc; | ||
730 | } | ||
731 | |||
732 | info->buflen = max(PN544_MSG_MAX_SIZE, PN544_MAX_I2C_TRANSFER); | ||
733 | info->buf = kzalloc(info->buflen, GFP_KERNEL); | ||
734 | if (!info->buf) { | ||
735 | dev_err(&client->dev, | ||
736 | "Cannot allocate memory for pn544_info->buf.\n"); | ||
737 | r = -ENOMEM; | ||
738 | goto err_buf_alloc; | ||
739 | } | ||
740 | |||
741 | info->regs[0].supply = reg_vdd_io; | ||
742 | info->regs[1].supply = reg_vbat; | ||
743 | r = regulator_bulk_get(&client->dev, ARRAY_SIZE(info->regs), | ||
744 | info->regs); | ||
745 | if (r < 0) | ||
746 | goto err_kmalloc; | ||
747 | |||
748 | info->i2c_dev = client; | ||
749 | info->state = PN544_ST_COLD; | ||
750 | info->read_irq = PN544_NONE; | ||
751 | mutex_init(&info->read_mutex); | ||
752 | mutex_init(&info->mutex); | ||
753 | init_waitqueue_head(&info->read_wait); | ||
754 | i2c_set_clientdata(client, info); | ||
755 | pdata = client->dev.platform_data; | ||
756 | if (!pdata) { | ||
757 | dev_err(&client->dev, "No platform data\n"); | ||
758 | r = -EINVAL; | ||
759 | goto err_reg; | ||
760 | } | ||
761 | |||
762 | if (!pdata->request_resources) { | ||
763 | dev_err(&client->dev, "request_resources() missing\n"); | ||
764 | r = -EINVAL; | ||
765 | goto err_reg; | ||
766 | } | ||
767 | |||
768 | r = pdata->request_resources(client); | ||
769 | if (r) { | ||
770 | dev_err(&client->dev, "Cannot get platform resources\n"); | ||
771 | goto err_reg; | ||
772 | } | ||
773 | |||
774 | r = request_threaded_irq(client->irq, NULL, pn544_irq_thread_fn, | ||
775 | IRQF_TRIGGER_RISING, PN544_DRIVER_NAME, | ||
776 | info); | ||
777 | if (r < 0) { | ||
778 | dev_err(&client->dev, "Unable to register IRQ handler\n"); | ||
779 | goto err_res; | ||
780 | } | ||
781 | |||
782 | /* If we don't have the test we don't need the sysfs file */ | ||
783 | if (pdata->test) { | ||
784 | r = device_create_file(&client->dev, &pn544_attr); | ||
785 | if (r) { | ||
786 | dev_err(&client->dev, | ||
787 | "sysfs registration failed, error %d\n", r); | ||
788 | goto err_irq; | ||
789 | } | ||
790 | } | ||
791 | |||
792 | info->miscdev.minor = MISC_DYNAMIC_MINOR; | ||
793 | info->miscdev.name = PN544_DRIVER_NAME; | ||
794 | info->miscdev.fops = &pn544_fops; | ||
795 | info->miscdev.parent = &client->dev; | ||
796 | r = misc_register(&info->miscdev); | ||
797 | if (r < 0) { | ||
798 | dev_err(&client->dev, "Device registration failed\n"); | ||
799 | goto err_sysfs; | ||
800 | } | ||
801 | |||
802 | dev_dbg(&client->dev, "%s: info: %p, pdata %p, client %p\n", | ||
803 | __func__, info, pdata, client); | ||
804 | |||
805 | return 0; | ||
806 | |||
807 | err_sysfs: | ||
808 | if (pdata->test) | ||
809 | device_remove_file(&client->dev, &pn544_attr); | ||
810 | err_irq: | ||
811 | free_irq(client->irq, info); | ||
812 | err_res: | ||
813 | if (pdata->free_resources) | ||
814 | pdata->free_resources(); | ||
815 | err_reg: | ||
816 | regulator_bulk_free(ARRAY_SIZE(info->regs), info->regs); | ||
817 | err_kmalloc: | ||
818 | kfree(info->buf); | ||
819 | err_buf_alloc: | ||
820 | kfree(info); | ||
821 | err_info_alloc: | ||
822 | return r; | ||
823 | } | ||
824 | |||
825 | static __devexit int pn544_remove(struct i2c_client *client) | ||
826 | { | ||
827 | struct pn544_info *info = i2c_get_clientdata(client); | ||
828 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
829 | |||
830 | dev_dbg(&client->dev, "%s\n", __func__); | ||
831 | |||
832 | misc_deregister(&info->miscdev); | ||
833 | if (pdata->test) | ||
834 | device_remove_file(&client->dev, &pn544_attr); | ||
835 | |||
836 | if (info->state != PN544_ST_COLD) { | ||
837 | if (pdata->disable) | ||
838 | pdata->disable(); | ||
839 | |||
840 | info->read_irq = PN544_NONE; | ||
841 | } | ||
842 | |||
843 | free_irq(client->irq, info); | ||
844 | if (pdata->free_resources) | ||
845 | pdata->free_resources(); | ||
846 | |||
847 | regulator_bulk_free(ARRAY_SIZE(info->regs), info->regs); | ||
848 | kfree(info->buf); | ||
849 | kfree(info); | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | static struct i2c_driver pn544_driver = { | ||
855 | .driver = { | ||
856 | .name = PN544_DRIVER_NAME, | ||
857 | #ifdef CONFIG_PM | ||
858 | .pm = &pn544_pm_ops, | ||
859 | #endif | ||
860 | }, | ||
861 | .probe = pn544_probe, | ||
862 | .id_table = pn544_id_table, | ||
863 | .remove = __devexit_p(pn544_remove), | ||
864 | }; | ||
865 | |||
866 | static int __init pn544_init(void) | ||
867 | { | ||
868 | int r; | ||
869 | |||
870 | pr_debug(DRIVER_DESC ": %s\n", __func__); | ||
871 | |||
872 | r = i2c_add_driver(&pn544_driver); | ||
873 | if (r) { | ||
874 | pr_err(PN544_DRIVER_NAME ": driver registration failed\n"); | ||
875 | return r; | ||
876 | } | ||
877 | |||
878 | return 0; | ||
879 | } | ||
880 | |||
881 | static void __exit pn544_exit(void) | ||
882 | { | ||
883 | i2c_del_driver(&pn544_driver); | ||
884 | pr_info(DRIVER_DESC ", Exiting.\n"); | ||
885 | } | ||
886 | |||
887 | module_init(pn544_init); | ||
888 | module_exit(pn544_exit); | ||
889 | |||
890 | MODULE_LICENSE("GPL"); | ||
891 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/pcmcia/m32r_cfc.h b/drivers/pcmcia/m32r_cfc.h index 8146e3bee2e8..f558e1adf954 100644 --- a/drivers/pcmcia/m32r_cfc.h +++ b/drivers/pcmcia/m32r_cfc.h | |||
@@ -9,7 +9,7 @@ | |||
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * M32R PC Card Controler | 12 | * M32R PC Card Controller |
13 | */ | 13 | */ |
14 | #define M32R_PCC0_BASE 0x00ef7000 | 14 | #define M32R_PCC0_BASE 0x00ef7000 |
15 | #define M32R_PCC1_BASE 0x00ef7020 | 15 | #define M32R_PCC1_BASE 0x00ef7020 |
diff --git a/drivers/pcmcia/m32r_pcc.h b/drivers/pcmcia/m32r_pcc.h index e4fffe417ba9..f95c58563bc8 100644 --- a/drivers/pcmcia/m32r_pcc.h +++ b/drivers/pcmcia/m32r_pcc.h | |||
@@ -5,7 +5,7 @@ | |||
5 | #define M32R_MAX_PCC 2 | 5 | #define M32R_MAX_PCC 2 |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * M32R PC Card Controler | 8 | * M32R PC Card Controller |
9 | */ | 9 | */ |
10 | #define M32R_PCC0_BASE 0x00ef7000 | 10 | #define M32R_PCC0_BASE 0x00ef7000 |
11 | #define M32R_PCC1_BASE 0x00ef7020 | 11 | #define M32R_PCC1_BASE 0x00ef7020 |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 99d4f23cb435..0db482771fb5 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
@@ -1198,7 +1198,7 @@ static int __init m8xx_probe(struct platform_device *ofdev, | |||
1198 | out_be32(M8XX_PGCRX(1), | 1198 | out_be32(M8XX_PGCRX(1), |
1199 | M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); | 1199 | M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); |
1200 | 1200 | ||
1201 | /* intialize the fixed memory windows */ | 1201 | /* initialize the fixed memory windows */ |
1202 | 1202 | ||
1203 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { | 1203 | for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { |
1204 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { | 1204 | for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index ee40d681edd0..c5c4b8c32eb8 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -1021,7 +1021,7 @@ static int update_bl_status(struct backlight_device *bd) | |||
1021 | return 0; | 1021 | return 0; |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | static struct backlight_ops acer_bl_ops = { | 1024 | static const struct backlight_ops acer_bl_ops = { |
1025 | .get_brightness = read_brightness, | 1025 | .get_brightness = read_brightness, |
1026 | .update_status = update_bl_status, | 1026 | .update_status = update_bl_status, |
1027 | }; | 1027 | }; |
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index d235f44fd7a3..f3aa6a7fdab6 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -640,7 +640,7 @@ static int update_bl_status(struct backlight_device *bd) | |||
640 | return asus_lcd_set(asus, value); | 640 | return asus_lcd_set(asus, value); |
641 | } | 641 | } |
642 | 642 | ||
643 | static struct backlight_ops asusbl_ops = { | 643 | static const struct backlight_ops asusbl_ops = { |
644 | .get_brightness = asus_read_brightness, | 644 | .get_brightness = asus_read_brightness, |
645 | .update_status = update_bl_status, | 645 | .update_status = update_bl_status, |
646 | }; | 646 | }; |
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index ca05aefd03bf..4633fd8532cc 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c | |||
@@ -1467,7 +1467,7 @@ static int asus_hotk_remove(struct acpi_device *device, int type) | |||
1467 | return 0; | 1467 | return 0; |
1468 | } | 1468 | } |
1469 | 1469 | ||
1470 | static struct backlight_ops asus_backlight_data = { | 1470 | static const struct backlight_ops asus_backlight_data = { |
1471 | .get_brightness = read_brightness, | 1471 | .get_brightness = read_brightness, |
1472 | .update_status = set_brightness_status, | 1472 | .update_status = set_brightness_status, |
1473 | }; | 1473 | }; |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index cf8a89a0d8f5..34657f96b5a5 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
@@ -546,7 +546,7 @@ out: | |||
546 | return buffer->output[1]; | 546 | return buffer->output[1]; |
547 | } | 547 | } |
548 | 548 | ||
549 | static struct backlight_ops dell_ops = { | 549 | static const struct backlight_ops dell_ops = { |
550 | .get_brightness = dell_get_intensity, | 550 | .get_brightness = dell_get_intensity, |
551 | .update_status = dell_send_intensity, | 551 | .update_status = dell_send_intensity, |
552 | }; | 552 | }; |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index e9fc530e7dc2..49d9ad708f89 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -1126,7 +1126,7 @@ static int update_bl_status(struct backlight_device *bd) | |||
1126 | return set_brightness(bd, bd->props.brightness); | 1126 | return set_brightness(bd, bd->props.brightness); |
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | static struct backlight_ops eeepcbl_ops = { | 1129 | static const struct backlight_ops eeepcbl_ops = { |
1130 | .get_brightness = read_brightness, | 1130 | .get_brightness = read_brightness, |
1131 | .update_status = update_bl_status, | 1131 | .update_status = update_bl_status, |
1132 | }; | 1132 | }; |
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index ad88b2ec34a1..19e92b2a7f7e 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c | |||
@@ -437,7 +437,7 @@ static int bl_update_status(struct backlight_device *b) | |||
437 | return ret; | 437 | return ret; |
438 | } | 438 | } |
439 | 439 | ||
440 | static struct backlight_ops fujitsubl_ops = { | 440 | static const struct backlight_ops fujitsubl_ops = { |
441 | .get_brightness = bl_get_brightness, | 441 | .get_brightness = bl_get_brightness, |
442 | .update_status = bl_update_status, | 442 | .update_status = bl_update_status, |
443 | }; | 443 | }; |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index b4a95bb2f232..5e83370b0812 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -858,7 +858,7 @@ static int sony_backlight_get_brightness(struct backlight_device *bd) | |||
858 | } | 858 | } |
859 | 859 | ||
860 | static struct backlight_device *sony_backlight_device; | 860 | static struct backlight_device *sony_backlight_device; |
861 | static struct backlight_ops sony_backlight_ops = { | 861 | static const struct backlight_ops sony_backlight_ops = { |
862 | .update_status = sony_backlight_update_status, | 862 | .update_status = sony_backlight_update_status, |
863 | .get_brightness = sony_backlight_get_brightness, | 863 | .get_brightness = sony_backlight_get_brightness, |
864 | }; | 864 | }; |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a974ca383cb9..dd599585c6a9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -6110,7 +6110,7 @@ static void tpacpi_brightness_notify_change(void) | |||
6110 | BACKLIGHT_UPDATE_HOTKEY); | 6110 | BACKLIGHT_UPDATE_HOTKEY); |
6111 | } | 6111 | } |
6112 | 6112 | ||
6113 | static struct backlight_ops ibm_backlight_data = { | 6113 | static const struct backlight_ops ibm_backlight_data = { |
6114 | .get_brightness = brightness_get, | 6114 | .get_brightness = brightness_get, |
6115 | .update_status = brightness_update_status, | 6115 | .update_status = brightness_update_status, |
6116 | }; | 6116 | }; |
@@ -7194,7 +7194,7 @@ static struct ibm_struct volume_driver_data = { | |||
7194 | * TPACPI_FAN_WR_ACPI_FANS (X31/X40/X41) | 7194 | * TPACPI_FAN_WR_ACPI_FANS (X31/X40/X41) |
7195 | * | 7195 | * |
7196 | * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at | 7196 | * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at |
7197 | * boot. Apparently the EC does not intialize it, so unless ACPI DSDT | 7197 | * boot. Apparently the EC does not initialize it, so unless ACPI DSDT |
7198 | * does so, its initial value is meaningless (0x07). | 7198 | * does so, its initial value is meaningless (0x07). |
7199 | * | 7199 | * |
7200 | * For firmware bugs, refer to: | 7200 | * For firmware bugs, refer to: |
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 4276da7291b8..209cced786c6 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -841,7 +841,7 @@ static void remove_toshiba_proc_entries(void) | |||
841 | remove_proc_entry("version", toshiba_proc_dir); | 841 | remove_proc_entry("version", toshiba_proc_dir); |
842 | } | 842 | } |
843 | 843 | ||
844 | static struct backlight_ops toshiba_backlight_data = { | 844 | static const struct backlight_ops toshiba_backlight_data = { |
845 | .get_brightness = get_lcd, | 845 | .get_brightness = get_lcd, |
846 | .update_status = set_lcd_status, | 846 | .update_status = set_lcd_status, |
847 | }; | 847 | }; |
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c index fe16b482e912..4a8ae3935b3b 100644 --- a/drivers/power/s3c_adc_battery.c +++ b/drivers/power/s3c_adc_battery.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * iPAQ h1930/h1940/rx1950 battery controler driver | 2 | * iPAQ h1930/h1940/rx1950 battery controller driver |
3 | * Copyright (c) Vasily Khoruzhick | 3 | * Copyright (c) Vasily Khoruzhick |
4 | * Based on h1940_battery.c by Arnaud Patard | 4 | * Based on h1940_battery.c by Arnaud Patard |
5 | * | 5 | * |
@@ -427,5 +427,5 @@ static void __exit s3c_adc_bat_exit(void) | |||
427 | module_exit(s3c_adc_bat_exit); | 427 | module_exit(s3c_adc_bat_exit); |
428 | 428 | ||
429 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); | 429 | MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); |
430 | MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controler driver"); | 430 | MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver"); |
431 | MODULE_LICENSE("GPL"); | 431 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/pps/Kconfig b/drivers/pps/Kconfig index 1afe4e03440f..f0d3376b58ba 100644 --- a/drivers/pps/Kconfig +++ b/drivers/pps/Kconfig | |||
@@ -30,6 +30,17 @@ config PPS_DEBUG | |||
30 | messages to the system log. Select this if you are having a | 30 | messages to the system log. Select this if you are having a |
31 | problem with PPS support and want to see more of what is going on. | 31 | problem with PPS support and want to see more of what is going on. |
32 | 32 | ||
33 | config NTP_PPS | ||
34 | bool "PPS kernel consumer support" | ||
35 | depends on PPS && !NO_HZ | ||
36 | help | ||
37 | This option adds support for direct in-kernel time | ||
38 | syncronization using an external PPS signal. | ||
39 | |||
40 | It doesn't work on tickless systems at the moment. | ||
41 | |||
33 | source drivers/pps/clients/Kconfig | 42 | source drivers/pps/clients/Kconfig |
34 | 43 | ||
44 | source drivers/pps/generators/Kconfig | ||
45 | |||
35 | endmenu | 46 | endmenu |
diff --git a/drivers/pps/Makefile b/drivers/pps/Makefile index 98960ddd3188..4483eaadaddd 100644 --- a/drivers/pps/Makefile +++ b/drivers/pps/Makefile | |||
@@ -3,7 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | pps_core-y := pps.o kapi.o sysfs.o | 5 | pps_core-y := pps.o kapi.o sysfs.o |
6 | pps_core-$(CONFIG_NTP_PPS) += kc.o | ||
6 | obj-$(CONFIG_PPS) := pps_core.o | 7 | obj-$(CONFIG_PPS) := pps_core.o |
7 | obj-y += clients/ | 8 | obj-y += clients/ generators/ |
8 | 9 | ||
9 | ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG | 10 | ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG |
diff --git a/drivers/pps/clients/Kconfig b/drivers/pps/clients/Kconfig index 4e801bd7254f..8520a7f4dd62 100644 --- a/drivers/pps/clients/Kconfig +++ b/drivers/pps/clients/Kconfig | |||
@@ -22,4 +22,11 @@ config PPS_CLIENT_LDISC | |||
22 | If you say yes here you get support for a PPS source connected | 22 | If you say yes here you get support for a PPS source connected |
23 | with the CD (Carrier Detect) pin of your serial port. | 23 | with the CD (Carrier Detect) pin of your serial port. |
24 | 24 | ||
25 | config PPS_CLIENT_PARPORT | ||
26 | tristate "Parallel port PPS client" | ||
27 | depends on PPS && PARPORT | ||
28 | help | ||
29 | If you say yes here you get support for a PPS source connected | ||
30 | with the interrupt pin of your parallel port. | ||
31 | |||
25 | endif | 32 | endif |
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile index 812c9b19b430..42517da07049 100644 --- a/drivers/pps/clients/Makefile +++ b/drivers/pps/clients/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o | 5 | obj-$(CONFIG_PPS_CLIENT_KTIMER) += pps-ktimer.o |
6 | obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o | 6 | obj-$(CONFIG_PPS_CLIENT_LDISC) += pps-ldisc.o |
7 | obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o | ||
7 | 8 | ||
8 | ifeq ($(CONFIG_PPS_DEBUG),y) | 9 | ifeq ($(CONFIG_PPS_DEBUG),y) |
9 | EXTRA_CFLAGS += -DDEBUG | 10 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/pps/clients/pps-ktimer.c b/drivers/pps/clients/pps-ktimer.c index e7ef5b8186d0..2728469d3884 100644 --- a/drivers/pps/clients/pps-ktimer.c +++ b/drivers/pps/clients/pps-ktimer.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
22 | 23 | ||
23 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -31,7 +32,7 @@ | |||
31 | * Global variables | 32 | * Global variables |
32 | */ | 33 | */ |
33 | 34 | ||
34 | static int source; | 35 | static struct pps_device *pps; |
35 | static struct timer_list ktimer; | 36 | static struct timer_list ktimer; |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -40,19 +41,14 @@ static struct timer_list ktimer; | |||
40 | 41 | ||
41 | static void pps_ktimer_event(unsigned long ptr) | 42 | static void pps_ktimer_event(unsigned long ptr) |
42 | { | 43 | { |
43 | struct timespec __ts; | 44 | struct pps_event_time ts; |
44 | struct pps_ktime ts; | ||
45 | 45 | ||
46 | /* First of all we get the time stamp... */ | 46 | /* First of all we get the time stamp... */ |
47 | getnstimeofday(&__ts); | 47 | pps_get_ts(&ts); |
48 | 48 | ||
49 | pr_info("PPS event at %lu\n", jiffies); | 49 | dev_info(pps->dev, "PPS event at %lu\n", jiffies); |
50 | 50 | ||
51 | /* ... and translate it to PPS time data struct */ | 51 | pps_event(pps, &ts, PPS_CAPTUREASSERT, NULL); |
52 | ts.sec = __ts.tv_sec; | ||
53 | ts.nsec = __ts.tv_nsec; | ||
54 | |||
55 | pps_event(source, &ts, PPS_CAPTUREASSERT, NULL); | ||
56 | 52 | ||
57 | mod_timer(&ktimer, jiffies + HZ); | 53 | mod_timer(&ktimer, jiffies + HZ); |
58 | } | 54 | } |
@@ -61,12 +57,11 @@ static void pps_ktimer_event(unsigned long ptr) | |||
61 | * The echo function | 57 | * The echo function |
62 | */ | 58 | */ |
63 | 59 | ||
64 | static void pps_ktimer_echo(int source, int event, void *data) | 60 | static void pps_ktimer_echo(struct pps_device *pps, int event, void *data) |
65 | { | 61 | { |
66 | pr_info("echo %s %s for source %d\n", | 62 | dev_info(pps->dev, "echo %s %s\n", |
67 | event & PPS_CAPTUREASSERT ? "assert" : "", | 63 | event & PPS_CAPTUREASSERT ? "assert" : "", |
68 | event & PPS_CAPTURECLEAR ? "clear" : "", | 64 | event & PPS_CAPTURECLEAR ? "clear" : ""); |
69 | source); | ||
70 | } | 65 | } |
71 | 66 | ||
72 | /* | 67 | /* |
@@ -89,30 +84,27 @@ static struct pps_source_info pps_ktimer_info = { | |||
89 | 84 | ||
90 | static void __exit pps_ktimer_exit(void) | 85 | static void __exit pps_ktimer_exit(void) |
91 | { | 86 | { |
92 | del_timer_sync(&ktimer); | 87 | dev_info(pps->dev, "ktimer PPS source unregistered\n"); |
93 | pps_unregister_source(source); | ||
94 | 88 | ||
95 | pr_info("ktimer PPS source unregistered\n"); | 89 | del_timer_sync(&ktimer); |
90 | pps_unregister_source(pps); | ||
96 | } | 91 | } |
97 | 92 | ||
98 | static int __init pps_ktimer_init(void) | 93 | static int __init pps_ktimer_init(void) |
99 | { | 94 | { |
100 | int ret; | 95 | pps = pps_register_source(&pps_ktimer_info, |
101 | |||
102 | ret = pps_register_source(&pps_ktimer_info, | ||
103 | PPS_CAPTUREASSERT | PPS_OFFSETASSERT); | 96 | PPS_CAPTUREASSERT | PPS_OFFSETASSERT); |
104 | if (ret < 0) { | 97 | if (pps == NULL) { |
105 | printk(KERN_ERR "cannot register ktimer source\n"); | 98 | pr_err("cannot register PPS source\n"); |
106 | return ret; | 99 | return -ENOMEM; |
107 | } | 100 | } |
108 | source = ret; | ||
109 | 101 | ||
110 | setup_timer(&ktimer, pps_ktimer_event, 0); | 102 | setup_timer(&ktimer, pps_ktimer_event, 0); |
111 | mod_timer(&ktimer, jiffies + HZ); | 103 | mod_timer(&ktimer, jiffies + HZ); |
112 | 104 | ||
113 | pr_info("ktimer PPS source registered at %d\n", source); | 105 | dev_info(pps->dev, "ktimer PPS source registered\n"); |
114 | 106 | ||
115 | return 0; | 107 | return 0; |
116 | } | 108 | } |
117 | 109 | ||
118 | module_init(pps_ktimer_init); | 110 | module_init(pps_ktimer_init); |
diff --git a/drivers/pps/clients/pps-ldisc.c b/drivers/pps/clients/pps-ldisc.c index 8e1932d29fd4..79451f2dea6a 100644 --- a/drivers/pps/clients/pps-ldisc.c +++ b/drivers/pps/clients/pps-ldisc.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
23 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
24 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
@@ -27,30 +29,18 @@ | |||
27 | #define PPS_TTY_MAGIC 0x0001 | 29 | #define PPS_TTY_MAGIC 0x0001 |
28 | 30 | ||
29 | static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, | 31 | static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, |
30 | struct timespec *ts) | 32 | struct pps_event_time *ts) |
31 | { | 33 | { |
32 | int id = (long)tty->disc_data; | 34 | struct pps_device *pps = (struct pps_device *)tty->disc_data; |
33 | struct timespec __ts; | 35 | |
34 | struct pps_ktime pps_ts; | 36 | BUG_ON(pps == NULL); |
35 | |||
36 | /* First of all we get the time stamp... */ | ||
37 | getnstimeofday(&__ts); | ||
38 | |||
39 | /* Does caller give us a timestamp? */ | ||
40 | if (ts) { /* Yes. Let's use it! */ | ||
41 | pps_ts.sec = ts->tv_sec; | ||
42 | pps_ts.nsec = ts->tv_nsec; | ||
43 | } else { /* No. Do it ourself! */ | ||
44 | pps_ts.sec = __ts.tv_sec; | ||
45 | pps_ts.nsec = __ts.tv_nsec; | ||
46 | } | ||
47 | 37 | ||
48 | /* Now do the PPS event report */ | 38 | /* Now do the PPS event report */ |
49 | pps_event(id, &pps_ts, status ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR, | 39 | pps_event(pps, ts, status ? PPS_CAPTUREASSERT : |
50 | NULL); | 40 | PPS_CAPTURECLEAR, NULL); |
51 | 41 | ||
52 | pr_debug("PPS %s at %lu on source #%d\n", | 42 | dev_dbg(pps->dev, "PPS %s at %lu\n", |
53 | status ? "assert" : "clear", jiffies, id); | 43 | status ? "assert" : "clear", jiffies); |
54 | } | 44 | } |
55 | 45 | ||
56 | static int (*alias_n_tty_open)(struct tty_struct *tty); | 46 | static int (*alias_n_tty_open)(struct tty_struct *tty); |
@@ -60,6 +50,7 @@ static int pps_tty_open(struct tty_struct *tty) | |||
60 | struct pps_source_info info; | 50 | struct pps_source_info info; |
61 | struct tty_driver *drv = tty->driver; | 51 | struct tty_driver *drv = tty->driver; |
62 | int index = tty->index + drv->name_base; | 52 | int index = tty->index + drv->name_base; |
53 | struct pps_device *pps; | ||
63 | int ret; | 54 | int ret; |
64 | 55 | ||
65 | info.owner = THIS_MODULE; | 56 | info.owner = THIS_MODULE; |
@@ -70,34 +61,42 @@ static int pps_tty_open(struct tty_struct *tty) | |||
70 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ | 61 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ |
71 | PPS_CANWAIT | PPS_TSFMT_TSPEC; | 62 | PPS_CANWAIT | PPS_TSFMT_TSPEC; |
72 | 63 | ||
73 | ret = pps_register_source(&info, PPS_CAPTUREBOTH | \ | 64 | pps = pps_register_source(&info, PPS_CAPTUREBOTH | \ |
74 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); | 65 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); |
75 | if (ret < 0) { | 66 | if (pps == NULL) { |
76 | pr_err("cannot register PPS source \"%s\"\n", info.path); | 67 | pr_err("cannot register PPS source \"%s\"\n", info.path); |
77 | return ret; | 68 | return -ENOMEM; |
78 | } | 69 | } |
79 | tty->disc_data = (void *)(long)ret; | 70 | tty->disc_data = pps; |
80 | 71 | ||
81 | /* Should open N_TTY ldisc too */ | 72 | /* Should open N_TTY ldisc too */ |
82 | ret = alias_n_tty_open(tty); | 73 | ret = alias_n_tty_open(tty); |
83 | if (ret < 0) | 74 | if (ret < 0) { |
84 | pps_unregister_source((long)tty->disc_data); | 75 | pr_err("cannot open tty ldisc \"%s\"\n", info.path); |
76 | goto err_unregister; | ||
77 | } | ||
85 | 78 | ||
86 | pr_info("PPS source #%d \"%s\" added\n", ret, info.path); | 79 | dev_info(pps->dev, "source \"%s\" added\n", info.path); |
87 | 80 | ||
88 | return 0; | 81 | return 0; |
82 | |||
83 | err_unregister: | ||
84 | tty->disc_data = NULL; | ||
85 | pps_unregister_source(pps); | ||
86 | return ret; | ||
89 | } | 87 | } |
90 | 88 | ||
91 | static void (*alias_n_tty_close)(struct tty_struct *tty); | 89 | static void (*alias_n_tty_close)(struct tty_struct *tty); |
92 | 90 | ||
93 | static void pps_tty_close(struct tty_struct *tty) | 91 | static void pps_tty_close(struct tty_struct *tty) |
94 | { | 92 | { |
95 | int id = (long)tty->disc_data; | 93 | struct pps_device *pps = (struct pps_device *)tty->disc_data; |
96 | 94 | ||
97 | pps_unregister_source(id); | ||
98 | alias_n_tty_close(tty); | 95 | alias_n_tty_close(tty); |
99 | 96 | ||
100 | pr_info("PPS source #%d removed\n", id); | 97 | tty->disc_data = NULL; |
98 | dev_info(pps->dev, "removed\n"); | ||
99 | pps_unregister_source(pps); | ||
101 | } | 100 | } |
102 | 101 | ||
103 | static struct tty_ldisc_ops pps_ldisc_ops; | 102 | static struct tty_ldisc_ops pps_ldisc_ops; |
diff --git a/drivers/pps/clients/pps_parport.c b/drivers/pps/clients/pps_parport.c new file mode 100644 index 000000000000..32221efd9ca9 --- /dev/null +++ b/drivers/pps/clients/pps_parport.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * pps_parport.c -- kernel parallel port PPS client | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2009 Alexander Gordeev <lasaine@lvk.cs.msu.su> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | |||
23 | /* | ||
24 | * TODO: | ||
25 | * implement echo over SEL pin | ||
26 | */ | ||
27 | |||
28 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/irqnr.h> | ||
34 | #include <linux/time.h> | ||
35 | #include <linux/parport.h> | ||
36 | #include <linux/pps_kernel.h> | ||
37 | |||
38 | #define DRVDESC "parallel port PPS client" | ||
39 | |||
40 | /* module parameters */ | ||
41 | |||
42 | #define CLEAR_WAIT_MAX 100 | ||
43 | #define CLEAR_WAIT_MAX_ERRORS 5 | ||
44 | |||
45 | static unsigned int clear_wait = 100; | ||
46 | MODULE_PARM_DESC(clear_wait, | ||
47 | "Maximum number of port reads when polling for signal clear," | ||
48 | " zero turns clear edge capture off entirely"); | ||
49 | module_param(clear_wait, uint, 0); | ||
50 | |||
51 | |||
52 | /* internal per port structure */ | ||
53 | struct pps_client_pp { | ||
54 | struct pardevice *pardev; /* parport device */ | ||
55 | struct pps_device *pps; /* PPS device */ | ||
56 | unsigned int cw; /* port clear timeout */ | ||
57 | unsigned int cw_err; /* number of timeouts */ | ||
58 | }; | ||
59 | |||
60 | static inline int signal_is_set(struct parport *port) | ||
61 | { | ||
62 | return (port->ops->read_status(port) & PARPORT_STATUS_ACK) != 0; | ||
63 | } | ||
64 | |||
65 | /* parport interrupt handler */ | ||
66 | static void parport_irq(void *handle) | ||
67 | { | ||
68 | struct pps_event_time ts_assert, ts_clear; | ||
69 | struct pps_client_pp *dev = handle; | ||
70 | struct parport *port = dev->pardev->port; | ||
71 | unsigned int i; | ||
72 | unsigned long flags; | ||
73 | |||
74 | /* first of all we get the time stamp... */ | ||
75 | pps_get_ts(&ts_assert); | ||
76 | |||
77 | if (dev->cw == 0) | ||
78 | /* clear edge capture disabled */ | ||
79 | goto out_assert; | ||
80 | |||
81 | /* try capture the clear edge */ | ||
82 | |||
83 | /* We have to disable interrupts here. The idea is to prevent | ||
84 | * other interrupts on the same processor to introduce random | ||
85 | * lags while polling the port. Reading from IO port is known | ||
86 | * to take approximately 1us while other interrupt handlers can | ||
87 | * take much more potentially. | ||
88 | * | ||
89 | * Interrupts won't be disabled for a long time because the | ||
90 | * number of polls is limited by clear_wait parameter which is | ||
91 | * kept rather low. So it should never be an issue. | ||
92 | */ | ||
93 | local_irq_save(flags); | ||
94 | /* check the signal (no signal means the pulse is lost this time) */ | ||
95 | if (!signal_is_set(port)) { | ||
96 | local_irq_restore(flags); | ||
97 | dev_err(dev->pps->dev, "lost the signal\n"); | ||
98 | goto out_assert; | ||
99 | } | ||
100 | |||
101 | /* poll the port until the signal is unset */ | ||
102 | for (i = dev->cw; i; i--) | ||
103 | if (!signal_is_set(port)) { | ||
104 | pps_get_ts(&ts_clear); | ||
105 | local_irq_restore(flags); | ||
106 | dev->cw_err = 0; | ||
107 | goto out_both; | ||
108 | } | ||
109 | local_irq_restore(flags); | ||
110 | |||
111 | /* timeout */ | ||
112 | dev->cw_err++; | ||
113 | if (dev->cw_err >= CLEAR_WAIT_MAX_ERRORS) { | ||
114 | dev_err(dev->pps->dev, "disabled clear edge capture after %d" | ||
115 | " timeouts\n", dev->cw_err); | ||
116 | dev->cw = 0; | ||
117 | dev->cw_err = 0; | ||
118 | } | ||
119 | |||
120 | out_assert: | ||
121 | /* fire assert event */ | ||
122 | pps_event(dev->pps, &ts_assert, | ||
123 | PPS_CAPTUREASSERT, NULL); | ||
124 | return; | ||
125 | |||
126 | out_both: | ||
127 | /* fire assert event */ | ||
128 | pps_event(dev->pps, &ts_assert, | ||
129 | PPS_CAPTUREASSERT, NULL); | ||
130 | /* fire clear event */ | ||
131 | pps_event(dev->pps, &ts_clear, | ||
132 | PPS_CAPTURECLEAR, NULL); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | /* the PPS echo function */ | ||
137 | static void pps_echo(struct pps_device *pps, int event, void *data) | ||
138 | { | ||
139 | dev_info(pps->dev, "echo %s %s\n", | ||
140 | event & PPS_CAPTUREASSERT ? "assert" : "", | ||
141 | event & PPS_CAPTURECLEAR ? "clear" : ""); | ||
142 | } | ||
143 | |||
144 | static void parport_attach(struct parport *port) | ||
145 | { | ||
146 | struct pps_client_pp *device; | ||
147 | struct pps_source_info info = { | ||
148 | .name = KBUILD_MODNAME, | ||
149 | .path = "", | ||
150 | .mode = PPS_CAPTUREBOTH | \ | ||
151 | PPS_OFFSETASSERT | PPS_OFFSETCLEAR | \ | ||
152 | PPS_ECHOASSERT | PPS_ECHOCLEAR | \ | ||
153 | PPS_CANWAIT | PPS_TSFMT_TSPEC, | ||
154 | .echo = pps_echo, | ||
155 | .owner = THIS_MODULE, | ||
156 | .dev = NULL | ||
157 | }; | ||
158 | |||
159 | device = kzalloc(sizeof(struct pps_client_pp), GFP_KERNEL); | ||
160 | if (!device) { | ||
161 | pr_err("memory allocation failed, not attaching\n"); | ||
162 | return; | ||
163 | } | ||
164 | |||
165 | device->pardev = parport_register_device(port, KBUILD_MODNAME, | ||
166 | NULL, NULL, parport_irq, 0, device); | ||
167 | if (!device->pardev) { | ||
168 | pr_err("couldn't register with %s\n", port->name); | ||
169 | goto err_free; | ||
170 | } | ||
171 | |||
172 | if (parport_claim_or_block(device->pardev) < 0) { | ||
173 | pr_err("couldn't claim %s\n", port->name); | ||
174 | goto err_unregister_dev; | ||
175 | } | ||
176 | |||
177 | device->pps = pps_register_source(&info, | ||
178 | PPS_CAPTUREBOTH | PPS_OFFSETASSERT | PPS_OFFSETCLEAR); | ||
179 | if (device->pps == NULL) { | ||
180 | pr_err("couldn't register PPS source\n"); | ||
181 | goto err_release_dev; | ||
182 | } | ||
183 | |||
184 | device->cw = clear_wait; | ||
185 | |||
186 | port->ops->enable_irq(port); | ||
187 | |||
188 | pr_info("attached to %s\n", port->name); | ||
189 | |||
190 | return; | ||
191 | |||
192 | err_release_dev: | ||
193 | parport_release(device->pardev); | ||
194 | err_unregister_dev: | ||
195 | parport_unregister_device(device->pardev); | ||
196 | err_free: | ||
197 | kfree(device); | ||
198 | } | ||
199 | |||
200 | static void parport_detach(struct parport *port) | ||
201 | { | ||
202 | struct pardevice *pardev = port->cad; | ||
203 | struct pps_client_pp *device; | ||
204 | |||
205 | /* FIXME: oooh, this is ugly! */ | ||
206 | if (strcmp(pardev->name, KBUILD_MODNAME)) | ||
207 | /* not our port */ | ||
208 | return; | ||
209 | |||
210 | device = pardev->private; | ||
211 | |||
212 | port->ops->disable_irq(port); | ||
213 | pps_unregister_source(device->pps); | ||
214 | parport_release(pardev); | ||
215 | parport_unregister_device(pardev); | ||
216 | kfree(device); | ||
217 | } | ||
218 | |||
219 | static struct parport_driver pps_parport_driver = { | ||
220 | .name = KBUILD_MODNAME, | ||
221 | .attach = parport_attach, | ||
222 | .detach = parport_detach, | ||
223 | }; | ||
224 | |||
225 | /* module staff */ | ||
226 | |||
227 | static int __init pps_parport_init(void) | ||
228 | { | ||
229 | int ret; | ||
230 | |||
231 | pr_info(DRVDESC "\n"); | ||
232 | |||
233 | if (clear_wait > CLEAR_WAIT_MAX) { | ||
234 | pr_err("clear_wait value should be not greater" | ||
235 | " then %d\n", CLEAR_WAIT_MAX); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
239 | ret = parport_register_driver(&pps_parport_driver); | ||
240 | if (ret) { | ||
241 | pr_err("unable to register with parport\n"); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static void __exit pps_parport_exit(void) | ||
249 | { | ||
250 | parport_unregister_driver(&pps_parport_driver); | ||
251 | } | ||
252 | |||
253 | module_init(pps_parport_init); | ||
254 | module_exit(pps_parport_exit); | ||
255 | |||
256 | MODULE_AUTHOR("Alexander Gordeev <lasaine@lvk.cs.msu.su>"); | ||
257 | MODULE_DESCRIPTION(DRVDESC); | ||
258 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pps/generators/Kconfig b/drivers/pps/generators/Kconfig new file mode 100644 index 000000000000..f3a73dd77660 --- /dev/null +++ b/drivers/pps/generators/Kconfig | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # PPS generators configuration | ||
3 | # | ||
4 | |||
5 | comment "PPS generators support" | ||
6 | |||
7 | config PPS_GENERATOR_PARPORT | ||
8 | tristate "Parallel port PPS signal generator" | ||
9 | depends on PARPORT | ||
10 | help | ||
11 | If you say yes here you get support for a PPS signal generator which | ||
12 | utilizes STROBE pin of a parallel port to send PPS signals. It uses | ||
13 | parport abstraction layer and hrtimers to precisely control the signal. | ||
diff --git a/drivers/pps/generators/Makefile b/drivers/pps/generators/Makefile new file mode 100644 index 000000000000..303304a6b8ec --- /dev/null +++ b/drivers/pps/generators/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # | ||
2 | # Makefile for PPS generators. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PPS_GENERATOR_PARPORT) += pps_gen_parport.o | ||
6 | |||
7 | ifeq ($(CONFIG_PPS_DEBUG),y) | ||
8 | EXTRA_CFLAGS += -DDEBUG | ||
9 | endif | ||
diff --git a/drivers/pps/generators/pps_gen_parport.c b/drivers/pps/generators/pps_gen_parport.c new file mode 100644 index 000000000000..5c32f8dacf56 --- /dev/null +++ b/drivers/pps/generators/pps_gen_parport.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * pps_gen_parport.c -- kernel parallel port PPS signal generator | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2009 Alexander Gordeev <lasaine@lvk.cs.msu.su> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | |||
23 | /* | ||
24 | * TODO: | ||
25 | * fix issues when realtime clock is adjusted in a leap | ||
26 | */ | ||
27 | |||
28 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/time.h> | ||
34 | #include <linux/hrtimer.h> | ||
35 | #include <linux/parport.h> | ||
36 | |||
37 | #define DRVDESC "parallel port PPS signal generator" | ||
38 | |||
39 | #define SIGNAL 0 | ||
40 | #define NO_SIGNAL PARPORT_CONTROL_STROBE | ||
41 | |||
42 | /* module parameters */ | ||
43 | |||
44 | #define SEND_DELAY_MAX 100000 | ||
45 | |||
46 | static unsigned int send_delay = 30000; | ||
47 | MODULE_PARM_DESC(delay, | ||
48 | "Delay between setting and dropping the signal (ns)"); | ||
49 | module_param_named(delay, send_delay, uint, 0); | ||
50 | |||
51 | |||
52 | #define SAFETY_INTERVAL 3000 /* set the hrtimer earlier for safety (ns) */ | ||
53 | |||
54 | /* internal per port structure */ | ||
55 | struct pps_generator_pp { | ||
56 | struct pardevice *pardev; /* parport device */ | ||
57 | struct hrtimer timer; | ||
58 | long port_write_time; /* calibrated port write time (ns) */ | ||
59 | }; | ||
60 | |||
61 | static struct pps_generator_pp device = { | ||
62 | .pardev = NULL, | ||
63 | }; | ||
64 | |||
65 | static int attached; | ||
66 | |||
67 | /* calibrated time between a hrtimer event and the reaction */ | ||
68 | static long hrtimer_error = SAFETY_INTERVAL; | ||
69 | |||
70 | /* the kernel hrtimer event */ | ||
71 | static enum hrtimer_restart hrtimer_event(struct hrtimer *timer) | ||
72 | { | ||
73 | struct timespec expire_time, ts1, ts2, ts3, dts; | ||
74 | struct pps_generator_pp *dev; | ||
75 | struct parport *port; | ||
76 | long lim, delta; | ||
77 | unsigned long flags; | ||
78 | |||
79 | /* We have to disable interrupts here. The idea is to prevent | ||
80 | * other interrupts on the same processor to introduce random | ||
81 | * lags while polling the clock. getnstimeofday() takes <1us on | ||
82 | * most machines while other interrupt handlers can take much | ||
83 | * more potentially. | ||
84 | * | ||
85 | * NB: approx time with blocked interrupts = | ||
86 | * send_delay + 3 * SAFETY_INTERVAL | ||
87 | */ | ||
88 | local_irq_save(flags); | ||
89 | |||
90 | /* first of all we get the time stamp... */ | ||
91 | getnstimeofday(&ts1); | ||
92 | expire_time = ktime_to_timespec(hrtimer_get_softexpires(timer)); | ||
93 | dev = container_of(timer, struct pps_generator_pp, timer); | ||
94 | lim = NSEC_PER_SEC - send_delay - dev->port_write_time; | ||
95 | |||
96 | /* check if we are late */ | ||
97 | if (expire_time.tv_sec != ts1.tv_sec || ts1.tv_nsec > lim) { | ||
98 | local_irq_restore(flags); | ||
99 | pr_err("we are late this time %ld.%09ld\n", | ||
100 | ts1.tv_sec, ts1.tv_nsec); | ||
101 | goto done; | ||
102 | } | ||
103 | |||
104 | /* busy loop until the time is right for an assert edge */ | ||
105 | do { | ||
106 | getnstimeofday(&ts2); | ||
107 | } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); | ||
108 | |||
109 | /* set the signal */ | ||
110 | port = dev->pardev->port; | ||
111 | port->ops->write_control(port, SIGNAL); | ||
112 | |||
113 | /* busy loop until the time is right for a clear edge */ | ||
114 | lim = NSEC_PER_SEC - dev->port_write_time; | ||
115 | do { | ||
116 | getnstimeofday(&ts2); | ||
117 | } while (expire_time.tv_sec == ts2.tv_sec && ts2.tv_nsec < lim); | ||
118 | |||
119 | /* unset the signal */ | ||
120 | port->ops->write_control(port, NO_SIGNAL); | ||
121 | |||
122 | getnstimeofday(&ts3); | ||
123 | |||
124 | local_irq_restore(flags); | ||
125 | |||
126 | /* update calibrated port write time */ | ||
127 | dts = timespec_sub(ts3, ts2); | ||
128 | dev->port_write_time = | ||
129 | (dev->port_write_time + timespec_to_ns(&dts)) >> 1; | ||
130 | |||
131 | done: | ||
132 | /* update calibrated hrtimer error */ | ||
133 | dts = timespec_sub(ts1, expire_time); | ||
134 | delta = timespec_to_ns(&dts); | ||
135 | /* If the new error value is bigger then the old, use the new | ||
136 | * value, if not then slowly move towards the new value. This | ||
137 | * way it should be safe in bad conditions and efficient in | ||
138 | * good conditions. | ||
139 | */ | ||
140 | if (delta >= hrtimer_error) | ||
141 | hrtimer_error = delta; | ||
142 | else | ||
143 | hrtimer_error = (3 * hrtimer_error + delta) >> 2; | ||
144 | |||
145 | /* update the hrtimer expire time */ | ||
146 | hrtimer_set_expires(timer, | ||
147 | ktime_set(expire_time.tv_sec + 1, | ||
148 | NSEC_PER_SEC - (send_delay + | ||
149 | dev->port_write_time + SAFETY_INTERVAL + | ||
150 | 2 * hrtimer_error))); | ||
151 | |||
152 | return HRTIMER_RESTART; | ||
153 | } | ||
154 | |||
155 | /* calibrate port write time */ | ||
156 | #define PORT_NTESTS_SHIFT 5 | ||
157 | static void calibrate_port(struct pps_generator_pp *dev) | ||
158 | { | ||
159 | struct parport *port = dev->pardev->port; | ||
160 | int i; | ||
161 | long acc = 0; | ||
162 | |||
163 | for (i = 0; i < (1 << PORT_NTESTS_SHIFT); i++) { | ||
164 | struct timespec a, b; | ||
165 | unsigned long irq_flags; | ||
166 | |||
167 | local_irq_save(irq_flags); | ||
168 | getnstimeofday(&a); | ||
169 | port->ops->write_control(port, NO_SIGNAL); | ||
170 | getnstimeofday(&b); | ||
171 | local_irq_restore(irq_flags); | ||
172 | |||
173 | b = timespec_sub(b, a); | ||
174 | acc += timespec_to_ns(&b); | ||
175 | } | ||
176 | |||
177 | dev->port_write_time = acc >> PORT_NTESTS_SHIFT; | ||
178 | pr_info("port write takes %ldns\n", dev->port_write_time); | ||
179 | } | ||
180 | |||
181 | static inline ktime_t next_intr_time(struct pps_generator_pp *dev) | ||
182 | { | ||
183 | struct timespec ts; | ||
184 | |||
185 | getnstimeofday(&ts); | ||
186 | |||
187 | return ktime_set(ts.tv_sec + | ||
188 | ((ts.tv_nsec > 990 * NSEC_PER_MSEC) ? 1 : 0), | ||
189 | NSEC_PER_SEC - (send_delay + | ||
190 | dev->port_write_time + 3 * SAFETY_INTERVAL)); | ||
191 | } | ||
192 | |||
193 | static void parport_attach(struct parport *port) | ||
194 | { | ||
195 | if (attached) { | ||
196 | /* we already have a port */ | ||
197 | return; | ||
198 | } | ||
199 | |||
200 | device.pardev = parport_register_device(port, KBUILD_MODNAME, | ||
201 | NULL, NULL, NULL, 0, &device); | ||
202 | if (!device.pardev) { | ||
203 | pr_err("couldn't register with %s\n", port->name); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | if (parport_claim_or_block(device.pardev) < 0) { | ||
208 | pr_err("couldn't claim %s\n", port->name); | ||
209 | goto err_unregister_dev; | ||
210 | } | ||
211 | |||
212 | pr_info("attached to %s\n", port->name); | ||
213 | attached = 1; | ||
214 | |||
215 | calibrate_port(&device); | ||
216 | |||
217 | hrtimer_init(&device.timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); | ||
218 | device.timer.function = hrtimer_event; | ||
219 | #ifdef CONFIG_PREEMPT_RT | ||
220 | /* hrtimer interrupt will run in the interrupt context with this */ | ||
221 | device.timer.irqsafe = 1; | ||
222 | #endif | ||
223 | |||
224 | hrtimer_start(&device.timer, next_intr_time(&device), HRTIMER_MODE_ABS); | ||
225 | |||
226 | return; | ||
227 | |||
228 | err_unregister_dev: | ||
229 | parport_unregister_device(device.pardev); | ||
230 | } | ||
231 | |||
232 | static void parport_detach(struct parport *port) | ||
233 | { | ||
234 | if (port->cad != device.pardev) | ||
235 | return; /* not our port */ | ||
236 | |||
237 | hrtimer_cancel(&device.timer); | ||
238 | parport_release(device.pardev); | ||
239 | parport_unregister_device(device.pardev); | ||
240 | } | ||
241 | |||
242 | static struct parport_driver pps_gen_parport_driver = { | ||
243 | .name = KBUILD_MODNAME, | ||
244 | .attach = parport_attach, | ||
245 | .detach = parport_detach, | ||
246 | }; | ||
247 | |||
248 | /* module staff */ | ||
249 | |||
250 | static int __init pps_gen_parport_init(void) | ||
251 | { | ||
252 | int ret; | ||
253 | |||
254 | pr_info(DRVDESC "\n"); | ||
255 | |||
256 | if (send_delay > SEND_DELAY_MAX) { | ||
257 | pr_err("delay value should be not greater" | ||
258 | " then %d\n", SEND_DELAY_MAX); | ||
259 | return -EINVAL; | ||
260 | } | ||
261 | |||
262 | ret = parport_register_driver(&pps_gen_parport_driver); | ||
263 | if (ret) { | ||
264 | pr_err("unable to register with parport\n"); | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static void __exit pps_gen_parport_exit(void) | ||
272 | { | ||
273 | parport_unregister_driver(&pps_gen_parport_driver); | ||
274 | pr_info("hrtimer avg error is %ldns\n", hrtimer_error); | ||
275 | } | ||
276 | |||
277 | module_init(pps_gen_parport_init); | ||
278 | module_exit(pps_gen_parport_exit); | ||
279 | |||
280 | MODULE_AUTHOR("Alexander Gordeev <lasaine@lvk.cs.msu.su>"); | ||
281 | MODULE_DESCRIPTION(DRVDESC); | ||
282 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c index 1aa02db3ff4e..cba1b43f7519 100644 --- a/drivers/pps/kapi.c +++ b/drivers/pps/kapi.c | |||
@@ -19,24 +19,20 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
22 | 23 | ||
23 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
25 | #include <linux/init.h> | 26 | #include <linux/init.h> |
26 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
27 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/timex.h> | ||
28 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
29 | #include <linux/idr.h> | ||
30 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
31 | #include <linux/pps_kernel.h> | 32 | #include <linux/pps_kernel.h> |
32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
33 | 34 | ||
34 | /* | 35 | #include "kc.h" |
35 | * Global variables | ||
36 | */ | ||
37 | |||
38 | DEFINE_SPINLOCK(pps_idr_lock); | ||
39 | DEFINE_IDR(pps_idr); | ||
40 | 36 | ||
41 | /* | 37 | /* |
42 | * Local functions | 38 | * Local functions |
@@ -60,60 +56,6 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset) | |||
60 | * Exported functions | 56 | * Exported functions |
61 | */ | 57 | */ |
62 | 58 | ||
63 | /* pps_get_source - find a PPS source | ||
64 | * @source: the PPS source ID. | ||
65 | * | ||
66 | * This function is used to find an already registered PPS source into the | ||
67 | * system. | ||
68 | * | ||
69 | * The function returns NULL if found nothing, otherwise it returns a pointer | ||
70 | * to the PPS source data struct (the refcounter is incremented by 1). | ||
71 | */ | ||
72 | |||
73 | struct pps_device *pps_get_source(int source) | ||
74 | { | ||
75 | struct pps_device *pps; | ||
76 | unsigned long flags; | ||
77 | |||
78 | spin_lock_irqsave(&pps_idr_lock, flags); | ||
79 | |||
80 | pps = idr_find(&pps_idr, source); | ||
81 | if (pps != NULL) | ||
82 | atomic_inc(&pps->usage); | ||
83 | |||
84 | spin_unlock_irqrestore(&pps_idr_lock, flags); | ||
85 | |||
86 | return pps; | ||
87 | } | ||
88 | |||
89 | /* pps_put_source - free the PPS source data | ||
90 | * @pps: a pointer to the PPS source. | ||
91 | * | ||
92 | * This function is used to free a PPS data struct if its refcount is 0. | ||
93 | */ | ||
94 | |||
95 | void pps_put_source(struct pps_device *pps) | ||
96 | { | ||
97 | unsigned long flags; | ||
98 | |||
99 | spin_lock_irqsave(&pps_idr_lock, flags); | ||
100 | BUG_ON(atomic_read(&pps->usage) == 0); | ||
101 | |||
102 | if (!atomic_dec_and_test(&pps->usage)) { | ||
103 | pps = NULL; | ||
104 | goto exit; | ||
105 | } | ||
106 | |||
107 | /* No more reference to the PPS source. We can safely remove the | ||
108 | * PPS data struct. | ||
109 | */ | ||
110 | idr_remove(&pps_idr, pps->id); | ||
111 | |||
112 | exit: | ||
113 | spin_unlock_irqrestore(&pps_idr_lock, flags); | ||
114 | kfree(pps); | ||
115 | } | ||
116 | |||
117 | /* pps_register_source - add a PPS source in the system | 59 | /* pps_register_source - add a PPS source in the system |
118 | * @info: the PPS info struct | 60 | * @info: the PPS info struct |
119 | * @default_params: the default PPS parameters of the new source | 61 | * @default_params: the default PPS parameters of the new source |
@@ -122,31 +64,31 @@ exit: | |||
122 | * source is described by info's fields and it will have, as default PPS | 64 | * source is described by info's fields and it will have, as default PPS |
123 | * parameters, the ones specified into default_params. | 65 | * parameters, the ones specified into default_params. |
124 | * | 66 | * |
125 | * The function returns, in case of success, the PPS source ID. | 67 | * The function returns, in case of success, the PPS device. Otherwise NULL. |
126 | */ | 68 | */ |
127 | 69 | ||
128 | int pps_register_source(struct pps_source_info *info, int default_params) | 70 | struct pps_device *pps_register_source(struct pps_source_info *info, |
71 | int default_params) | ||
129 | { | 72 | { |
130 | struct pps_device *pps; | 73 | struct pps_device *pps; |
131 | int id; | ||
132 | int err; | 74 | int err; |
133 | 75 | ||
134 | /* Sanity checks */ | 76 | /* Sanity checks */ |
135 | if ((info->mode & default_params) != default_params) { | 77 | if ((info->mode & default_params) != default_params) { |
136 | printk(KERN_ERR "pps: %s: unsupported default parameters\n", | 78 | pr_err("%s: unsupported default parameters\n", |
137 | info->name); | 79 | info->name); |
138 | err = -EINVAL; | 80 | err = -EINVAL; |
139 | goto pps_register_source_exit; | 81 | goto pps_register_source_exit; |
140 | } | 82 | } |
141 | if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 && | 83 | if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 && |
142 | info->echo == NULL) { | 84 | info->echo == NULL) { |
143 | printk(KERN_ERR "pps: %s: echo function is not defined\n", | 85 | pr_err("%s: echo function is not defined\n", |
144 | info->name); | 86 | info->name); |
145 | err = -EINVAL; | 87 | err = -EINVAL; |
146 | goto pps_register_source_exit; | 88 | goto pps_register_source_exit; |
147 | } | 89 | } |
148 | if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { | 90 | if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { |
149 | printk(KERN_ERR "pps: %s: unspecified time format\n", | 91 | pr_err("%s: unspecified time format\n", |
150 | info->name); | 92 | info->name); |
151 | err = -EINVAL; | 93 | err = -EINVAL; |
152 | goto pps_register_source_exit; | 94 | goto pps_register_source_exit; |
@@ -168,94 +110,48 @@ int pps_register_source(struct pps_source_info *info, int default_params) | |||
168 | 110 | ||
169 | init_waitqueue_head(&pps->queue); | 111 | init_waitqueue_head(&pps->queue); |
170 | spin_lock_init(&pps->lock); | 112 | spin_lock_init(&pps->lock); |
171 | atomic_set(&pps->usage, 1); | ||
172 | |||
173 | /* Get new ID for the new PPS source */ | ||
174 | if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) { | ||
175 | err = -ENOMEM; | ||
176 | goto kfree_pps; | ||
177 | } | ||
178 | |||
179 | spin_lock_irq(&pps_idr_lock); | ||
180 | |||
181 | /* Now really allocate the PPS source. | ||
182 | * After idr_get_new() calling the new source will be freely available | ||
183 | * into the kernel. | ||
184 | */ | ||
185 | err = idr_get_new(&pps_idr, pps, &id); | ||
186 | if (err < 0) { | ||
187 | spin_unlock_irq(&pps_idr_lock); | ||
188 | goto kfree_pps; | ||
189 | } | ||
190 | |||
191 | id = id & MAX_ID_MASK; | ||
192 | if (id >= PPS_MAX_SOURCES) { | ||
193 | spin_unlock_irq(&pps_idr_lock); | ||
194 | |||
195 | printk(KERN_ERR "pps: %s: too many PPS sources in the system\n", | ||
196 | info->name); | ||
197 | err = -EBUSY; | ||
198 | goto free_idr; | ||
199 | } | ||
200 | pps->id = id; | ||
201 | |||
202 | spin_unlock_irq(&pps_idr_lock); | ||
203 | 113 | ||
204 | /* Create the char device */ | 114 | /* Create the char device */ |
205 | err = pps_register_cdev(pps); | 115 | err = pps_register_cdev(pps); |
206 | if (err < 0) { | 116 | if (err < 0) { |
207 | printk(KERN_ERR "pps: %s: unable to create char device\n", | 117 | pr_err("%s: unable to create char device\n", |
208 | info->name); | 118 | info->name); |
209 | goto free_idr; | 119 | goto kfree_pps; |
210 | } | 120 | } |
211 | 121 | ||
212 | pr_info("new PPS source %s at ID %d\n", info->name, id); | 122 | dev_info(pps->dev, "new PPS source %s\n", info->name); |
213 | 123 | ||
214 | return id; | 124 | return pps; |
215 | |||
216 | free_idr: | ||
217 | spin_lock_irq(&pps_idr_lock); | ||
218 | idr_remove(&pps_idr, id); | ||
219 | spin_unlock_irq(&pps_idr_lock); | ||
220 | 125 | ||
221 | kfree_pps: | 126 | kfree_pps: |
222 | kfree(pps); | 127 | kfree(pps); |
223 | 128 | ||
224 | pps_register_source_exit: | 129 | pps_register_source_exit: |
225 | printk(KERN_ERR "pps: %s: unable to register source\n", info->name); | 130 | pr_err("%s: unable to register source\n", info->name); |
226 | 131 | ||
227 | return err; | 132 | return NULL; |
228 | } | 133 | } |
229 | EXPORT_SYMBOL(pps_register_source); | 134 | EXPORT_SYMBOL(pps_register_source); |
230 | 135 | ||
231 | /* pps_unregister_source - remove a PPS source from the system | 136 | /* pps_unregister_source - remove a PPS source from the system |
232 | * @source: the PPS source ID | 137 | * @pps: the PPS source |
233 | * | 138 | * |
234 | * This function is used to remove a previously registered PPS source from | 139 | * This function is used to remove a previously registered PPS source from |
235 | * the system. | 140 | * the system. |
236 | */ | 141 | */ |
237 | 142 | ||
238 | void pps_unregister_source(int source) | 143 | void pps_unregister_source(struct pps_device *pps) |
239 | { | 144 | { |
240 | struct pps_device *pps; | 145 | pps_kc_remove(pps); |
241 | |||
242 | spin_lock_irq(&pps_idr_lock); | ||
243 | pps = idr_find(&pps_idr, source); | ||
244 | |||
245 | if (!pps) { | ||
246 | BUG(); | ||
247 | spin_unlock_irq(&pps_idr_lock); | ||
248 | return; | ||
249 | } | ||
250 | spin_unlock_irq(&pps_idr_lock); | ||
251 | |||
252 | pps_unregister_cdev(pps); | 146 | pps_unregister_cdev(pps); |
253 | pps_put_source(pps); | 147 | |
148 | /* don't have to kfree(pps) here because it will be done on | ||
149 | * device destruction */ | ||
254 | } | 150 | } |
255 | EXPORT_SYMBOL(pps_unregister_source); | 151 | EXPORT_SYMBOL(pps_unregister_source); |
256 | 152 | ||
257 | /* pps_event - register a PPS event into the system | 153 | /* pps_event - register a PPS event into the system |
258 | * @source: the PPS source ID | 154 | * @pps: the PPS device |
259 | * @ts: the event timestamp | 155 | * @ts: the event timestamp |
260 | * @event: the event type | 156 | * @event: the event type |
261 | * @data: userdef pointer | 157 | * @data: userdef pointer |
@@ -263,78 +159,72 @@ EXPORT_SYMBOL(pps_unregister_source); | |||
263 | * This function is used by each PPS client in order to register a new | 159 | * This function is used by each PPS client in order to register a new |
264 | * PPS event into the system (it's usually called inside an IRQ handler). | 160 | * PPS event into the system (it's usually called inside an IRQ handler). |
265 | * | 161 | * |
266 | * If an echo function is associated with the PPS source it will be called | 162 | * If an echo function is associated with the PPS device it will be called |
267 | * as: | 163 | * as: |
268 | * pps->info.echo(source, event, data); | 164 | * pps->info.echo(pps, event, data); |
269 | */ | 165 | */ |
270 | 166 | void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event, | |
271 | void pps_event(int source, struct pps_ktime *ts, int event, void *data) | 167 | void *data) |
272 | { | 168 | { |
273 | struct pps_device *pps; | ||
274 | unsigned long flags; | 169 | unsigned long flags; |
275 | int captured = 0; | 170 | int captured = 0; |
171 | struct pps_ktime ts_real; | ||
276 | 172 | ||
277 | if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { | 173 | /* check event type */ |
278 | printk(KERN_ERR "pps: unknown event (%x) for source %d\n", | 174 | BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0); |
279 | event, source); | ||
280 | return; | ||
281 | } | ||
282 | 175 | ||
283 | pps = pps_get_source(source); | 176 | dev_dbg(pps->dev, "PPS event at %ld.%09ld\n", |
284 | if (!pps) | 177 | ts->ts_real.tv_sec, ts->ts_real.tv_nsec); |
285 | return; | ||
286 | 178 | ||
287 | pr_debug("PPS event on source %d at %llu.%06u\n", | 179 | timespec_to_pps_ktime(&ts_real, ts->ts_real); |
288 | pps->id, (unsigned long long) ts->sec, ts->nsec); | ||
289 | 180 | ||
290 | spin_lock_irqsave(&pps->lock, flags); | 181 | spin_lock_irqsave(&pps->lock, flags); |
291 | 182 | ||
292 | /* Must call the echo function? */ | 183 | /* Must call the echo function? */ |
293 | if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) | 184 | if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) |
294 | pps->info.echo(source, event, data); | 185 | pps->info.echo(pps, event, data); |
295 | 186 | ||
296 | /* Check the event */ | 187 | /* Check the event */ |
297 | pps->current_mode = pps->params.mode; | 188 | pps->current_mode = pps->params.mode; |
298 | if ((event & PPS_CAPTUREASSERT) & | 189 | if (event & pps->params.mode & PPS_CAPTUREASSERT) { |
299 | (pps->params.mode & PPS_CAPTUREASSERT)) { | ||
300 | /* We have to add an offset? */ | 190 | /* We have to add an offset? */ |
301 | if (pps->params.mode & PPS_OFFSETASSERT) | 191 | if (pps->params.mode & PPS_OFFSETASSERT) |
302 | pps_add_offset(ts, &pps->params.assert_off_tu); | 192 | pps_add_offset(&ts_real, |
193 | &pps->params.assert_off_tu); | ||
303 | 194 | ||
304 | /* Save the time stamp */ | 195 | /* Save the time stamp */ |
305 | pps->assert_tu = *ts; | 196 | pps->assert_tu = ts_real; |
306 | pps->assert_sequence++; | 197 | pps->assert_sequence++; |
307 | pr_debug("capture assert seq #%u for source %d\n", | 198 | dev_dbg(pps->dev, "capture assert seq #%u\n", |
308 | pps->assert_sequence, source); | 199 | pps->assert_sequence); |
309 | 200 | ||
310 | captured = ~0; | 201 | captured = ~0; |
311 | } | 202 | } |
312 | if ((event & PPS_CAPTURECLEAR) & | 203 | if (event & pps->params.mode & PPS_CAPTURECLEAR) { |
313 | (pps->params.mode & PPS_CAPTURECLEAR)) { | ||
314 | /* We have to add an offset? */ | 204 | /* We have to add an offset? */ |
315 | if (pps->params.mode & PPS_OFFSETCLEAR) | 205 | if (pps->params.mode & PPS_OFFSETCLEAR) |
316 | pps_add_offset(ts, &pps->params.clear_off_tu); | 206 | pps_add_offset(&ts_real, |
207 | &pps->params.clear_off_tu); | ||
317 | 208 | ||
318 | /* Save the time stamp */ | 209 | /* Save the time stamp */ |
319 | pps->clear_tu = *ts; | 210 | pps->clear_tu = ts_real; |
320 | pps->clear_sequence++; | 211 | pps->clear_sequence++; |
321 | pr_debug("capture clear seq #%u for source %d\n", | 212 | dev_dbg(pps->dev, "capture clear seq #%u\n", |
322 | pps->clear_sequence, source); | 213 | pps->clear_sequence); |
323 | 214 | ||
324 | captured = ~0; | 215 | captured = ~0; |
325 | } | 216 | } |
326 | 217 | ||
327 | /* Wake up iif captured somthing */ | 218 | pps_kc_event(pps, ts, event); |
219 | |||
220 | /* Wake up if captured something */ | ||
328 | if (captured) { | 221 | if (captured) { |
329 | pps->go = ~0; | 222 | pps->last_ev++; |
330 | wake_up_interruptible(&pps->queue); | 223 | wake_up_interruptible_all(&pps->queue); |
331 | 224 | ||
332 | kill_fasync(&pps->async_queue, SIGIO, POLL_IN); | 225 | kill_fasync(&pps->async_queue, SIGIO, POLL_IN); |
333 | } | 226 | } |
334 | 227 | ||
335 | spin_unlock_irqrestore(&pps->lock, flags); | 228 | spin_unlock_irqrestore(&pps->lock, flags); |
336 | |||
337 | /* Now we can release the PPS source for (possible) deregistration */ | ||
338 | pps_put_source(pps); | ||
339 | } | 229 | } |
340 | EXPORT_SYMBOL(pps_event); | 230 | EXPORT_SYMBOL(pps_event); |
diff --git a/drivers/pps/kc.c b/drivers/pps/kc.c new file mode 100644 index 000000000000..079e930b1938 --- /dev/null +++ b/drivers/pps/kc.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * PPS kernel consumer API | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Alexander Gordeev <lasaine@lvk.cs.msu.su> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/pps_kernel.h> | ||
29 | |||
30 | #include "kc.h" | ||
31 | |||
32 | /* | ||
33 | * Global variables | ||
34 | */ | ||
35 | |||
36 | /* state variables to bind kernel consumer */ | ||
37 | DEFINE_SPINLOCK(pps_kc_hardpps_lock); | ||
38 | /* PPS API (RFC 2783): current source and mode for kernel consumer */ | ||
39 | struct pps_device *pps_kc_hardpps_dev; /* unique pointer to device */ | ||
40 | int pps_kc_hardpps_mode; /* mode bits for kernel consumer */ | ||
41 | |||
42 | /* pps_kc_bind - control PPS kernel consumer binding | ||
43 | * @pps: the PPS source | ||
44 | * @bind_args: kernel consumer bind parameters | ||
45 | * | ||
46 | * This function is used to bind or unbind PPS kernel consumer according to | ||
47 | * supplied parameters. Should not be called in interrupt context. | ||
48 | */ | ||
49 | int pps_kc_bind(struct pps_device *pps, struct pps_bind_args *bind_args) | ||
50 | { | ||
51 | /* Check if another consumer is already bound */ | ||
52 | spin_lock_irq(&pps_kc_hardpps_lock); | ||
53 | |||
54 | if (bind_args->edge == 0) | ||
55 | if (pps_kc_hardpps_dev == pps) { | ||
56 | pps_kc_hardpps_mode = 0; | ||
57 | pps_kc_hardpps_dev = NULL; | ||
58 | spin_unlock_irq(&pps_kc_hardpps_lock); | ||
59 | dev_info(pps->dev, "unbound kernel" | ||
60 | " consumer\n"); | ||
61 | } else { | ||
62 | spin_unlock_irq(&pps_kc_hardpps_lock); | ||
63 | dev_err(pps->dev, "selected kernel consumer" | ||
64 | " is not bound\n"); | ||
65 | return -EINVAL; | ||
66 | } | ||
67 | else | ||
68 | if (pps_kc_hardpps_dev == NULL || | ||
69 | pps_kc_hardpps_dev == pps) { | ||
70 | pps_kc_hardpps_mode = bind_args->edge; | ||
71 | pps_kc_hardpps_dev = pps; | ||
72 | spin_unlock_irq(&pps_kc_hardpps_lock); | ||
73 | dev_info(pps->dev, "bound kernel consumer: " | ||
74 | "edge=0x%x\n", bind_args->edge); | ||
75 | } else { | ||
76 | spin_unlock_irq(&pps_kc_hardpps_lock); | ||
77 | dev_err(pps->dev, "another kernel consumer" | ||
78 | " is already bound\n"); | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /* pps_kc_remove - unbind kernel consumer on PPS source removal | ||
86 | * @pps: the PPS source | ||
87 | * | ||
88 | * This function is used to disable kernel consumer on PPS source removal | ||
89 | * if this source was bound to PPS kernel consumer. Can be called on any | ||
90 | * source safely. Should not be called in interrupt context. | ||
91 | */ | ||
92 | void pps_kc_remove(struct pps_device *pps) | ||
93 | { | ||
94 | spin_lock_irq(&pps_kc_hardpps_lock); | ||
95 | if (pps == pps_kc_hardpps_dev) { | ||
96 | pps_kc_hardpps_mode = 0; | ||
97 | pps_kc_hardpps_dev = NULL; | ||
98 | spin_unlock_irq(&pps_kc_hardpps_lock); | ||
99 | dev_info(pps->dev, "unbound kernel consumer" | ||
100 | " on device removal\n"); | ||
101 | } else | ||
102 | spin_unlock_irq(&pps_kc_hardpps_lock); | ||
103 | } | ||
104 | |||
105 | /* pps_kc_event - call hardpps() on PPS event | ||
106 | * @pps: the PPS source | ||
107 | * @ts: PPS event timestamp | ||
108 | * @event: PPS event edge | ||
109 | * | ||
110 | * This function calls hardpps() when an event from bound PPS source occurs. | ||
111 | */ | ||
112 | void pps_kc_event(struct pps_device *pps, struct pps_event_time *ts, | ||
113 | int event) | ||
114 | { | ||
115 | unsigned long flags; | ||
116 | |||
117 | /* Pass some events to kernel consumer if activated */ | ||
118 | spin_lock_irqsave(&pps_kc_hardpps_lock, flags); | ||
119 | if (pps == pps_kc_hardpps_dev && event & pps_kc_hardpps_mode) | ||
120 | hardpps(&ts->ts_real, &ts->ts_raw); | ||
121 | spin_unlock_irqrestore(&pps_kc_hardpps_lock, flags); | ||
122 | } | ||
diff --git a/drivers/pps/kc.h b/drivers/pps/kc.h new file mode 100644 index 000000000000..d296fcd0a175 --- /dev/null +++ b/drivers/pps/kc.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * PPS kernel consumer API header | ||
3 | * | ||
4 | * Copyright (C) 2009-2010 Alexander Gordeev <lasaine@lvk.cs.msu.su> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef LINUX_PPS_KC_H | ||
22 | #define LINUX_PPS_KC_H | ||
23 | |||
24 | #include <linux/errno.h> | ||
25 | #include <linux/pps_kernel.h> | ||
26 | |||
27 | #ifdef CONFIG_NTP_PPS | ||
28 | |||
29 | extern int pps_kc_bind(struct pps_device *pps, | ||
30 | struct pps_bind_args *bind_args); | ||
31 | extern void pps_kc_remove(struct pps_device *pps); | ||
32 | extern void pps_kc_event(struct pps_device *pps, | ||
33 | struct pps_event_time *ts, int event); | ||
34 | |||
35 | |||
36 | #else /* CONFIG_NTP_PPS */ | ||
37 | |||
38 | static inline int pps_kc_bind(struct pps_device *pps, | ||
39 | struct pps_bind_args *bind_args) { return -EOPNOTSUPP; } | ||
40 | static inline void pps_kc_remove(struct pps_device *pps) {} | ||
41 | static inline void pps_kc_event(struct pps_device *pps, | ||
42 | struct pps_event_time *ts, int event) {} | ||
43 | |||
44 | #endif /* CONFIG_NTP_PPS */ | ||
45 | |||
46 | #endif /* LINUX_PPS_KC_H */ | ||
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index ca5183bdad85..2baadd21b7a6 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
22 | 23 | ||
23 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -26,9 +27,13 @@ | |||
26 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
27 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
28 | #include <linux/idr.h> | 29 | #include <linux/idr.h> |
30 | #include <linux/mutex.h> | ||
29 | #include <linux/cdev.h> | 31 | #include <linux/cdev.h> |
30 | #include <linux/poll.h> | 32 | #include <linux/poll.h> |
31 | #include <linux/pps_kernel.h> | 33 | #include <linux/pps_kernel.h> |
34 | #include <linux/slab.h> | ||
35 | |||
36 | #include "kc.h" | ||
32 | 37 | ||
33 | /* | 38 | /* |
34 | * Local variables | 39 | * Local variables |
@@ -37,6 +42,9 @@ | |||
37 | static dev_t pps_devt; | 42 | static dev_t pps_devt; |
38 | static struct class *pps_class; | 43 | static struct class *pps_class; |
39 | 44 | ||
45 | static DEFINE_MUTEX(pps_idr_lock); | ||
46 | static DEFINE_IDR(pps_idr); | ||
47 | |||
40 | /* | 48 | /* |
41 | * Char device methods | 49 | * Char device methods |
42 | */ | 50 | */ |
@@ -61,15 +69,13 @@ static long pps_cdev_ioctl(struct file *file, | |||
61 | { | 69 | { |
62 | struct pps_device *pps = file->private_data; | 70 | struct pps_device *pps = file->private_data; |
63 | struct pps_kparams params; | 71 | struct pps_kparams params; |
64 | struct pps_fdata fdata; | ||
65 | unsigned long ticks; | ||
66 | void __user *uarg = (void __user *) arg; | 72 | void __user *uarg = (void __user *) arg; |
67 | int __user *iuarg = (int __user *) arg; | 73 | int __user *iuarg = (int __user *) arg; |
68 | int err; | 74 | int err; |
69 | 75 | ||
70 | switch (cmd) { | 76 | switch (cmd) { |
71 | case PPS_GETPARAMS: | 77 | case PPS_GETPARAMS: |
72 | pr_debug("PPS_GETPARAMS: source %d\n", pps->id); | 78 | dev_dbg(pps->dev, "PPS_GETPARAMS\n"); |
73 | 79 | ||
74 | spin_lock_irq(&pps->lock); | 80 | spin_lock_irq(&pps->lock); |
75 | 81 | ||
@@ -85,7 +91,7 @@ static long pps_cdev_ioctl(struct file *file, | |||
85 | break; | 91 | break; |
86 | 92 | ||
87 | case PPS_SETPARAMS: | 93 | case PPS_SETPARAMS: |
88 | pr_debug("PPS_SETPARAMS: source %d\n", pps->id); | 94 | dev_dbg(pps->dev, "PPS_SETPARAMS\n"); |
89 | 95 | ||
90 | /* Check the capabilities */ | 96 | /* Check the capabilities */ |
91 | if (!capable(CAP_SYS_TIME)) | 97 | if (!capable(CAP_SYS_TIME)) |
@@ -95,14 +101,14 @@ static long pps_cdev_ioctl(struct file *file, | |||
95 | if (err) | 101 | if (err) |
96 | return -EFAULT; | 102 | return -EFAULT; |
97 | if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) { | 103 | if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) { |
98 | pr_debug("capture mode unspecified (%x)\n", | 104 | dev_dbg(pps->dev, "capture mode unspecified (%x)\n", |
99 | params.mode); | 105 | params.mode); |
100 | return -EINVAL; | 106 | return -EINVAL; |
101 | } | 107 | } |
102 | 108 | ||
103 | /* Check for supported capabilities */ | 109 | /* Check for supported capabilities */ |
104 | if ((params.mode & ~pps->info.mode) != 0) { | 110 | if ((params.mode & ~pps->info.mode) != 0) { |
105 | pr_debug("unsupported capabilities (%x)\n", | 111 | dev_dbg(pps->dev, "unsupported capabilities (%x)\n", |
106 | params.mode); | 112 | params.mode); |
107 | return -EINVAL; | 113 | return -EINVAL; |
108 | } | 114 | } |
@@ -115,7 +121,7 @@ static long pps_cdev_ioctl(struct file *file, | |||
115 | /* Restore the read only parameters */ | 121 | /* Restore the read only parameters */ |
116 | if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { | 122 | if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { |
117 | /* section 3.3 of RFC 2783 interpreted */ | 123 | /* section 3.3 of RFC 2783 interpreted */ |
118 | pr_debug("time format unspecified (%x)\n", | 124 | dev_dbg(pps->dev, "time format unspecified (%x)\n", |
119 | params.mode); | 125 | params.mode); |
120 | pps->params.mode |= PPS_TSFMT_TSPEC; | 126 | pps->params.mode |= PPS_TSFMT_TSPEC; |
121 | } | 127 | } |
@@ -128,7 +134,7 @@ static long pps_cdev_ioctl(struct file *file, | |||
128 | break; | 134 | break; |
129 | 135 | ||
130 | case PPS_GETCAP: | 136 | case PPS_GETCAP: |
131 | pr_debug("PPS_GETCAP: source %d\n", pps->id); | 137 | dev_dbg(pps->dev, "PPS_GETCAP\n"); |
132 | 138 | ||
133 | err = put_user(pps->info.mode, iuarg); | 139 | err = put_user(pps->info.mode, iuarg); |
134 | if (err) | 140 | if (err) |
@@ -136,20 +142,26 @@ static long pps_cdev_ioctl(struct file *file, | |||
136 | 142 | ||
137 | break; | 143 | break; |
138 | 144 | ||
139 | case PPS_FETCH: | 145 | case PPS_FETCH: { |
140 | pr_debug("PPS_FETCH: source %d\n", pps->id); | 146 | struct pps_fdata fdata; |
147 | unsigned int ev; | ||
148 | |||
149 | dev_dbg(pps->dev, "PPS_FETCH\n"); | ||
141 | 150 | ||
142 | err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata)); | 151 | err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata)); |
143 | if (err) | 152 | if (err) |
144 | return -EFAULT; | 153 | return -EFAULT; |
145 | 154 | ||
146 | pps->go = 0; | 155 | ev = pps->last_ev; |
147 | 156 | ||
148 | /* Manage the timeout */ | 157 | /* Manage the timeout */ |
149 | if (fdata.timeout.flags & PPS_TIME_INVALID) | 158 | if (fdata.timeout.flags & PPS_TIME_INVALID) |
150 | err = wait_event_interruptible(pps->queue, pps->go); | 159 | err = wait_event_interruptible(pps->queue, |
160 | ev != pps->last_ev); | ||
151 | else { | 161 | else { |
152 | pr_debug("timeout %lld.%09d\n", | 162 | unsigned long ticks; |
163 | |||
164 | dev_dbg(pps->dev, "timeout %lld.%09d\n", | ||
153 | (long long) fdata.timeout.sec, | 165 | (long long) fdata.timeout.sec, |
154 | fdata.timeout.nsec); | 166 | fdata.timeout.nsec); |
155 | ticks = fdata.timeout.sec * HZ; | 167 | ticks = fdata.timeout.sec * HZ; |
@@ -157,7 +169,9 @@ static long pps_cdev_ioctl(struct file *file, | |||
157 | 169 | ||
158 | if (ticks != 0) { | 170 | if (ticks != 0) { |
159 | err = wait_event_interruptible_timeout( | 171 | err = wait_event_interruptible_timeout( |
160 | pps->queue, pps->go, ticks); | 172 | pps->queue, |
173 | ev != pps->last_ev, | ||
174 | ticks); | ||
161 | if (err == 0) | 175 | if (err == 0) |
162 | return -ETIMEDOUT; | 176 | return -ETIMEDOUT; |
163 | } | 177 | } |
@@ -165,7 +179,7 @@ static long pps_cdev_ioctl(struct file *file, | |||
165 | 179 | ||
166 | /* Check for pending signals */ | 180 | /* Check for pending signals */ |
167 | if (err == -ERESTARTSYS) { | 181 | if (err == -ERESTARTSYS) { |
168 | pr_debug("pending signal caught\n"); | 182 | dev_dbg(pps->dev, "pending signal caught\n"); |
169 | return -EINTR; | 183 | return -EINTR; |
170 | } | 184 | } |
171 | 185 | ||
@@ -185,10 +199,44 @@ static long pps_cdev_ioctl(struct file *file, | |||
185 | return -EFAULT; | 199 | return -EFAULT; |
186 | 200 | ||
187 | break; | 201 | break; |
202 | } | ||
203 | case PPS_KC_BIND: { | ||
204 | struct pps_bind_args bind_args; | ||
205 | |||
206 | dev_dbg(pps->dev, "PPS_KC_BIND\n"); | ||
207 | |||
208 | /* Check the capabilities */ | ||
209 | if (!capable(CAP_SYS_TIME)) | ||
210 | return -EPERM; | ||
211 | |||
212 | if (copy_from_user(&bind_args, uarg, | ||
213 | sizeof(struct pps_bind_args))) | ||
214 | return -EFAULT; | ||
188 | 215 | ||
216 | /* Check for supported capabilities */ | ||
217 | if ((bind_args.edge & ~pps->info.mode) != 0) { | ||
218 | dev_err(pps->dev, "unsupported capabilities (%x)\n", | ||
219 | bind_args.edge); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | /* Validate parameters roughly */ | ||
224 | if (bind_args.tsformat != PPS_TSFMT_TSPEC || | ||
225 | (bind_args.edge & ~PPS_CAPTUREBOTH) != 0 || | ||
226 | bind_args.consumer != PPS_KC_HARDPPS) { | ||
227 | dev_err(pps->dev, "invalid kernel consumer bind" | ||
228 | " parameters (%x)\n", bind_args.edge); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | |||
232 | err = pps_kc_bind(pps, &bind_args); | ||
233 | if (err < 0) | ||
234 | return err; | ||
235 | |||
236 | break; | ||
237 | } | ||
189 | default: | 238 | default: |
190 | return -ENOTTY; | 239 | return -ENOTTY; |
191 | break; | ||
192 | } | 240 | } |
193 | 241 | ||
194 | return 0; | 242 | return 0; |
@@ -198,12 +246,6 @@ static int pps_cdev_open(struct inode *inode, struct file *file) | |||
198 | { | 246 | { |
199 | struct pps_device *pps = container_of(inode->i_cdev, | 247 | struct pps_device *pps = container_of(inode->i_cdev, |
200 | struct pps_device, cdev); | 248 | struct pps_device, cdev); |
201 | int found; | ||
202 | |||
203 | found = pps_get_source(pps->id) != 0; | ||
204 | if (!found) | ||
205 | return -ENODEV; | ||
206 | |||
207 | file->private_data = pps; | 249 | file->private_data = pps; |
208 | 250 | ||
209 | return 0; | 251 | return 0; |
@@ -211,11 +253,6 @@ static int pps_cdev_open(struct inode *inode, struct file *file) | |||
211 | 253 | ||
212 | static int pps_cdev_release(struct inode *inode, struct file *file) | 254 | static int pps_cdev_release(struct inode *inode, struct file *file) |
213 | { | 255 | { |
214 | struct pps_device *pps = file->private_data; | ||
215 | |||
216 | /* Free the PPS source and wake up (possible) deregistration */ | ||
217 | pps_put_source(pps); | ||
218 | |||
219 | return 0; | 256 | return 0; |
220 | } | 257 | } |
221 | 258 | ||
@@ -233,25 +270,67 @@ static const struct file_operations pps_cdev_fops = { | |||
233 | .release = pps_cdev_release, | 270 | .release = pps_cdev_release, |
234 | }; | 271 | }; |
235 | 272 | ||
273 | static void pps_device_destruct(struct device *dev) | ||
274 | { | ||
275 | struct pps_device *pps = dev_get_drvdata(dev); | ||
276 | |||
277 | /* release id here to protect others from using it while it's | ||
278 | * still in use */ | ||
279 | mutex_lock(&pps_idr_lock); | ||
280 | idr_remove(&pps_idr, pps->id); | ||
281 | mutex_unlock(&pps_idr_lock); | ||
282 | |||
283 | kfree(dev); | ||
284 | kfree(pps); | ||
285 | } | ||
286 | |||
236 | int pps_register_cdev(struct pps_device *pps) | 287 | int pps_register_cdev(struct pps_device *pps) |
237 | { | 288 | { |
238 | int err; | 289 | int err; |
290 | dev_t devt; | ||
291 | |||
292 | mutex_lock(&pps_idr_lock); | ||
293 | /* Get new ID for the new PPS source */ | ||
294 | if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) { | ||
295 | mutex_unlock(&pps_idr_lock); | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | |||
299 | /* Now really allocate the PPS source. | ||
300 | * After idr_get_new() calling the new source will be freely available | ||
301 | * into the kernel. | ||
302 | */ | ||
303 | err = idr_get_new(&pps_idr, pps, &pps->id); | ||
304 | mutex_unlock(&pps_idr_lock); | ||
305 | |||
306 | if (err < 0) | ||
307 | return err; | ||
308 | |||
309 | pps->id &= MAX_ID_MASK; | ||
310 | if (pps->id >= PPS_MAX_SOURCES) { | ||
311 | pr_err("%s: too many PPS sources in the system\n", | ||
312 | pps->info.name); | ||
313 | err = -EBUSY; | ||
314 | goto free_idr; | ||
315 | } | ||
316 | |||
317 | devt = MKDEV(MAJOR(pps_devt), pps->id); | ||
239 | 318 | ||
240 | pps->devno = MKDEV(MAJOR(pps_devt), pps->id); | ||
241 | cdev_init(&pps->cdev, &pps_cdev_fops); | 319 | cdev_init(&pps->cdev, &pps_cdev_fops); |
242 | pps->cdev.owner = pps->info.owner; | 320 | pps->cdev.owner = pps->info.owner; |
243 | 321 | ||
244 | err = cdev_add(&pps->cdev, pps->devno, 1); | 322 | err = cdev_add(&pps->cdev, devt, 1); |
245 | if (err) { | 323 | if (err) { |
246 | printk(KERN_ERR "pps: %s: failed to add char device %d:%d\n", | 324 | pr_err("%s: failed to add char device %d:%d\n", |
247 | pps->info.name, MAJOR(pps_devt), pps->id); | 325 | pps->info.name, MAJOR(pps_devt), pps->id); |
248 | return err; | 326 | goto free_idr; |
249 | } | 327 | } |
250 | pps->dev = device_create(pps_class, pps->info.dev, pps->devno, NULL, | 328 | pps->dev = device_create(pps_class, pps->info.dev, devt, pps, |
251 | "pps%d", pps->id); | 329 | "pps%d", pps->id); |
252 | if (IS_ERR(pps->dev)) | 330 | if (IS_ERR(pps->dev)) |
253 | goto del_cdev; | 331 | goto del_cdev; |
254 | dev_set_drvdata(pps->dev, pps); | 332 | |
333 | pps->dev->release = pps_device_destruct; | ||
255 | 334 | ||
256 | pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, | 335 | pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, |
257 | MAJOR(pps_devt), pps->id); | 336 | MAJOR(pps_devt), pps->id); |
@@ -261,12 +340,17 @@ int pps_register_cdev(struct pps_device *pps) | |||
261 | del_cdev: | 340 | del_cdev: |
262 | cdev_del(&pps->cdev); | 341 | cdev_del(&pps->cdev); |
263 | 342 | ||
343 | free_idr: | ||
344 | mutex_lock(&pps_idr_lock); | ||
345 | idr_remove(&pps_idr, pps->id); | ||
346 | mutex_unlock(&pps_idr_lock); | ||
347 | |||
264 | return err; | 348 | return err; |
265 | } | 349 | } |
266 | 350 | ||
267 | void pps_unregister_cdev(struct pps_device *pps) | 351 | void pps_unregister_cdev(struct pps_device *pps) |
268 | { | 352 | { |
269 | device_destroy(pps_class, pps->devno); | 353 | device_destroy(pps_class, pps->dev->devt); |
270 | cdev_del(&pps->cdev); | 354 | cdev_del(&pps->cdev); |
271 | } | 355 | } |
272 | 356 | ||
@@ -286,14 +370,14 @@ static int __init pps_init(void) | |||
286 | 370 | ||
287 | pps_class = class_create(THIS_MODULE, "pps"); | 371 | pps_class = class_create(THIS_MODULE, "pps"); |
288 | if (!pps_class) { | 372 | if (!pps_class) { |
289 | printk(KERN_ERR "pps: failed to allocate class\n"); | 373 | pr_err("failed to allocate class\n"); |
290 | return -ENOMEM; | 374 | return -ENOMEM; |
291 | } | 375 | } |
292 | pps_class->dev_attrs = pps_attrs; | 376 | pps_class->dev_attrs = pps_attrs; |
293 | 377 | ||
294 | err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps"); | 378 | err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps"); |
295 | if (err < 0) { | 379 | if (err < 0) { |
296 | printk(KERN_ERR "pps: failed to allocate char device region\n"); | 380 | pr_err("failed to allocate char device region\n"); |
297 | goto remove_class; | 381 | goto remove_class; |
298 | } | 382 | } |
299 | 383 | ||
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 1eb82c4c712e..467e82bd0929 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -46,7 +46,6 @@ static void rio_init_em(struct rio_dev *rdev); | |||
46 | DEFINE_SPINLOCK(rio_global_list_lock); | 46 | DEFINE_SPINLOCK(rio_global_list_lock); |
47 | 47 | ||
48 | static int next_destid = 0; | 48 | static int next_destid = 0; |
49 | static int next_switchid = 0; | ||
50 | static int next_net = 0; | 49 | static int next_net = 0; |
51 | static int next_comptag = 1; | 50 | static int next_comptag = 1; |
52 | 51 | ||
@@ -378,12 +377,30 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
378 | struct rio_dev *rdev; | 377 | struct rio_dev *rdev; |
379 | struct rio_switch *rswitch = NULL; | 378 | struct rio_switch *rswitch = NULL; |
380 | int result, rdid; | 379 | int result, rdid; |
380 | size_t size; | ||
381 | u32 swpinfo = 0; | ||
381 | 382 | ||
382 | rdev = kzalloc(sizeof(struct rio_dev), GFP_KERNEL); | 383 | size = sizeof(struct rio_dev); |
384 | if (rio_mport_read_config_32(port, destid, hopcount, | ||
385 | RIO_PEF_CAR, &result)) | ||
386 | return NULL; | ||
387 | |||
388 | if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { | ||
389 | rio_mport_read_config_32(port, destid, hopcount, | ||
390 | RIO_SWP_INFO_CAR, &swpinfo); | ||
391 | if (result & RIO_PEF_SWITCH) { | ||
392 | size += (RIO_GET_TOTAL_PORTS(swpinfo) * | ||
393 | sizeof(rswitch->nextdev[0])) + sizeof(*rswitch); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | rdev = kzalloc(size, GFP_KERNEL); | ||
383 | if (!rdev) | 398 | if (!rdev) |
384 | return NULL; | 399 | return NULL; |
385 | 400 | ||
386 | rdev->net = net; | 401 | rdev->net = net; |
402 | rdev->pef = result; | ||
403 | rdev->swpinfo = swpinfo; | ||
387 | rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, | 404 | rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR, |
388 | &result); | 405 | &result); |
389 | rdev->did = result >> 16; | 406 | rdev->did = result >> 16; |
@@ -397,8 +414,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
397 | rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, | 414 | rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR, |
398 | &result); | 415 | &result); |
399 | rdev->asm_rev = result >> 16; | 416 | rdev->asm_rev = result >> 16; |
400 | rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, | ||
401 | &rdev->pef); | ||
402 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { | 417 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { |
403 | rdev->efptr = result & 0xffff; | 418 | rdev->efptr = result & 0xffff; |
404 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, | 419 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, |
@@ -408,11 +423,6 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
408 | hopcount, RIO_EFB_ERR_MGMNT); | 423 | hopcount, RIO_EFB_ERR_MGMNT); |
409 | } | 424 | } |
410 | 425 | ||
411 | if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) { | ||
412 | rio_mport_read_config_32(port, destid, hopcount, | ||
413 | RIO_SWP_INFO_CAR, &rdev->swpinfo); | ||
414 | } | ||
415 | |||
416 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, | 426 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, |
417 | &rdev->src_ops); | 427 | &rdev->src_ops); |
418 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, | 428 | rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, |
@@ -427,6 +437,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
427 | rio_mport_write_config_32(port, destid, hopcount, | 437 | rio_mport_write_config_32(port, destid, hopcount, |
428 | RIO_COMPONENT_TAG_CSR, next_comptag); | 438 | RIO_COMPONENT_TAG_CSR, next_comptag); |
429 | rdev->comp_tag = next_comptag++; | 439 | rdev->comp_tag = next_comptag++; |
440 | } else { | ||
441 | rio_mport_read_config_32(port, destid, hopcount, | ||
442 | RIO_COMPONENT_TAG_CSR, | ||
443 | &rdev->comp_tag); | ||
430 | } | 444 | } |
431 | 445 | ||
432 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { | 446 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { |
@@ -437,21 +451,20 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
437 | next_destid++; | 451 | next_destid++; |
438 | } else | 452 | } else |
439 | rdev->destid = rio_get_device_id(port, destid, hopcount); | 453 | rdev->destid = rio_get_device_id(port, destid, hopcount); |
440 | } else | 454 | |
441 | /* Switch device has an associated destID */ | 455 | rdev->hopcount = 0xff; |
442 | rdev->destid = RIO_INVALID_DESTID; | 456 | } else { |
457 | /* Switch device has an associated destID which | ||
458 | * will be adjusted later | ||
459 | */ | ||
460 | rdev->destid = destid; | ||
461 | rdev->hopcount = hopcount; | ||
462 | } | ||
443 | 463 | ||
444 | /* If a PE has both switch and other functions, show it as a switch */ | 464 | /* If a PE has both switch and other functions, show it as a switch */ |
445 | if (rio_is_switch(rdev)) { | 465 | if (rio_is_switch(rdev)) { |
446 | rswitch = kzalloc(sizeof(*rswitch) + | 466 | rswitch = rdev->rswitch; |
447 | RIO_GET_TOTAL_PORTS(rdev->swpinfo) * | 467 | rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID; |
448 | sizeof(rswitch->nextdev[0]), | ||
449 | GFP_KERNEL); | ||
450 | if (!rswitch) | ||
451 | goto cleanup; | ||
452 | rswitch->switchid = next_switchid; | ||
453 | rswitch->hopcount = hopcount; | ||
454 | rswitch->destid = destid; | ||
455 | rswitch->port_ok = 0; | 468 | rswitch->port_ok = 0; |
456 | rswitch->route_table = kzalloc(sizeof(u8)* | 469 | rswitch->route_table = kzalloc(sizeof(u8)* |
457 | RIO_MAX_ROUTE_ENTRIES(port->sys_size), | 470 | RIO_MAX_ROUTE_ENTRIES(port->sys_size), |
@@ -462,15 +475,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
462 | for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); | 475 | for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size); |
463 | rdid++) | 476 | rdid++) |
464 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; | 477 | rswitch->route_table[rdid] = RIO_INVALID_ROUTE; |
465 | rdev->rswitch = rswitch; | ||
466 | rswitch->rdev = rdev; | ||
467 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, | 478 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, |
468 | rdev->rswitch->switchid); | 479 | rswitch->switchid); |
469 | rio_switch_init(rdev, do_enum); | 480 | rio_switch_init(rdev, do_enum); |
470 | 481 | ||
471 | if (do_enum && rdev->rswitch->clr_table) | 482 | if (do_enum && rswitch->clr_table) |
472 | rdev->rswitch->clr_table(port, destid, hopcount, | 483 | rswitch->clr_table(port, destid, hopcount, |
473 | RIO_GLOBAL_TABLE); | 484 | RIO_GLOBAL_TABLE); |
474 | 485 | ||
475 | list_add_tail(&rswitch->node, &rio_switches); | 486 | list_add_tail(&rswitch->node, &rio_switches); |
476 | 487 | ||
@@ -506,10 +517,9 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
506 | return rdev; | 517 | return rdev; |
507 | 518 | ||
508 | cleanup: | 519 | cleanup: |
509 | if (rswitch) { | 520 | if (rswitch->route_table) |
510 | kfree(rswitch->route_table); | 521 | kfree(rswitch->route_table); |
511 | kfree(rswitch); | 522 | |
512 | } | ||
513 | kfree(rdev); | 523 | kfree(rdev); |
514 | return NULL; | 524 | return NULL; |
515 | } | 525 | } |
@@ -632,8 +642,7 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) | |||
632 | 642 | ||
633 | /** | 643 | /** |
634 | * rio_route_add_entry- Add a route entry to a switch routing table | 644 | * rio_route_add_entry- Add a route entry to a switch routing table |
635 | * @mport: Master port to send transaction | 645 | * @rdev: RIO device |
636 | * @rswitch: Switch device | ||
637 | * @table: Routing table ID | 646 | * @table: Routing table ID |
638 | * @route_destid: Destination ID to be routed | 647 | * @route_destid: Destination ID to be routed |
639 | * @route_port: Port number to be routed | 648 | * @route_port: Port number to be routed |
@@ -647,31 +656,31 @@ rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) | |||
647 | * on failure. | 656 | * on failure. |
648 | */ | 657 | */ |
649 | static int | 658 | static int |
650 | rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, | 659 | rio_route_add_entry(struct rio_dev *rdev, |
651 | u16 table, u16 route_destid, u8 route_port, int lock) | 660 | u16 table, u16 route_destid, u8 route_port, int lock) |
652 | { | 661 | { |
653 | int rc; | 662 | int rc; |
654 | 663 | ||
655 | if (lock) { | 664 | if (lock) { |
656 | rc = rio_lock_device(mport, rswitch->destid, | 665 | rc = rio_lock_device(rdev->net->hport, rdev->destid, |
657 | rswitch->hopcount, 1000); | 666 | rdev->hopcount, 1000); |
658 | if (rc) | 667 | if (rc) |
659 | return rc; | 668 | return rc; |
660 | } | 669 | } |
661 | 670 | ||
662 | rc = rswitch->add_entry(mport, rswitch->destid, | 671 | rc = rdev->rswitch->add_entry(rdev->net->hport, rdev->destid, |
663 | rswitch->hopcount, table, | 672 | rdev->hopcount, table, |
664 | route_destid, route_port); | 673 | route_destid, route_port); |
665 | if (lock) | 674 | if (lock) |
666 | rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); | 675 | rio_unlock_device(rdev->net->hport, rdev->destid, |
676 | rdev->hopcount); | ||
667 | 677 | ||
668 | return rc; | 678 | return rc; |
669 | } | 679 | } |
670 | 680 | ||
671 | /** | 681 | /** |
672 | * rio_route_get_entry- Read a route entry in a switch routing table | 682 | * rio_route_get_entry- Read a route entry in a switch routing table |
673 | * @mport: Master port to send transaction | 683 | * @rdev: RIO device |
674 | * @rswitch: Switch device | ||
675 | * @table: Routing table ID | 684 | * @table: Routing table ID |
676 | * @route_destid: Destination ID to be routed | 685 | * @route_destid: Destination ID to be routed |
677 | * @route_port: Pointer to read port number into | 686 | * @route_port: Pointer to read port number into |
@@ -685,23 +694,24 @@ rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, | |||
685 | * on failure. | 694 | * on failure. |
686 | */ | 695 | */ |
687 | static int | 696 | static int |
688 | rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, | 697 | rio_route_get_entry(struct rio_dev *rdev, u16 table, |
689 | u16 route_destid, u8 *route_port, int lock) | 698 | u16 route_destid, u8 *route_port, int lock) |
690 | { | 699 | { |
691 | int rc; | 700 | int rc; |
692 | 701 | ||
693 | if (lock) { | 702 | if (lock) { |
694 | rc = rio_lock_device(mport, rswitch->destid, | 703 | rc = rio_lock_device(rdev->net->hport, rdev->destid, |
695 | rswitch->hopcount, 1000); | 704 | rdev->hopcount, 1000); |
696 | if (rc) | 705 | if (rc) |
697 | return rc; | 706 | return rc; |
698 | } | 707 | } |
699 | 708 | ||
700 | rc = rswitch->get_entry(mport, rswitch->destid, | 709 | rc = rdev->rswitch->get_entry(rdev->net->hport, rdev->destid, |
701 | rswitch->hopcount, table, | 710 | rdev->hopcount, table, |
702 | route_destid, route_port); | 711 | route_destid, route_port); |
703 | if (lock) | 712 | if (lock) |
704 | rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); | 713 | rio_unlock_device(rdev->net->hport, rdev->destid, |
714 | rdev->hopcount); | ||
705 | 715 | ||
706 | return rc; | 716 | return rc; |
707 | } | 717 | } |
@@ -809,16 +819,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
809 | return -1; | 819 | return -1; |
810 | 820 | ||
811 | if (rio_is_switch(rdev)) { | 821 | if (rio_is_switch(rdev)) { |
812 | next_switchid++; | ||
813 | sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); | 822 | sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); |
814 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | 823 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
815 | port->host_deviceid, sw_inport, 0); | 824 | port->host_deviceid, sw_inport, 0); |
816 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; | 825 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; |
817 | 826 | ||
818 | for (destid = 0; destid < next_destid; destid++) { | 827 | for (destid = 0; destid < next_destid; destid++) { |
819 | if (destid == port->host_deviceid) | 828 | if (destid == port->host_deviceid) |
820 | continue; | 829 | continue; |
821 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | 830 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
822 | destid, sw_inport, 0); | 831 | destid, sw_inport, 0); |
823 | rdev->rswitch->route_table[destid] = sw_inport; | 832 | rdev->rswitch->route_table[destid] = sw_inport; |
824 | } | 833 | } |
@@ -850,8 +859,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
850 | "RIO: scanning device on port %d\n", | 859 | "RIO: scanning device on port %d\n", |
851 | port_num); | 860 | port_num); |
852 | rdev->rswitch->port_ok |= (1 << port_num); | 861 | rdev->rswitch->port_ok |= (1 << port_num); |
853 | rio_route_add_entry(port, rdev->rswitch, | 862 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
854 | RIO_GLOBAL_TABLE, | ||
855 | RIO_ANY_DESTID(port->sys_size), | 863 | RIO_ANY_DESTID(port->sys_size), |
856 | port_num, 0); | 864 | port_num, 0); |
857 | 865 | ||
@@ -865,7 +873,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
865 | destid < next_destid; destid++) { | 873 | destid < next_destid; destid++) { |
866 | if (destid == port->host_deviceid) | 874 | if (destid == port->host_deviceid) |
867 | continue; | 875 | continue; |
868 | rio_route_add_entry(port, rdev->rswitch, | 876 | rio_route_add_entry(rdev, |
869 | RIO_GLOBAL_TABLE, | 877 | RIO_GLOBAL_TABLE, |
870 | destid, | 878 | destid, |
871 | port_num, | 879 | port_num, |
@@ -904,7 +912,7 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
904 | next_destid++; | 912 | next_destid++; |
905 | } | 913 | } |
906 | 914 | ||
907 | rdev->rswitch->destid = sw_destid; | 915 | rdev->destid = sw_destid; |
908 | } else | 916 | } else |
909 | pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", | 917 | pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n", |
910 | rio_name(rdev), rdev->vid, rdev->did); | 918 | rio_name(rdev), rdev->vid, rdev->did); |
@@ -941,7 +949,7 @@ static int rio_enum_complete(struct rio_mport *port) | |||
941 | */ | 949 | */ |
942 | static int __devinit | 950 | static int __devinit |
943 | rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | 951 | rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, |
944 | u8 hopcount) | 952 | u8 hopcount, struct rio_dev *prev, int prev_port) |
945 | { | 953 | { |
946 | u8 port_num, route_port; | 954 | u8 port_num, route_port; |
947 | struct rio_dev *rdev; | 955 | struct rio_dev *rdev; |
@@ -951,14 +959,15 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
951 | if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { | 959 | if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) { |
952 | /* Add device to the global and bus/net specific list. */ | 960 | /* Add device to the global and bus/net specific list. */ |
953 | list_add_tail(&rdev->net_list, &net->devices); | 961 | list_add_tail(&rdev->net_list, &net->devices); |
962 | rdev->prev = prev; | ||
963 | if (prev && rio_is_switch(prev)) | ||
964 | prev->rswitch->nextdev[prev_port] = rdev; | ||
954 | } else | 965 | } else |
955 | return -1; | 966 | return -1; |
956 | 967 | ||
957 | if (rio_is_switch(rdev)) { | 968 | if (rio_is_switch(rdev)) { |
958 | next_switchid++; | ||
959 | |||
960 | /* Associated destid is how we accessed this switch */ | 969 | /* Associated destid is how we accessed this switch */ |
961 | rdev->rswitch->destid = destid; | 970 | rdev->destid = destid; |
962 | 971 | ||
963 | pr_debug( | 972 | pr_debug( |
964 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 973 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
@@ -981,7 +990,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
981 | for (ndestid = 0; | 990 | for (ndestid = 0; |
982 | ndestid < RIO_ANY_DESTID(port->sys_size); | 991 | ndestid < RIO_ANY_DESTID(port->sys_size); |
983 | ndestid++) { | 992 | ndestid++) { |
984 | rio_route_get_entry(port, rdev->rswitch, | 993 | rio_route_get_entry(rdev, |
985 | RIO_GLOBAL_TABLE, | 994 | RIO_GLOBAL_TABLE, |
986 | ndestid, | 995 | ndestid, |
987 | &route_port, 0); | 996 | &route_port, 0); |
@@ -992,8 +1001,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
992 | if (ndestid == RIO_ANY_DESTID(port->sys_size)) | 1001 | if (ndestid == RIO_ANY_DESTID(port->sys_size)) |
993 | continue; | 1002 | continue; |
994 | rio_unlock_device(port, destid, hopcount); | 1003 | rio_unlock_device(port, destid, hopcount); |
995 | if (rio_disc_peer | 1004 | if (rio_disc_peer(net, port, ndestid, |
996 | (net, port, ndestid, hopcount + 1) < 0) | 1005 | hopcount + 1, rdev, port_num) < 0) |
997 | return -1; | 1006 | return -1; |
998 | } | 1007 | } |
999 | } | 1008 | } |
@@ -1069,14 +1078,14 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) | |||
1069 | */ | 1078 | */ |
1070 | static void rio_update_route_tables(struct rio_mport *port) | 1079 | static void rio_update_route_tables(struct rio_mport *port) |
1071 | { | 1080 | { |
1072 | struct rio_dev *rdev; | 1081 | struct rio_dev *rdev, *swrdev; |
1073 | struct rio_switch *rswitch; | 1082 | struct rio_switch *rswitch; |
1074 | u8 sport; | 1083 | u8 sport; |
1075 | u16 destid; | 1084 | u16 destid; |
1076 | 1085 | ||
1077 | list_for_each_entry(rdev, &rio_devices, global_list) { | 1086 | list_for_each_entry(rdev, &rio_devices, global_list) { |
1078 | 1087 | ||
1079 | destid = (rio_is_switch(rdev))?rdev->rswitch->destid:rdev->destid; | 1088 | destid = rdev->destid; |
1080 | 1089 | ||
1081 | list_for_each_entry(rswitch, &rio_switches, node) { | 1090 | list_for_each_entry(rswitch, &rio_switches, node) { |
1082 | 1091 | ||
@@ -1084,14 +1093,16 @@ static void rio_update_route_tables(struct rio_mport *port) | |||
1084 | continue; | 1093 | continue; |
1085 | 1094 | ||
1086 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { | 1095 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { |
1096 | swrdev = sw_to_rio_dev(rswitch); | ||
1097 | |||
1087 | /* Skip if destid ends in empty switch*/ | 1098 | /* Skip if destid ends in empty switch*/ |
1088 | if (rswitch->destid == destid) | 1099 | if (swrdev->destid == destid) |
1089 | continue; | 1100 | continue; |
1090 | 1101 | ||
1091 | sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo); | 1102 | sport = RIO_GET_PORT_NUM(swrdev->swpinfo); |
1092 | 1103 | ||
1093 | if (rswitch->add_entry) { | 1104 | if (rswitch->add_entry) { |
1094 | rio_route_add_entry(port, rswitch, | 1105 | rio_route_add_entry(swrdev, |
1095 | RIO_GLOBAL_TABLE, destid, | 1106 | RIO_GLOBAL_TABLE, destid, |
1096 | sport, 0); | 1107 | sport, 0); |
1097 | rswitch->route_table[destid] = sport; | 1108 | rswitch->route_table[destid] = sport; |
@@ -1203,21 +1214,20 @@ static void rio_build_route_tables(void) | |||
1203 | 1214 | ||
1204 | list_for_each_entry(rdev, &rio_devices, global_list) | 1215 | list_for_each_entry(rdev, &rio_devices, global_list) |
1205 | if (rio_is_switch(rdev)) { | 1216 | if (rio_is_switch(rdev)) { |
1206 | rio_lock_device(rdev->net->hport, rdev->rswitch->destid, | 1217 | rio_lock_device(rdev->net->hport, rdev->destid, |
1207 | rdev->rswitch->hopcount, 1000); | 1218 | rdev->hopcount, 1000); |
1208 | for (i = 0; | 1219 | for (i = 0; |
1209 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); | 1220 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); |
1210 | i++) { | 1221 | i++) { |
1211 | if (rio_route_get_entry | 1222 | if (rio_route_get_entry(rdev, |
1212 | (rdev->net->hport, rdev->rswitch, | 1223 | RIO_GLOBAL_TABLE, i, &sport, 0) < 0) |
1213 | RIO_GLOBAL_TABLE, i, &sport, 0) < 0) | ||
1214 | continue; | 1224 | continue; |
1215 | rdev->rswitch->route_table[i] = sport; | 1225 | rdev->rswitch->route_table[i] = sport; |
1216 | } | 1226 | } |
1217 | 1227 | ||
1218 | rio_unlock_device(rdev->net->hport, | 1228 | rio_unlock_device(rdev->net->hport, |
1219 | rdev->rswitch->destid, | 1229 | rdev->destid, |
1220 | rdev->rswitch->hopcount); | 1230 | rdev->hopcount); |
1221 | } | 1231 | } |
1222 | } | 1232 | } |
1223 | 1233 | ||
@@ -1284,7 +1294,7 @@ int __devinit rio_disc_mport(struct rio_mport *mport) | |||
1284 | mport->host_deviceid); | 1294 | mport->host_deviceid); |
1285 | 1295 | ||
1286 | if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), | 1296 | if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), |
1287 | 0) < 0) { | 1297 | 0, NULL, 0) < 0) { |
1288 | printk(KERN_INFO | 1298 | printk(KERN_INFO |
1289 | "RIO: master port %d device has failed discovery\n", | 1299 | "RIO: master port %d device has failed discovery\n", |
1290 | mport->id); | 1300 | mport->id); |
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 137ed93ee33f..76b41853a877 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c | |||
@@ -217,7 +217,7 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) | |||
217 | 217 | ||
218 | err = device_create_bin_file(&rdev->dev, &rio_config_attr); | 218 | err = device_create_bin_file(&rdev->dev, &rio_config_attr); |
219 | 219 | ||
220 | if (!err && rdev->rswitch) { | 220 | if (!err && (rdev->pef & RIO_PEF_SWITCH)) { |
221 | err = device_create_file(&rdev->dev, &dev_attr_routes); | 221 | err = device_create_file(&rdev->dev, &dev_attr_routes); |
222 | if (!err && rdev->rswitch->sw_sysfs) | 222 | if (!err && rdev->rswitch->sw_sysfs) |
223 | err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); | 223 | err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE); |
@@ -239,7 +239,7 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) | |||
239 | void rio_remove_sysfs_dev_files(struct rio_dev *rdev) | 239 | void rio_remove_sysfs_dev_files(struct rio_dev *rdev) |
240 | { | 240 | { |
241 | device_remove_bin_file(&rdev->dev, &rio_config_attr); | 241 | device_remove_bin_file(&rdev->dev, &rio_config_attr); |
242 | if (rdev->rswitch) { | 242 | if (rdev->pef & RIO_PEF_SWITCH) { |
243 | device_remove_file(&rdev->dev, &dev_attr_routes); | 243 | device_remove_file(&rdev->dev, &dev_attr_routes); |
244 | if (rdev->rswitch->sw_sysfs) | 244 | if (rdev->rswitch->sw_sysfs) |
245 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); | 245 | rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); |
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 7b5080c45569..cc2a3b74d0f0 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -471,16 +471,9 @@ exit: | |||
471 | */ | 471 | */ |
472 | int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | 472 | int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) |
473 | { | 473 | { |
474 | u8 hopcount = 0xff; | ||
475 | u16 destid = rdev->destid; | ||
476 | u32 regval; | 474 | u32 regval; |
477 | 475 | ||
478 | if (rdev->rswitch) { | 476 | rio_read_config_32(rdev, |
479 | destid = rdev->rswitch->destid; | ||
480 | hopcount = rdev->rswitch->hopcount; | ||
481 | } | ||
482 | |||
483 | rio_mport_read_config_32(rdev->net->hport, destid, hopcount, | ||
484 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), | 477 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), |
485 | ®val); | 478 | ®val); |
486 | if (lock) | 479 | if (lock) |
@@ -488,7 +481,7 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | |||
488 | else | 481 | else |
489 | regval &= ~RIO_PORT_N_CTL_LOCKOUT; | 482 | regval &= ~RIO_PORT_N_CTL_LOCKOUT; |
490 | 483 | ||
491 | rio_mport_write_config_32(rdev->net->hport, destid, hopcount, | 484 | rio_write_config_32(rdev, |
492 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), | 485 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), |
493 | regval); | 486 | regval); |
494 | return 0; | 487 | return 0; |
@@ -507,7 +500,7 @@ static int | |||
507 | rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) | 500 | rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) |
508 | { | 501 | { |
509 | u32 result; | 502 | u32 result; |
510 | int p_port, dstid, rc = -EIO; | 503 | int p_port, rc = -EIO; |
511 | struct rio_dev *prev = NULL; | 504 | struct rio_dev *prev = NULL; |
512 | 505 | ||
513 | /* Find switch with failed RIO link */ | 506 | /* Find switch with failed RIO link */ |
@@ -522,9 +515,7 @@ rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum) | |||
522 | if (prev == NULL) | 515 | if (prev == NULL) |
523 | goto err_out; | 516 | goto err_out; |
524 | 517 | ||
525 | dstid = (rdev->pef & RIO_PEF_SWITCH) ? | 518 | p_port = prev->rswitch->route_table[rdev->destid]; |
526 | rdev->rswitch->destid : rdev->destid; | ||
527 | p_port = prev->rswitch->route_table[dstid]; | ||
528 | 519 | ||
529 | if (p_port != RIO_INVALID_ROUTE) { | 520 | if (p_port != RIO_INVALID_ROUTE) { |
530 | pr_debug("RIO: link failed on [%s]-P%d\n", | 521 | pr_debug("RIO: link failed on [%s]-P%d\n", |
@@ -567,15 +558,8 @@ rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount) | |||
567 | */ | 558 | */ |
568 | static int rio_chk_dev_access(struct rio_dev *rdev) | 559 | static int rio_chk_dev_access(struct rio_dev *rdev) |
569 | { | 560 | { |
570 | u8 hopcount = 0xff; | 561 | return rio_mport_chk_dev_access(rdev->net->hport, |
571 | u16 destid = rdev->destid; | 562 | rdev->destid, rdev->hopcount); |
572 | |||
573 | if (rdev->rswitch) { | ||
574 | destid = rdev->rswitch->destid; | ||
575 | hopcount = rdev->rswitch->hopcount; | ||
576 | } | ||
577 | |||
578 | return rio_mport_chk_dev_access(rdev->net->hport, destid, hopcount); | ||
579 | } | 563 | } |
580 | 564 | ||
581 | /** | 565 | /** |
@@ -588,23 +572,20 @@ static int rio_chk_dev_access(struct rio_dev *rdev) | |||
588 | static int | 572 | static int |
589 | rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) | 573 | rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) |
590 | { | 574 | { |
591 | struct rio_mport *mport = rdev->net->hport; | ||
592 | u16 destid = rdev->rswitch->destid; | ||
593 | u8 hopcount = rdev->rswitch->hopcount; | ||
594 | u32 regval; | 575 | u32 regval; |
595 | int checkcount; | 576 | int checkcount; |
596 | 577 | ||
597 | if (lnkresp) { | 578 | if (lnkresp) { |
598 | /* Read from link maintenance response register | 579 | /* Read from link maintenance response register |
599 | * to clear valid bit */ | 580 | * to clear valid bit */ |
600 | rio_mport_read_config_32(mport, destid, hopcount, | 581 | rio_read_config_32(rdev, |
601 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), | 582 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), |
602 | ®val); | 583 | ®val); |
603 | udelay(50); | 584 | udelay(50); |
604 | } | 585 | } |
605 | 586 | ||
606 | /* Issue Input-status command */ | 587 | /* Issue Input-status command */ |
607 | rio_mport_write_config_32(mport, destid, hopcount, | 588 | rio_write_config_32(rdev, |
608 | rdev->phys_efptr + RIO_PORT_N_MNT_REQ_CSR(pnum), | 589 | rdev->phys_efptr + RIO_PORT_N_MNT_REQ_CSR(pnum), |
609 | RIO_MNT_REQ_CMD_IS); | 590 | RIO_MNT_REQ_CMD_IS); |
610 | 591 | ||
@@ -615,7 +596,7 @@ rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) | |||
615 | checkcount = 3; | 596 | checkcount = 3; |
616 | while (checkcount--) { | 597 | while (checkcount--) { |
617 | udelay(50); | 598 | udelay(50); |
618 | rio_mport_read_config_32(mport, destid, hopcount, | 599 | rio_read_config_32(rdev, |
619 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), | 600 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum), |
620 | ®val); | 601 | ®val); |
621 | if (regval & RIO_PORT_N_MNT_RSP_RVAL) { | 602 | if (regval & RIO_PORT_N_MNT_RSP_RVAL) { |
@@ -635,15 +616,12 @@ rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp) | |||
635 | */ | 616 | */ |
636 | static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) | 617 | static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) |
637 | { | 618 | { |
638 | struct rio_mport *mport = rdev->net->hport; | ||
639 | u16 destid = rdev->rswitch->destid; | ||
640 | u8 hopcount = rdev->rswitch->hopcount; | ||
641 | struct rio_dev *nextdev = rdev->rswitch->nextdev[pnum]; | 619 | struct rio_dev *nextdev = rdev->rswitch->nextdev[pnum]; |
642 | u32 regval; | 620 | u32 regval; |
643 | u32 far_ackid, far_linkstat, near_ackid; | 621 | u32 far_ackid, far_linkstat, near_ackid; |
644 | 622 | ||
645 | if (err_status == 0) | 623 | if (err_status == 0) |
646 | rio_mport_read_config_32(mport, destid, hopcount, | 624 | rio_read_config_32(rdev, |
647 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), | 625 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), |
648 | &err_status); | 626 | &err_status); |
649 | 627 | ||
@@ -661,7 +639,7 @@ static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) | |||
661 | pnum, regval); | 639 | pnum, regval); |
662 | far_ackid = (regval & RIO_PORT_N_MNT_RSP_ASTAT) >> 5; | 640 | far_ackid = (regval & RIO_PORT_N_MNT_RSP_ASTAT) >> 5; |
663 | far_linkstat = regval & RIO_PORT_N_MNT_RSP_LSTAT; | 641 | far_linkstat = regval & RIO_PORT_N_MNT_RSP_LSTAT; |
664 | rio_mport_read_config_32(mport, destid, hopcount, | 642 | rio_read_config_32(rdev, |
665 | rdev->phys_efptr + RIO_PORT_N_ACK_STS_CSR(pnum), | 643 | rdev->phys_efptr + RIO_PORT_N_ACK_STS_CSR(pnum), |
666 | ®val); | 644 | ®val); |
667 | pr_debug("RIO_EM: SP%d_ACK_STS_CSR=0x%08x\n", pnum, regval); | 645 | pr_debug("RIO_EM: SP%d_ACK_STS_CSR=0x%08x\n", pnum, regval); |
@@ -679,9 +657,8 @@ static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) | |||
679 | /* Align near outstanding/outbound ackIDs with | 657 | /* Align near outstanding/outbound ackIDs with |
680 | * far inbound. | 658 | * far inbound. |
681 | */ | 659 | */ |
682 | rio_mport_write_config_32(mport, destid, | 660 | rio_write_config_32(rdev, |
683 | hopcount, rdev->phys_efptr + | 661 | rdev->phys_efptr + RIO_PORT_N_ACK_STS_CSR(pnum), |
684 | RIO_PORT_N_ACK_STS_CSR(pnum), | ||
685 | (near_ackid << 24) | | 662 | (near_ackid << 24) | |
686 | (far_ackid << 8) | far_ackid); | 663 | (far_ackid << 8) | far_ackid); |
687 | /* Align far outstanding/outbound ackIDs with | 664 | /* Align far outstanding/outbound ackIDs with |
@@ -698,7 +675,7 @@ static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status) | |||
698 | pr_debug("RIO_EM: Invalid nextdev pointer (NULL)\n"); | 675 | pr_debug("RIO_EM: Invalid nextdev pointer (NULL)\n"); |
699 | } | 676 | } |
700 | rd_err: | 677 | rd_err: |
701 | rio_mport_read_config_32(mport, destid, hopcount, | 678 | rio_read_config_32(rdev, |
702 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), | 679 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), |
703 | &err_status); | 680 | &err_status); |
704 | pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status); | 681 | pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status); |
@@ -710,7 +687,7 @@ rd_err: | |||
710 | RIO_GET_PORT_NUM(nextdev->swpinfo), NULL); | 687 | RIO_GET_PORT_NUM(nextdev->swpinfo), NULL); |
711 | udelay(50); | 688 | udelay(50); |
712 | 689 | ||
713 | rio_mport_read_config_32(mport, destid, hopcount, | 690 | rio_read_config_32(rdev, |
714 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), | 691 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum), |
715 | &err_status); | 692 | &err_status); |
716 | pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status); | 693 | pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status); |
@@ -730,13 +707,10 @@ rd_err: | |||
730 | int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | 707 | int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) |
731 | { | 708 | { |
732 | struct rio_dev *rdev; | 709 | struct rio_dev *rdev; |
733 | struct rio_mport *mport; | ||
734 | u8 hopcount; | ||
735 | u16 destid; | ||
736 | u32 err_status, em_perrdet, em_ltlerrdet; | 710 | u32 err_status, em_perrdet, em_ltlerrdet; |
737 | int rc, portnum; | 711 | int rc, portnum; |
738 | 712 | ||
739 | rdev = rio_get_comptag(pw_msg->em.comptag, NULL); | 713 | rdev = rio_get_comptag((pw_msg->em.comptag & RIO_CTAG_UDEVID), NULL); |
740 | if (rdev == NULL) { | 714 | if (rdev == NULL) { |
741 | /* Device removed or enumeration error */ | 715 | /* Device removed or enumeration error */ |
742 | pr_debug("RIO: %s No matching device for CTag 0x%08x\n", | 716 | pr_debug("RIO: %s No matching device for CTag 0x%08x\n", |
@@ -800,17 +774,13 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
800 | return 0; | 774 | return 0; |
801 | } | 775 | } |
802 | 776 | ||
803 | mport = rdev->net->hport; | ||
804 | destid = rdev->rswitch->destid; | ||
805 | hopcount = rdev->rswitch->hopcount; | ||
806 | |||
807 | /* | 777 | /* |
808 | * Process the port-write notification from switch | 778 | * Process the port-write notification from switch |
809 | */ | 779 | */ |
810 | if (rdev->rswitch->em_handle) | 780 | if (rdev->rswitch->em_handle) |
811 | rdev->rswitch->em_handle(rdev, portnum); | 781 | rdev->rswitch->em_handle(rdev, portnum); |
812 | 782 | ||
813 | rio_mport_read_config_32(mport, destid, hopcount, | 783 | rio_read_config_32(rdev, |
814 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | 784 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), |
815 | &err_status); | 785 | &err_status); |
816 | pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status); | 786 | pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status); |
@@ -840,7 +810,7 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
840 | rdev->rswitch->port_ok &= ~(1 << portnum); | 810 | rdev->rswitch->port_ok &= ~(1 << portnum); |
841 | rio_set_port_lockout(rdev, portnum, 1); | 811 | rio_set_port_lockout(rdev, portnum, 1); |
842 | 812 | ||
843 | rio_mport_write_config_32(mport, destid, hopcount, | 813 | rio_write_config_32(rdev, |
844 | rdev->phys_efptr + | 814 | rdev->phys_efptr + |
845 | RIO_PORT_N_ACK_STS_CSR(portnum), | 815 | RIO_PORT_N_ACK_STS_CSR(portnum), |
846 | RIO_PORT_N_ACK_CLEAR); | 816 | RIO_PORT_N_ACK_CLEAR); |
@@ -851,28 +821,28 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
851 | } | 821 | } |
852 | } | 822 | } |
853 | 823 | ||
854 | rio_mport_read_config_32(mport, destid, hopcount, | 824 | rio_read_config_32(rdev, |
855 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); | 825 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); |
856 | if (em_perrdet) { | 826 | if (em_perrdet) { |
857 | pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n", | 827 | pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n", |
858 | portnum, em_perrdet); | 828 | portnum, em_perrdet); |
859 | /* Clear EM Port N Error Detect CSR */ | 829 | /* Clear EM Port N Error Detect CSR */ |
860 | rio_mport_write_config_32(mport, destid, hopcount, | 830 | rio_write_config_32(rdev, |
861 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0); | 831 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0); |
862 | } | 832 | } |
863 | 833 | ||
864 | rio_mport_read_config_32(mport, destid, hopcount, | 834 | rio_read_config_32(rdev, |
865 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); | 835 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); |
866 | if (em_ltlerrdet) { | 836 | if (em_ltlerrdet) { |
867 | pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", | 837 | pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", |
868 | em_ltlerrdet); | 838 | em_ltlerrdet); |
869 | /* Clear EM L/T Layer Error Detect CSR */ | 839 | /* Clear EM L/T Layer Error Detect CSR */ |
870 | rio_mport_write_config_32(mport, destid, hopcount, | 840 | rio_write_config_32(rdev, |
871 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); | 841 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); |
872 | } | 842 | } |
873 | 843 | ||
874 | /* Clear remaining error bits and Port-Write Pending bit */ | 844 | /* Clear remaining error bits and Port-Write Pending bit */ |
875 | rio_mport_write_config_32(mport, destid, hopcount, | 845 | rio_write_config_32(rdev, |
876 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | 846 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), |
877 | err_status); | 847 | err_status); |
878 | 848 | ||
diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c index 0bb871cb5c40..095016a9dec1 100644 --- a/drivers/rapidio/switches/idt_gen2.c +++ b/drivers/rapidio/switches/idt_gen2.c | |||
@@ -209,9 +209,6 @@ idtg2_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
209 | static int | 209 | static int |
210 | idtg2_em_init(struct rio_dev *rdev) | 210 | idtg2_em_init(struct rio_dev *rdev) |
211 | { | 211 | { |
212 | struct rio_mport *mport = rdev->net->hport; | ||
213 | u16 destid = rdev->rswitch->destid; | ||
214 | u8 hopcount = rdev->rswitch->hopcount; | ||
215 | u32 regval; | 212 | u32 regval; |
216 | int i, tmp; | 213 | int i, tmp; |
217 | 214 | ||
@@ -220,29 +217,25 @@ idtg2_em_init(struct rio_dev *rdev) | |||
220 | * All standard EM configuration should be performed at upper level. | 217 | * All standard EM configuration should be performed at upper level. |
221 | */ | 218 | */ |
222 | 219 | ||
223 | pr_debug("RIO: %s [%d:%d]\n", __func__, destid, hopcount); | 220 | pr_debug("RIO: %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount); |
224 | 221 | ||
225 | /* Set Port-Write info CSR: PRIO=3 and CRF=1 */ | 222 | /* Set Port-Write info CSR: PRIO=3 and CRF=1 */ |
226 | rio_mport_write_config_32(mport, destid, hopcount, | 223 | rio_write_config_32(rdev, IDT_PW_INFO_CSR, 0x0000e000); |
227 | IDT_PW_INFO_CSR, 0x0000e000); | ||
228 | 224 | ||
229 | /* | 225 | /* |
230 | * Configure LT LAYER error reporting. | 226 | * Configure LT LAYER error reporting. |
231 | */ | 227 | */ |
232 | 228 | ||
233 | /* Enable standard (RIO.p8) error reporting */ | 229 | /* Enable standard (RIO.p8) error reporting */ |
234 | rio_mport_write_config_32(mport, destid, hopcount, | 230 | rio_write_config_32(rdev, IDT_LT_ERR_REPORT_EN, |
235 | IDT_LT_ERR_REPORT_EN, | ||
236 | REM_LTL_ERR_ILLTRAN | REM_LTL_ERR_UNSOLR | | 231 | REM_LTL_ERR_ILLTRAN | REM_LTL_ERR_UNSOLR | |
237 | REM_LTL_ERR_UNSUPTR); | 232 | REM_LTL_ERR_UNSUPTR); |
238 | 233 | ||
239 | /* Use Port-Writes for LT layer error reporting. | 234 | /* Use Port-Writes for LT layer error reporting. |
240 | * Enable per-port reset | 235 | * Enable per-port reset |
241 | */ | 236 | */ |
242 | rio_mport_read_config_32(mport, destid, hopcount, | 237 | rio_read_config_32(rdev, IDT_DEV_CTRL_1, ®val); |
243 | IDT_DEV_CTRL_1, ®val); | 238 | rio_write_config_32(rdev, IDT_DEV_CTRL_1, |
244 | rio_mport_write_config_32(mport, destid, hopcount, | ||
245 | IDT_DEV_CTRL_1, | ||
246 | regval | IDT_DEV_CTRL_1_GENPW | IDT_DEV_CTRL_1_PRSTBEH); | 239 | regval | IDT_DEV_CTRL_1_GENPW | IDT_DEV_CTRL_1_PRSTBEH); |
247 | 240 | ||
248 | /* | 241 | /* |
@@ -250,45 +243,40 @@ idtg2_em_init(struct rio_dev *rdev) | |||
250 | */ | 243 | */ |
251 | 244 | ||
252 | /* Report all RIO.p8 errors supported by device */ | 245 | /* Report all RIO.p8 errors supported by device */ |
253 | rio_mport_write_config_32(mport, destid, hopcount, | 246 | rio_write_config_32(rdev, IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037); |
254 | IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037); | ||
255 | 247 | ||
256 | /* Configure reporting of implementation specific errors/events */ | 248 | /* Configure reporting of implementation specific errors/events */ |
257 | rio_mport_write_config_32(mport, destid, hopcount, | 249 | rio_write_config_32(rdev, IDT_PORT_ISERR_REPORT_EN_BC, |
258 | IDT_PORT_ISERR_REPORT_EN_BC, IDT_PORT_INIT_TX_ACQUIRED); | 250 | IDT_PORT_INIT_TX_ACQUIRED); |
259 | 251 | ||
260 | /* Use Port-Writes for port error reporting and enable error logging */ | 252 | /* Use Port-Writes for port error reporting and enable error logging */ |
261 | tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo); | 253 | tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo); |
262 | for (i = 0; i < tmp; i++) { | 254 | for (i = 0; i < tmp; i++) { |
263 | rio_mport_read_config_32(mport, destid, hopcount, | 255 | rio_read_config_32(rdev, IDT_PORT_OPS(i), ®val); |
264 | IDT_PORT_OPS(i), ®val); | 256 | rio_write_config_32(rdev, |
265 | rio_mport_write_config_32(mport, destid, hopcount, | ||
266 | IDT_PORT_OPS(i), regval | IDT_PORT_OPS_GENPW | | 257 | IDT_PORT_OPS(i), regval | IDT_PORT_OPS_GENPW | |
267 | IDT_PORT_OPS_PL_ELOG | | 258 | IDT_PORT_OPS_PL_ELOG | |
268 | IDT_PORT_OPS_LL_ELOG | | 259 | IDT_PORT_OPS_LL_ELOG | |
269 | IDT_PORT_OPS_LT_ELOG); | 260 | IDT_PORT_OPS_LT_ELOG); |
270 | } | 261 | } |
271 | /* Overwrite error log if full */ | 262 | /* Overwrite error log if full */ |
272 | rio_mport_write_config_32(mport, destid, hopcount, | 263 | rio_write_config_32(rdev, IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR); |
273 | IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR); | ||
274 | 264 | ||
275 | /* | 265 | /* |
276 | * Configure LANE error reporting. | 266 | * Configure LANE error reporting. |
277 | */ | 267 | */ |
278 | 268 | ||
279 | /* Disable line error reporting */ | 269 | /* Disable line error reporting */ |
280 | rio_mport_write_config_32(mport, destid, hopcount, | 270 | rio_write_config_32(rdev, IDT_LANE_ERR_REPORT_EN_BC, 0); |
281 | IDT_LANE_ERR_REPORT_EN_BC, 0); | ||
282 | 271 | ||
283 | /* Use Port-Writes for lane error reporting (when enabled) | 272 | /* Use Port-Writes for lane error reporting (when enabled) |
284 | * (do per-lane update because lanes may have different configuration) | 273 | * (do per-lane update because lanes may have different configuration) |
285 | */ | 274 | */ |
286 | tmp = (rdev->did == RIO_DID_IDTCPS1848) ? 48 : 16; | 275 | tmp = (rdev->did == RIO_DID_IDTCPS1848) ? 48 : 16; |
287 | for (i = 0; i < tmp; i++) { | 276 | for (i = 0; i < tmp; i++) { |
288 | rio_mport_read_config_32(mport, destid, hopcount, | 277 | rio_read_config_32(rdev, IDT_LANE_CTRL(i), ®val); |
289 | IDT_LANE_CTRL(i), ®val); | 278 | rio_write_config_32(rdev, IDT_LANE_CTRL(i), |
290 | rio_mport_write_config_32(mport, destid, hopcount, | 279 | regval | IDT_LANE_CTRL_GENPW); |
291 | IDT_LANE_CTRL(i), regval | IDT_LANE_CTRL_GENPW); | ||
292 | } | 280 | } |
293 | 281 | ||
294 | /* | 282 | /* |
@@ -296,41 +284,32 @@ idtg2_em_init(struct rio_dev *rdev) | |||
296 | */ | 284 | */ |
297 | 285 | ||
298 | /* Disable JTAG and I2C Error capture */ | 286 | /* Disable JTAG and I2C Error capture */ |
299 | rio_mport_write_config_32(mport, destid, hopcount, | 287 | rio_write_config_32(rdev, IDT_AUX_PORT_ERR_CAP_EN, 0); |
300 | IDT_AUX_PORT_ERR_CAP_EN, 0); | ||
301 | 288 | ||
302 | /* Disable JTAG and I2C Error reporting/logging */ | 289 | /* Disable JTAG and I2C Error reporting/logging */ |
303 | rio_mport_write_config_32(mport, destid, hopcount, | 290 | rio_write_config_32(rdev, IDT_AUX_ERR_REPORT_EN, 0); |
304 | IDT_AUX_ERR_REPORT_EN, 0); | ||
305 | 291 | ||
306 | /* Disable Port-Write notification from JTAG */ | 292 | /* Disable Port-Write notification from JTAG */ |
307 | rio_mport_write_config_32(mport, destid, hopcount, | 293 | rio_write_config_32(rdev, IDT_JTAG_CTRL, 0); |
308 | IDT_JTAG_CTRL, 0); | ||
309 | 294 | ||
310 | /* Disable Port-Write notification from I2C */ | 295 | /* Disable Port-Write notification from I2C */ |
311 | rio_mport_read_config_32(mport, destid, hopcount, | 296 | rio_read_config_32(rdev, IDT_I2C_MCTRL, ®val); |
312 | IDT_I2C_MCTRL, ®val); | 297 | rio_write_config_32(rdev, IDT_I2C_MCTRL, regval & ~IDT_I2C_MCTRL_GENPW); |
313 | rio_mport_write_config_32(mport, destid, hopcount, | ||
314 | IDT_I2C_MCTRL, | ||
315 | regval & ~IDT_I2C_MCTRL_GENPW); | ||
316 | 298 | ||
317 | /* | 299 | /* |
318 | * Configure CFG_BLK error reporting. | 300 | * Configure CFG_BLK error reporting. |
319 | */ | 301 | */ |
320 | 302 | ||
321 | /* Disable Configuration Block error capture */ | 303 | /* Disable Configuration Block error capture */ |
322 | rio_mport_write_config_32(mport, destid, hopcount, | 304 | rio_write_config_32(rdev, IDT_CFGBLK_ERR_CAPTURE_EN, 0); |
323 | IDT_CFGBLK_ERR_CAPTURE_EN, 0); | ||
324 | 305 | ||
325 | /* Disable Port-Writes for Configuration Block error reporting */ | 306 | /* Disable Port-Writes for Configuration Block error reporting */ |
326 | rio_mport_read_config_32(mport, destid, hopcount, | 307 | rio_read_config_32(rdev, IDT_CFGBLK_ERR_REPORT, ®val); |
327 | IDT_CFGBLK_ERR_REPORT, ®val); | 308 | rio_write_config_32(rdev, IDT_CFGBLK_ERR_REPORT, |
328 | rio_mport_write_config_32(mport, destid, hopcount, | 309 | regval & ~IDT_CFGBLK_ERR_REPORT_GENPW); |
329 | IDT_CFGBLK_ERR_REPORT, | ||
330 | regval & ~IDT_CFGBLK_ERR_REPORT_GENPW); | ||
331 | 310 | ||
332 | /* set TVAL = ~50us */ | 311 | /* set TVAL = ~50us */ |
333 | rio_mport_write_config_32(mport, destid, hopcount, | 312 | rio_write_config_32(rdev, |
334 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); | 313 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); |
335 | 314 | ||
336 | return 0; | 315 | return 0; |
@@ -339,18 +318,15 @@ idtg2_em_init(struct rio_dev *rdev) | |||
339 | static int | 318 | static int |
340 | idtg2_em_handler(struct rio_dev *rdev, u8 portnum) | 319 | idtg2_em_handler(struct rio_dev *rdev, u8 portnum) |
341 | { | 320 | { |
342 | struct rio_mport *mport = rdev->net->hport; | ||
343 | u16 destid = rdev->rswitch->destid; | ||
344 | u8 hopcount = rdev->rswitch->hopcount; | ||
345 | u32 regval, em_perrdet, em_ltlerrdet; | 321 | u32 regval, em_perrdet, em_ltlerrdet; |
346 | 322 | ||
347 | rio_mport_read_config_32(mport, destid, hopcount, | 323 | rio_read_config_32(rdev, |
348 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); | 324 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); |
349 | if (em_ltlerrdet) { | 325 | if (em_ltlerrdet) { |
350 | /* Service Logical/Transport Layer Error(s) */ | 326 | /* Service Logical/Transport Layer Error(s) */ |
351 | if (em_ltlerrdet & REM_LTL_ERR_IMPSPEC) { | 327 | if (em_ltlerrdet & REM_LTL_ERR_IMPSPEC) { |
352 | /* Implementation specific error reported */ | 328 | /* Implementation specific error reported */ |
353 | rio_mport_read_config_32(mport, destid, hopcount, | 329 | rio_read_config_32(rdev, |
354 | IDT_ISLTL_ADDRESS_CAP, ®val); | 330 | IDT_ISLTL_ADDRESS_CAP, ®val); |
355 | 331 | ||
356 | pr_debug("RIO: %s Implementation Specific LTL errors" \ | 332 | pr_debug("RIO: %s Implementation Specific LTL errors" \ |
@@ -358,13 +334,12 @@ idtg2_em_handler(struct rio_dev *rdev, u8 portnum) | |||
358 | rio_name(rdev), em_ltlerrdet, regval); | 334 | rio_name(rdev), em_ltlerrdet, regval); |
359 | 335 | ||
360 | /* Clear implementation specific address capture CSR */ | 336 | /* Clear implementation specific address capture CSR */ |
361 | rio_mport_write_config_32(mport, destid, hopcount, | 337 | rio_write_config_32(rdev, IDT_ISLTL_ADDRESS_CAP, 0); |
362 | IDT_ISLTL_ADDRESS_CAP, 0); | ||
363 | 338 | ||
364 | } | 339 | } |
365 | } | 340 | } |
366 | 341 | ||
367 | rio_mport_read_config_32(mport, destid, hopcount, | 342 | rio_read_config_32(rdev, |
368 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); | 343 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); |
369 | if (em_perrdet) { | 344 | if (em_perrdet) { |
370 | /* Service Port-Level Error(s) */ | 345 | /* Service Port-Level Error(s) */ |
@@ -372,14 +347,14 @@ idtg2_em_handler(struct rio_dev *rdev, u8 portnum) | |||
372 | /* Implementation Specific port error reported */ | 347 | /* Implementation Specific port error reported */ |
373 | 348 | ||
374 | /* Get IS errors reported */ | 349 | /* Get IS errors reported */ |
375 | rio_mport_read_config_32(mport, destid, hopcount, | 350 | rio_read_config_32(rdev, |
376 | IDT_PORT_ISERR_DET(portnum), ®val); | 351 | IDT_PORT_ISERR_DET(portnum), ®val); |
377 | 352 | ||
378 | pr_debug("RIO: %s Implementation Specific Port" \ | 353 | pr_debug("RIO: %s Implementation Specific Port" \ |
379 | " errors 0x%x\n", rio_name(rdev), regval); | 354 | " errors 0x%x\n", rio_name(rdev), regval); |
380 | 355 | ||
381 | /* Clear all implementation specific events */ | 356 | /* Clear all implementation specific events */ |
382 | rio_mport_write_config_32(mport, destid, hopcount, | 357 | rio_write_config_32(rdev, |
383 | IDT_PORT_ISERR_DET(portnum), 0); | 358 | IDT_PORT_ISERR_DET(portnum), 0); |
384 | } | 359 | } |
385 | } | 360 | } |
@@ -391,14 +366,10 @@ static ssize_t | |||
391 | idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf) | 366 | idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf) |
392 | { | 367 | { |
393 | struct rio_dev *rdev = to_rio_dev(dev); | 368 | struct rio_dev *rdev = to_rio_dev(dev); |
394 | struct rio_mport *mport = rdev->net->hport; | ||
395 | u16 destid = rdev->rswitch->destid; | ||
396 | u8 hopcount = rdev->rswitch->hopcount; | ||
397 | ssize_t len = 0; | 369 | ssize_t len = 0; |
398 | u32 regval; | 370 | u32 regval; |
399 | 371 | ||
400 | while (!rio_mport_read_config_32(mport, destid, hopcount, | 372 | while (!rio_read_config_32(rdev, IDT_ERR_RD, ®val)) { |
401 | IDT_ERR_RD, ®val)) { | ||
402 | if (!regval) /* 0 = end of log */ | 373 | if (!regval) /* 0 = end of log */ |
403 | break; | 374 | break; |
404 | len += snprintf(buf + len, PAGE_SIZE - len, | 375 | len += snprintf(buf + len, PAGE_SIZE - len, |
@@ -445,3 +416,5 @@ static int idtg2_switch_init(struct rio_dev *rdev, int do_enum) | |||
445 | 416 | ||
446 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); | 417 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); |
447 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); | 418 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); |
419 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTVPS1616, idtg2_switch_init); | ||
420 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTSPS1616, idtg2_switch_init); | ||
diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c index fc9f6374f759..3a971077e7bf 100644 --- a/drivers/rapidio/switches/idtcps.c +++ b/drivers/rapidio/switches/idtcps.c | |||
@@ -117,10 +117,6 @@ idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
117 | 117 | ||
118 | static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) | 118 | static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) |
119 | { | 119 | { |
120 | struct rio_mport *mport = rdev->net->hport; | ||
121 | u16 destid = rdev->rswitch->destid; | ||
122 | u8 hopcount = rdev->rswitch->hopcount; | ||
123 | |||
124 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | 120 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); |
125 | rdev->rswitch->add_entry = idtcps_route_add_entry; | 121 | rdev->rswitch->add_entry = idtcps_route_add_entry; |
126 | rdev->rswitch->get_entry = idtcps_route_get_entry; | 122 | rdev->rswitch->get_entry = idtcps_route_get_entry; |
@@ -132,7 +128,7 @@ static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) | |||
132 | 128 | ||
133 | if (do_enum) { | 129 | if (do_enum) { |
134 | /* set TVAL = ~50us */ | 130 | /* set TVAL = ~50us */ |
135 | rio_mport_write_config_32(mport, destid, hopcount, | 131 | rio_write_config_32(rdev, |
136 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); | 132 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); |
137 | } | 133 | } |
138 | 134 | ||
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c index b9a389b9f812..3994c00aa01f 100644 --- a/drivers/rapidio/switches/tsi568.c +++ b/drivers/rapidio/switches/tsi568.c | |||
@@ -113,22 +113,17 @@ tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
113 | static int | 113 | static int |
114 | tsi568_em_init(struct rio_dev *rdev) | 114 | tsi568_em_init(struct rio_dev *rdev) |
115 | { | 115 | { |
116 | struct rio_mport *mport = rdev->net->hport; | ||
117 | u16 destid = rdev->rswitch->destid; | ||
118 | u8 hopcount = rdev->rswitch->hopcount; | ||
119 | u32 regval; | 116 | u32 regval; |
120 | int portnum; | 117 | int portnum; |
121 | 118 | ||
122 | pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount); | 119 | pr_debug("TSI568 %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount); |
123 | 120 | ||
124 | /* Make sure that Port-Writes are disabled (for all ports) */ | 121 | /* Make sure that Port-Writes are disabled (for all ports) */ |
125 | for (portnum = 0; | 122 | for (portnum = 0; |
126 | portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { | 123 | portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { |
127 | rio_mport_read_config_32(mport, destid, hopcount, | 124 | rio_read_config_32(rdev, TSI568_SP_MODE(portnum), ®val); |
128 | TSI568_SP_MODE(portnum), ®val); | 125 | rio_write_config_32(rdev, TSI568_SP_MODE(portnum), |
129 | rio_mport_write_config_32(mport, destid, hopcount, | 126 | regval | TSI568_SP_MODE_PW_DIS); |
130 | TSI568_SP_MODE(portnum), | ||
131 | regval | TSI568_SP_MODE_PW_DIS); | ||
132 | } | 127 | } |
133 | 128 | ||
134 | return 0; | 129 | return 0; |
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c index 2003fb63c404..1a62934bfebc 100644 --- a/drivers/rapidio/switches/tsi57x.c +++ b/drivers/rapidio/switches/tsi57x.c | |||
@@ -158,48 +158,45 @@ tsi57x_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
158 | static int | 158 | static int |
159 | tsi57x_em_init(struct rio_dev *rdev) | 159 | tsi57x_em_init(struct rio_dev *rdev) |
160 | { | 160 | { |
161 | struct rio_mport *mport = rdev->net->hport; | ||
162 | u16 destid = rdev->rswitch->destid; | ||
163 | u8 hopcount = rdev->rswitch->hopcount; | ||
164 | u32 regval; | 161 | u32 regval; |
165 | int portnum; | 162 | int portnum; |
166 | 163 | ||
167 | pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount); | 164 | pr_debug("TSI578 %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount); |
168 | 165 | ||
169 | for (portnum = 0; | 166 | for (portnum = 0; |
170 | portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { | 167 | portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) { |
171 | /* Make sure that Port-Writes are enabled (for all ports) */ | 168 | /* Make sure that Port-Writes are enabled (for all ports) */ |
172 | rio_mport_read_config_32(mport, destid, hopcount, | 169 | rio_read_config_32(rdev, |
173 | TSI578_SP_MODE(portnum), ®val); | 170 | TSI578_SP_MODE(portnum), ®val); |
174 | rio_mport_write_config_32(mport, destid, hopcount, | 171 | rio_write_config_32(rdev, |
175 | TSI578_SP_MODE(portnum), | 172 | TSI578_SP_MODE(portnum), |
176 | regval & ~TSI578_SP_MODE_PW_DIS); | 173 | regval & ~TSI578_SP_MODE_PW_DIS); |
177 | 174 | ||
178 | /* Clear all pending interrupts */ | 175 | /* Clear all pending interrupts */ |
179 | rio_mport_read_config_32(mport, destid, hopcount, | 176 | rio_read_config_32(rdev, |
180 | rdev->phys_efptr + | 177 | rdev->phys_efptr + |
181 | RIO_PORT_N_ERR_STS_CSR(portnum), | 178 | RIO_PORT_N_ERR_STS_CSR(portnum), |
182 | ®val); | 179 | ®val); |
183 | rio_mport_write_config_32(mport, destid, hopcount, | 180 | rio_write_config_32(rdev, |
184 | rdev->phys_efptr + | 181 | rdev->phys_efptr + |
185 | RIO_PORT_N_ERR_STS_CSR(portnum), | 182 | RIO_PORT_N_ERR_STS_CSR(portnum), |
186 | regval & 0x07120214); | 183 | regval & 0x07120214); |
187 | 184 | ||
188 | rio_mport_read_config_32(mport, destid, hopcount, | 185 | rio_read_config_32(rdev, |
189 | TSI578_SP_INT_STATUS(portnum), ®val); | 186 | TSI578_SP_INT_STATUS(portnum), ®val); |
190 | rio_mport_write_config_32(mport, destid, hopcount, | 187 | rio_write_config_32(rdev, |
191 | TSI578_SP_INT_STATUS(portnum), | 188 | TSI578_SP_INT_STATUS(portnum), |
192 | regval & 0x000700bd); | 189 | regval & 0x000700bd); |
193 | 190 | ||
194 | /* Enable all interrupts to allow ports to send a port-write */ | 191 | /* Enable all interrupts to allow ports to send a port-write */ |
195 | rio_mport_read_config_32(mport, destid, hopcount, | 192 | rio_read_config_32(rdev, |
196 | TSI578_SP_CTL_INDEP(portnum), ®val); | 193 | TSI578_SP_CTL_INDEP(portnum), ®val); |
197 | rio_mport_write_config_32(mport, destid, hopcount, | 194 | rio_write_config_32(rdev, |
198 | TSI578_SP_CTL_INDEP(portnum), | 195 | TSI578_SP_CTL_INDEP(portnum), |
199 | regval | 0x000b0000); | 196 | regval | 0x000b0000); |
200 | 197 | ||
201 | /* Skip next (odd) port if the current port is in x4 mode */ | 198 | /* Skip next (odd) port if the current port is in x4 mode */ |
202 | rio_mport_read_config_32(mport, destid, hopcount, | 199 | rio_read_config_32(rdev, |
203 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | 200 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), |
204 | ®val); | 201 | ®val); |
205 | if ((regval & RIO_PORT_N_CTL_PWIDTH) == RIO_PORT_N_CTL_PWIDTH_4) | 202 | if ((regval & RIO_PORT_N_CTL_PWIDTH) == RIO_PORT_N_CTL_PWIDTH_4) |
@@ -207,7 +204,7 @@ tsi57x_em_init(struct rio_dev *rdev) | |||
207 | } | 204 | } |
208 | 205 | ||
209 | /* set TVAL = ~50us */ | 206 | /* set TVAL = ~50us */ |
210 | rio_mport_write_config_32(mport, destid, hopcount, | 207 | rio_write_config_32(rdev, |
211 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x9a << 8); | 208 | rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x9a << 8); |
212 | 209 | ||
213 | return 0; | 210 | return 0; |
@@ -217,14 +214,12 @@ static int | |||
217 | tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) | 214 | tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) |
218 | { | 215 | { |
219 | struct rio_mport *mport = rdev->net->hport; | 216 | struct rio_mport *mport = rdev->net->hport; |
220 | u16 destid = rdev->rswitch->destid; | ||
221 | u8 hopcount = rdev->rswitch->hopcount; | ||
222 | u32 intstat, err_status; | 217 | u32 intstat, err_status; |
223 | int sendcount, checkcount; | 218 | int sendcount, checkcount; |
224 | u8 route_port; | 219 | u8 route_port; |
225 | u32 regval; | 220 | u32 regval; |
226 | 221 | ||
227 | rio_mport_read_config_32(mport, destid, hopcount, | 222 | rio_read_config_32(rdev, |
228 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | 223 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), |
229 | &err_status); | 224 | &err_status); |
230 | 225 | ||
@@ -232,15 +227,15 @@ tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) | |||
232 | (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES | | 227 | (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES | |
233 | RIO_PORT_N_ERR_STS_PW_INP_ES))) { | 228 | RIO_PORT_N_ERR_STS_PW_INP_ES))) { |
234 | /* Remove any queued packets by locking/unlocking port */ | 229 | /* Remove any queued packets by locking/unlocking port */ |
235 | rio_mport_read_config_32(mport, destid, hopcount, | 230 | rio_read_config_32(rdev, |
236 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | 231 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), |
237 | ®val); | 232 | ®val); |
238 | if (!(regval & RIO_PORT_N_CTL_LOCKOUT)) { | 233 | if (!(regval & RIO_PORT_N_CTL_LOCKOUT)) { |
239 | rio_mport_write_config_32(mport, destid, hopcount, | 234 | rio_write_config_32(rdev, |
240 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | 235 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), |
241 | regval | RIO_PORT_N_CTL_LOCKOUT); | 236 | regval | RIO_PORT_N_CTL_LOCKOUT); |
242 | udelay(50); | 237 | udelay(50); |
243 | rio_mport_write_config_32(mport, destid, hopcount, | 238 | rio_write_config_32(rdev, |
244 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | 239 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), |
245 | regval); | 240 | regval); |
246 | } | 241 | } |
@@ -248,7 +243,7 @@ tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) | |||
248 | /* Read from link maintenance response register to clear | 243 | /* Read from link maintenance response register to clear |
249 | * valid bit | 244 | * valid bit |
250 | */ | 245 | */ |
251 | rio_mport_read_config_32(mport, destid, hopcount, | 246 | rio_read_config_32(rdev, |
252 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(portnum), | 247 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(portnum), |
253 | ®val); | 248 | ®val); |
254 | 249 | ||
@@ -257,13 +252,12 @@ tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) | |||
257 | */ | 252 | */ |
258 | sendcount = 3; | 253 | sendcount = 3; |
259 | while (sendcount) { | 254 | while (sendcount) { |
260 | rio_mport_write_config_32(mport, destid, hopcount, | 255 | rio_write_config_32(rdev, |
261 | TSI578_SP_CS_TX(portnum), 0x40fc8000); | 256 | TSI578_SP_CS_TX(portnum), 0x40fc8000); |
262 | checkcount = 3; | 257 | checkcount = 3; |
263 | while (checkcount--) { | 258 | while (checkcount--) { |
264 | udelay(50); | 259 | udelay(50); |
265 | rio_mport_read_config_32( | 260 | rio_read_config_32(rdev, |
266 | mport, destid, hopcount, | ||
267 | rdev->phys_efptr + | 261 | rdev->phys_efptr + |
268 | RIO_PORT_N_MNT_RSP_CSR(portnum), | 262 | RIO_PORT_N_MNT_RSP_CSR(portnum), |
269 | ®val); | 263 | ®val); |
@@ -277,25 +271,23 @@ tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) | |||
277 | 271 | ||
278 | exit_es: | 272 | exit_es: |
279 | /* Clear implementation specific error status bits */ | 273 | /* Clear implementation specific error status bits */ |
280 | rio_mport_read_config_32(mport, destid, hopcount, | 274 | rio_read_config_32(rdev, TSI578_SP_INT_STATUS(portnum), &intstat); |
281 | TSI578_SP_INT_STATUS(portnum), &intstat); | ||
282 | pr_debug("TSI578[%x:%x] SP%d_INT_STATUS=0x%08x\n", | 275 | pr_debug("TSI578[%x:%x] SP%d_INT_STATUS=0x%08x\n", |
283 | destid, hopcount, portnum, intstat); | 276 | rdev->destid, rdev->hopcount, portnum, intstat); |
284 | 277 | ||
285 | if (intstat & 0x10000) { | 278 | if (intstat & 0x10000) { |
286 | rio_mport_read_config_32(mport, destid, hopcount, | 279 | rio_read_config_32(rdev, |
287 | TSI578_SP_LUT_PEINF(portnum), ®val); | 280 | TSI578_SP_LUT_PEINF(portnum), ®val); |
288 | regval = (mport->sys_size) ? (regval >> 16) : (regval >> 24); | 281 | regval = (mport->sys_size) ? (regval >> 16) : (regval >> 24); |
289 | route_port = rdev->rswitch->route_table[regval]; | 282 | route_port = rdev->rswitch->route_table[regval]; |
290 | pr_debug("RIO: TSI578[%s] P%d LUT Parity Error (destID=%d)\n", | 283 | pr_debug("RIO: TSI578[%s] P%d LUT Parity Error (destID=%d)\n", |
291 | rio_name(rdev), portnum, regval); | 284 | rio_name(rdev), portnum, regval); |
292 | tsi57x_route_add_entry(mport, destid, hopcount, | 285 | tsi57x_route_add_entry(mport, rdev->destid, rdev->hopcount, |
293 | RIO_GLOBAL_TABLE, regval, route_port); | 286 | RIO_GLOBAL_TABLE, regval, route_port); |
294 | } | 287 | } |
295 | 288 | ||
296 | rio_mport_write_config_32(mport, destid, hopcount, | 289 | rio_write_config_32(rdev, TSI578_SP_INT_STATUS(portnum), |
297 | TSI578_SP_INT_STATUS(portnum), | 290 | intstat & 0x000700bd); |
298 | intstat & 0x000700bd); | ||
299 | 291 | ||
300 | return 0; | 292 | return 0; |
301 | } | 293 | } |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 2ce2eb71d0f5..dd6308499bd4 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
@@ -249,7 +249,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
249 | } | 249 | } |
250 | 250 | ||
251 | static int pm8607_set_voltage(struct regulator_dev *rdev, | 251 | static int pm8607_set_voltage(struct regulator_dev *rdev, |
252 | int min_uV, int max_uV) | 252 | int min_uV, int max_uV, unsigned *selector) |
253 | { | 253 | { |
254 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | 254 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); |
255 | uint8_t val, mask; | 255 | uint8_t val, mask; |
@@ -263,6 +263,7 @@ static int pm8607_set_voltage(struct regulator_dev *rdev, | |||
263 | ret = choose_voltage(rdev, min_uV, max_uV); | 263 | ret = choose_voltage(rdev, min_uV, max_uV); |
264 | if (ret < 0) | 264 | if (ret < 0) |
265 | return -EINVAL; | 265 | return -EINVAL; |
266 | *selector = ret; | ||
266 | val = (uint8_t)(ret << info->vol_shift); | 267 | val = (uint8_t)(ret << info->vol_shift); |
267 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 268 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
268 | 269 | ||
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index dd30e883d4a7..e1d943619ab8 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -186,13 +186,25 @@ config REGULATOR_PCAP | |||
186 | This driver provides support for the voltage regulators of the | 186 | This driver provides support for the voltage regulators of the |
187 | PCAP2 PMIC. | 187 | PCAP2 PMIC. |
188 | 188 | ||
189 | config REGULATOR_MC13XXX_CORE | ||
190 | tristate | ||
191 | |||
189 | config REGULATOR_MC13783 | 192 | config REGULATOR_MC13783 |
190 | tristate "Support regulators on Freescale MC13783 PMIC" | 193 | tristate "Support regulators on Freescale MC13783 PMIC" |
191 | depends on MFD_MC13783 | 194 | depends on MFD_MC13783 |
195 | select REGULATOR_MC13XXX_CORE | ||
192 | help | 196 | help |
193 | Say y here to support the regulators found on the Freescale MC13783 | 197 | Say y here to support the regulators found on the Freescale MC13783 |
194 | PMIC. | 198 | PMIC. |
195 | 199 | ||
200 | config REGULATOR_MC13892 | ||
201 | tristate "Support regulators on Freescale MC13892 PMIC" | ||
202 | depends on MFD_MC13XXX | ||
203 | select REGULATOR_MC13XXX_CORE | ||
204 | help | ||
205 | Say y here to support the regulators found on the Freescale MC13892 | ||
206 | PMIC. | ||
207 | |||
196 | config REGULATOR_AB3100 | 208 | config REGULATOR_AB3100 |
197 | tristate "ST-Ericsson AB3100 Regulator functions" | 209 | tristate "ST-Ericsson AB3100 Regulator functions" |
198 | depends on AB3100_CORE | 210 | depends on AB3100_CORE |
@@ -250,5 +262,15 @@ config REGULATOR_TPS6586X | |||
250 | help | 262 | help |
251 | This driver supports TPS6586X voltage regulator chips. | 263 | This driver supports TPS6586X voltage regulator chips. |
252 | 264 | ||
265 | config REGULATOR_TPS6524X | ||
266 | tristate "TI TPS6524X Power regulators" | ||
267 | depends on SPI | ||
268 | help | ||
269 | This driver supports TPS6524X voltage regulator chips. TPS6524X | ||
270 | provides three step-down converters and two general-purpose LDO | ||
271 | voltage regulators. This device is interfaced using a customized | ||
272 | serial interface currently supported on the sequencer serial | ||
273 | port controller. | ||
274 | |||
253 | endif | 275 | endif |
254 | 276 | ||
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index bff815736780..0b5e88c2b8d7 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -30,10 +30,13 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o | |||
30 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o | 30 | obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o |
31 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 31 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
32 | obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o | 32 | obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o |
33 | obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o | ||
34 | obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o | ||
33 | obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o | 35 | obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o |
34 | 36 | ||
35 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o | 37 | obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o |
36 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o | 38 | obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o |
39 | obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o | ||
37 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o | 40 | obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o |
38 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | 41 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o |
39 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o | 42 | obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o |
diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index b349266a43de..ed6feaf9398d 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
@@ -362,7 +362,8 @@ static int ab3100_get_best_voltage_index(struct regulator_dev *reg, | |||
362 | } | 362 | } |
363 | 363 | ||
364 | static int ab3100_set_voltage_regulator(struct regulator_dev *reg, | 364 | static int ab3100_set_voltage_regulator(struct regulator_dev *reg, |
365 | int min_uV, int max_uV) | 365 | int min_uV, int max_uV, |
366 | unsigned *selector) | ||
366 | { | 367 | { |
367 | struct ab3100_regulator *abreg = reg->reg_data; | 368 | struct ab3100_regulator *abreg = reg->reg_data; |
368 | u8 regval; | 369 | u8 regval; |
@@ -373,6 +374,8 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg, | |||
373 | if (bestindex < 0) | 374 | if (bestindex < 0) |
374 | return bestindex; | 375 | return bestindex; |
375 | 376 | ||
377 | *selector = bestindex; | ||
378 | |||
376 | err = abx500_get_register_interruptible(abreg->dev, 0, | 379 | err = abx500_get_register_interruptible(abreg->dev, 0, |
377 | abreg->regreg, ®val); | 380 | abreg->regreg, ®val); |
378 | if (err) { | 381 | if (err) { |
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index db6b70f20511..d9a052c53aec 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c | |||
@@ -3,18 +3,13 @@ | |||
3 | * | 3 | * |
4 | * License Terms: GNU General Public License v2 | 4 | * License Terms: GNU General Public License v2 |
5 | * | 5 | * |
6 | * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson | 6 | * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson |
7 | * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson | ||
7 | * | 8 | * |
8 | * AB8500 peripheral regulators | 9 | * AB8500 peripheral regulators |
9 | * | 10 | * |
10 | * AB8500 supports the following regulators, | 11 | * AB8500 supports the following regulators: |
11 | * LDOs - VAUDIO, VANAMIC2/2, VDIGMIC, VINTCORE12, VTVOUT, | 12 | * VAUX1/2/3, VINTCORE, VTVOUT, VAUDIO, VAMIC1/2, VDMIC, VANA |
12 | * VAUX1/2/3, VANA | ||
13 | * | ||
14 | * for DB8500 cut 1.0 and previous versions of the silicon, all accesses | ||
15 | * to registers are through the DB8500 SPI. In cut 1.1 onwards, these | ||
16 | * accesses are through the DB8500 PRCMU I2C | ||
17 | * | ||
18 | */ | 13 | */ |
19 | #include <linux/init.h> | 14 | #include <linux/init.h> |
20 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
@@ -28,38 +23,37 @@ | |||
28 | 23 | ||
29 | /** | 24 | /** |
30 | * struct ab8500_regulator_info - ab8500 regulator information | 25 | * struct ab8500_regulator_info - ab8500 regulator information |
26 | * @dev: device pointer | ||
31 | * @desc: regulator description | 27 | * @desc: regulator description |
32 | * @ab8500: ab8500 parent | ||
33 | * @regulator_dev: regulator device | 28 | * @regulator_dev: regulator device |
34 | * @max_uV: maximum voltage (for variable voltage supplies) | 29 | * @max_uV: maximum voltage (for variable voltage supplies) |
35 | * @min_uV: minimum voltage (for variable voltage supplies) | 30 | * @min_uV: minimum voltage (for variable voltage supplies) |
36 | * @fixed_uV: typical voltage (for fixed voltage supplies) | 31 | * @fixed_uV: typical voltage (for fixed voltage supplies) |
37 | * @update_bank: bank to control on/off | 32 | * @update_bank: bank to control on/off |
38 | * @update_reg: register to control on/off | 33 | * @update_reg: register to control on/off |
39 | * @mask: mask to enable/disable regulator | 34 | * @update_mask: mask to enable/disable regulator |
40 | * @enable: bits to enable the regulator in normal(high power) mode | 35 | * @update_val_enable: bits to enable the regulator in normal (high power) mode |
41 | * @voltage_bank: bank to control regulator voltage | 36 | * @voltage_bank: bank to control regulator voltage |
42 | * @voltage_reg: register to control regulator voltage | 37 | * @voltage_reg: register to control regulator voltage |
43 | * @voltage_mask: mask to control regulator voltage | 38 | * @voltage_mask: mask to control regulator voltage |
44 | * @supported_voltages: supported voltage table | 39 | * @voltages: supported voltage table |
45 | * @voltages_len: number of supported voltages for the regulator | 40 | * @voltages_len: number of supported voltages for the regulator |
46 | */ | 41 | */ |
47 | struct ab8500_regulator_info { | 42 | struct ab8500_regulator_info { |
48 | struct device *dev; | 43 | struct device *dev; |
49 | struct regulator_desc desc; | 44 | struct regulator_desc desc; |
50 | struct ab8500 *ab8500; | ||
51 | struct regulator_dev *regulator; | 45 | struct regulator_dev *regulator; |
52 | int max_uV; | 46 | int max_uV; |
53 | int min_uV; | 47 | int min_uV; |
54 | int fixed_uV; | 48 | int fixed_uV; |
55 | u8 update_bank; | 49 | u8 update_bank; |
56 | u8 update_reg; | 50 | u8 update_reg; |
57 | u8 mask; | 51 | u8 update_mask; |
58 | u8 enable; | 52 | u8 update_val_enable; |
59 | u8 voltage_bank; | 53 | u8 voltage_bank; |
60 | u8 voltage_reg; | 54 | u8 voltage_reg; |
61 | u8 voltage_mask; | 55 | u8 voltage_mask; |
62 | int const *supported_voltages; | 56 | int const *voltages; |
63 | int voltages_len; | 57 | int voltages_len; |
64 | }; | 58 | }; |
65 | 59 | ||
@@ -83,6 +77,17 @@ static const int ldo_vauxn_voltages[] = { | |||
83 | 3300000, | 77 | 3300000, |
84 | }; | 78 | }; |
85 | 79 | ||
80 | static const int ldo_vaux3_voltages[] = { | ||
81 | 1200000, | ||
82 | 1500000, | ||
83 | 1800000, | ||
84 | 2100000, | ||
85 | 2500000, | ||
86 | 2750000, | ||
87 | 2790000, | ||
88 | 2910000, | ||
89 | }; | ||
90 | |||
86 | static const int ldo_vintcore_voltages[] = { | 91 | static const int ldo_vintcore_voltages[] = { |
87 | 1200000, | 92 | 1200000, |
88 | 1225000, | 93 | 1225000, |
@@ -95,57 +100,80 @@ static const int ldo_vintcore_voltages[] = { | |||
95 | 100 | ||
96 | static int ab8500_regulator_enable(struct regulator_dev *rdev) | 101 | static int ab8500_regulator_enable(struct regulator_dev *rdev) |
97 | { | 102 | { |
98 | int regulator_id, ret; | 103 | int ret; |
99 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 104 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
100 | 105 | ||
101 | regulator_id = rdev_get_id(rdev); | 106 | if (info == NULL) { |
102 | if (regulator_id >= AB8500_NUM_REGULATORS) | 107 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
103 | return -EINVAL; | 108 | return -EINVAL; |
109 | } | ||
104 | 110 | ||
105 | ret = abx500_mask_and_set_register_interruptible(info->dev, | 111 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
106 | info->update_bank, info->update_reg, info->mask, info->enable); | 112 | info->update_bank, info->update_reg, |
113 | info->update_mask, info->update_val_enable); | ||
107 | if (ret < 0) | 114 | if (ret < 0) |
108 | dev_err(rdev_get_dev(rdev), | 115 | dev_err(rdev_get_dev(rdev), |
109 | "couldn't set enable bits for regulator\n"); | 116 | "couldn't set enable bits for regulator\n"); |
117 | |||
118 | dev_vdbg(rdev_get_dev(rdev), | ||
119 | "%s-enable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", | ||
120 | info->desc.name, info->update_bank, info->update_reg, | ||
121 | info->update_mask, info->update_val_enable); | ||
122 | |||
110 | return ret; | 123 | return ret; |
111 | } | 124 | } |
112 | 125 | ||
113 | static int ab8500_regulator_disable(struct regulator_dev *rdev) | 126 | static int ab8500_regulator_disable(struct regulator_dev *rdev) |
114 | { | 127 | { |
115 | int regulator_id, ret; | 128 | int ret; |
116 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 129 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
117 | 130 | ||
118 | regulator_id = rdev_get_id(rdev); | 131 | if (info == NULL) { |
119 | if (regulator_id >= AB8500_NUM_REGULATORS) | 132 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
120 | return -EINVAL; | 133 | return -EINVAL; |
134 | } | ||
121 | 135 | ||
122 | ret = abx500_mask_and_set_register_interruptible(info->dev, | 136 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
123 | info->update_bank, info->update_reg, info->mask, 0x0); | 137 | info->update_bank, info->update_reg, |
138 | info->update_mask, 0x0); | ||
124 | if (ret < 0) | 139 | if (ret < 0) |
125 | dev_err(rdev_get_dev(rdev), | 140 | dev_err(rdev_get_dev(rdev), |
126 | "couldn't set disable bits for regulator\n"); | 141 | "couldn't set disable bits for regulator\n"); |
142 | |||
143 | dev_vdbg(rdev_get_dev(rdev), | ||
144 | "%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", | ||
145 | info->desc.name, info->update_bank, info->update_reg, | ||
146 | info->update_mask, 0x0); | ||
147 | |||
127 | return ret; | 148 | return ret; |
128 | } | 149 | } |
129 | 150 | ||
130 | static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) | 151 | static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) |
131 | { | 152 | { |
132 | int regulator_id, ret; | 153 | int ret; |
133 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 154 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
134 | u8 value; | 155 | u8 regval; |
135 | 156 | ||
136 | regulator_id = rdev_get_id(rdev); | 157 | if (info == NULL) { |
137 | if (regulator_id >= AB8500_NUM_REGULATORS) | 158 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
138 | return -EINVAL; | 159 | return -EINVAL; |
160 | } | ||
139 | 161 | ||
140 | ret = abx500_get_register_interruptible(info->dev, | 162 | ret = abx500_get_register_interruptible(info->dev, |
141 | info->update_bank, info->update_reg, &value); | 163 | info->update_bank, info->update_reg, ®val); |
142 | if (ret < 0) { | 164 | if (ret < 0) { |
143 | dev_err(rdev_get_dev(rdev), | 165 | dev_err(rdev_get_dev(rdev), |
144 | "couldn't read 0x%x register\n", info->update_reg); | 166 | "couldn't read 0x%x register\n", info->update_reg); |
145 | return ret; | 167 | return ret; |
146 | } | 168 | } |
147 | 169 | ||
148 | if (value & info->mask) | 170 | dev_vdbg(rdev_get_dev(rdev), |
171 | "%s-is_enabled (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," | ||
172 | " 0x%x\n", | ||
173 | info->desc.name, info->update_bank, info->update_reg, | ||
174 | info->update_mask, regval); | ||
175 | |||
176 | if (regval & info->update_mask) | ||
149 | return true; | 177 | return true; |
150 | else | 178 | else |
151 | return false; | 179 | return false; |
@@ -153,12 +181,12 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) | |||
153 | 181 | ||
154 | static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | 182 | static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) |
155 | { | 183 | { |
156 | int regulator_id; | ||
157 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 184 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
158 | 185 | ||
159 | regulator_id = rdev_get_id(rdev); | 186 | if (info == NULL) { |
160 | if (regulator_id >= AB8500_NUM_REGULATORS) | 187 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
161 | return -EINVAL; | 188 | return -EINVAL; |
189 | } | ||
162 | 190 | ||
163 | /* return the uV for the fixed regulators */ | 191 | /* return the uV for the fixed regulators */ |
164 | if (info->fixed_uV) | 192 | if (info->fixed_uV) |
@@ -167,33 +195,40 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) | |||
167 | if (selector >= info->voltages_len) | 195 | if (selector >= info->voltages_len) |
168 | return -EINVAL; | 196 | return -EINVAL; |
169 | 197 | ||
170 | return info->supported_voltages[selector]; | 198 | return info->voltages[selector]; |
171 | } | 199 | } |
172 | 200 | ||
173 | static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) | 201 | static int ab8500_regulator_get_voltage(struct regulator_dev *rdev) |
174 | { | 202 | { |
175 | int regulator_id, ret; | 203 | int ret, val; |
176 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 204 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
177 | u8 value; | 205 | u8 regval; |
178 | 206 | ||
179 | regulator_id = rdev_get_id(rdev); | 207 | if (info == NULL) { |
180 | if (regulator_id >= AB8500_NUM_REGULATORS) | 208 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
181 | return -EINVAL; | 209 | return -EINVAL; |
210 | } | ||
182 | 211 | ||
183 | ret = abx500_get_register_interruptible(info->dev, info->voltage_bank, | 212 | ret = abx500_get_register_interruptible(info->dev, |
184 | info->voltage_reg, &value); | 213 | info->voltage_bank, info->voltage_reg, ®val); |
185 | if (ret < 0) { | 214 | if (ret < 0) { |
186 | dev_err(rdev_get_dev(rdev), | 215 | dev_err(rdev_get_dev(rdev), |
187 | "couldn't read voltage reg for regulator\n"); | 216 | "couldn't read voltage reg for regulator\n"); |
188 | return ret; | 217 | return ret; |
189 | } | 218 | } |
190 | 219 | ||
220 | dev_vdbg(rdev_get_dev(rdev), | ||
221 | "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," | ||
222 | " 0x%x\n", | ||
223 | info->desc.name, info->voltage_bank, info->voltage_reg, | ||
224 | info->voltage_mask, regval); | ||
225 | |||
191 | /* vintcore has a different layout */ | 226 | /* vintcore has a different layout */ |
192 | value &= info->voltage_mask; | 227 | val = regval & info->voltage_mask; |
193 | if (regulator_id == AB8500_LDO_INTCORE) | 228 | if (info->desc.id == AB8500_LDO_INTCORE) |
194 | ret = info->supported_voltages[value >> 0x3]; | 229 | ret = info->voltages[val >> 0x3]; |
195 | else | 230 | else |
196 | ret = info->supported_voltages[value]; | 231 | ret = info->voltages[val]; |
197 | 232 | ||
198 | return ret; | 233 | return ret; |
199 | } | 234 | } |
@@ -206,8 +241,8 @@ static int ab8500_get_best_voltage_index(struct regulator_dev *rdev, | |||
206 | 241 | ||
207 | /* check the supported voltage */ | 242 | /* check the supported voltage */ |
208 | for (i = 0; i < info->voltages_len; i++) { | 243 | for (i = 0; i < info->voltages_len; i++) { |
209 | if ((info->supported_voltages[i] >= min_uV) && | 244 | if ((info->voltages[i] >= min_uV) && |
210 | (info->supported_voltages[i] <= max_uV)) | 245 | (info->voltages[i] <= max_uV)) |
211 | return i; | 246 | return i; |
212 | } | 247 | } |
213 | 248 | ||
@@ -215,14 +250,17 @@ static int ab8500_get_best_voltage_index(struct regulator_dev *rdev, | |||
215 | } | 250 | } |
216 | 251 | ||
217 | static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, | 252 | static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, |
218 | int min_uV, int max_uV) | 253 | int min_uV, int max_uV, |
254 | unsigned *selector) | ||
219 | { | 255 | { |
220 | int regulator_id, ret; | 256 | int ret; |
221 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 257 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
258 | u8 regval; | ||
222 | 259 | ||
223 | regulator_id = rdev_get_id(rdev); | 260 | if (info == NULL) { |
224 | if (regulator_id >= AB8500_NUM_REGULATORS) | 261 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
225 | return -EINVAL; | 262 | return -EINVAL; |
263 | } | ||
226 | 264 | ||
227 | /* get the appropriate voltages within the range */ | 265 | /* get the appropriate voltages within the range */ |
228 | ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV); | 266 | ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV); |
@@ -232,14 +270,23 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev, | |||
232 | return ret; | 270 | return ret; |
233 | } | 271 | } |
234 | 272 | ||
273 | *selector = ret; | ||
274 | |||
235 | /* set the registers for the request */ | 275 | /* set the registers for the request */ |
276 | regval = (u8)ret; | ||
236 | ret = abx500_mask_and_set_register_interruptible(info->dev, | 277 | ret = abx500_mask_and_set_register_interruptible(info->dev, |
237 | info->voltage_bank, info->voltage_reg, | 278 | info->voltage_bank, info->voltage_reg, |
238 | info->voltage_mask, (u8)ret); | 279 | info->voltage_mask, regval); |
239 | if (ret < 0) | 280 | if (ret < 0) |
240 | dev_err(rdev_get_dev(rdev), | 281 | dev_err(rdev_get_dev(rdev), |
241 | "couldn't set voltage reg for regulator\n"); | 282 | "couldn't set voltage reg for regulator\n"); |
242 | 283 | ||
284 | dev_vdbg(rdev_get_dev(rdev), | ||
285 | "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," | ||
286 | " 0x%x\n", | ||
287 | info->desc.name, info->voltage_bank, info->voltage_reg, | ||
288 | info->voltage_mask, regval); | ||
289 | |||
243 | return ret; | 290 | return ret; |
244 | } | 291 | } |
245 | 292 | ||
@@ -254,17 +301,17 @@ static struct regulator_ops ab8500_regulator_ops = { | |||
254 | 301 | ||
255 | static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) | 302 | static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) |
256 | { | 303 | { |
257 | int regulator_id; | ||
258 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); | 304 | struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); |
259 | 305 | ||
260 | regulator_id = rdev_get_id(rdev); | 306 | if (info == NULL) { |
261 | if (regulator_id >= AB8500_NUM_REGULATORS) | 307 | dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); |
262 | return -EINVAL; | 308 | return -EINVAL; |
309 | } | ||
263 | 310 | ||
264 | return info->fixed_uV; | 311 | return info->fixed_uV; |
265 | } | 312 | } |
266 | 313 | ||
267 | static struct regulator_ops ab8500_ldo_fixed_ops = { | 314 | static struct regulator_ops ab8500_regulator_fixed_ops = { |
268 | .enable = ab8500_regulator_enable, | 315 | .enable = ab8500_regulator_enable, |
269 | .disable = ab8500_regulator_disable, | 316 | .disable = ab8500_regulator_disable, |
270 | .is_enabled = ab8500_regulator_is_enabled, | 317 | .is_enabled = ab8500_regulator_is_enabled, |
@@ -272,88 +319,197 @@ static struct regulator_ops ab8500_ldo_fixed_ops = { | |||
272 | .list_voltage = ab8500_list_voltage, | 319 | .list_voltage = ab8500_list_voltage, |
273 | }; | 320 | }; |
274 | 321 | ||
275 | #define AB8500_LDO(_id, min, max, bank, reg, reg_mask, \ | 322 | static struct ab8500_regulator_info |
276 | reg_enable, volt_bank, volt_reg, volt_mask, \ | 323 | ab8500_regulator_info[AB8500_NUM_REGULATORS] = { |
277 | voltages, len_volts) \ | ||
278 | { \ | ||
279 | .desc = { \ | ||
280 | .name = "LDO-" #_id, \ | ||
281 | .ops = &ab8500_regulator_ops, \ | ||
282 | .type = REGULATOR_VOLTAGE, \ | ||
283 | .id = AB8500_LDO_##_id, \ | ||
284 | .owner = THIS_MODULE, \ | ||
285 | }, \ | ||
286 | .min_uV = (min) * 1000, \ | ||
287 | .max_uV = (max) * 1000, \ | ||
288 | .update_bank = bank, \ | ||
289 | .update_reg = reg, \ | ||
290 | .mask = reg_mask, \ | ||
291 | .enable = reg_enable, \ | ||
292 | .voltage_bank = volt_bank, \ | ||
293 | .voltage_reg = volt_reg, \ | ||
294 | .voltage_mask = volt_mask, \ | ||
295 | .supported_voltages = voltages, \ | ||
296 | .voltages_len = len_volts, \ | ||
297 | .fixed_uV = 0, \ | ||
298 | } | ||
299 | |||
300 | #define AB8500_FIXED_LDO(_id, fixed, bank, reg, \ | ||
301 | reg_mask, reg_enable) \ | ||
302 | { \ | ||
303 | .desc = { \ | ||
304 | .name = "LDO-" #_id, \ | ||
305 | .ops = &ab8500_ldo_fixed_ops, \ | ||
306 | .type = REGULATOR_VOLTAGE, \ | ||
307 | .id = AB8500_LDO_##_id, \ | ||
308 | .owner = THIS_MODULE, \ | ||
309 | }, \ | ||
310 | .fixed_uV = fixed * 1000, \ | ||
311 | .update_bank = bank, \ | ||
312 | .update_reg = reg, \ | ||
313 | .mask = reg_mask, \ | ||
314 | .enable = reg_enable, \ | ||
315 | } | ||
316 | |||
317 | static struct ab8500_regulator_info ab8500_regulator_info[] = { | ||
318 | /* | 324 | /* |
319 | * Variable Voltage LDOs | 325 | * Variable Voltage Regulators |
320 | * name, min uV, max uV, ctrl bank, ctrl reg, reg mask, enable mask, | 326 | * name, min mV, max mV, |
321 | * volt ctrl bank, volt ctrl reg, volt ctrl mask, volt table, | 327 | * update bank, reg, mask, enable val |
322 | * num supported volts | 328 | * volt bank, reg, mask, table, table length |
323 | */ | 329 | */ |
324 | AB8500_LDO(AUX1, 1100, 3300, 0x04, 0x09, 0x3, 0x1, 0x04, 0x1f, 0xf, | 330 | [AB8500_LDO_AUX1] = { |
325 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | 331 | .desc = { |
326 | AB8500_LDO(AUX2, 1100, 3300, 0x04, 0x09, 0xc, 0x4, 0x04, 0x20, 0xf, | 332 | .name = "LDO-AUX1", |
327 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | 333 | .ops = &ab8500_regulator_ops, |
328 | AB8500_LDO(AUX3, 1100, 3300, 0x04, 0x0a, 0x3, 0x1, 0x04, 0x21, 0xf, | 334 | .type = REGULATOR_VOLTAGE, |
329 | ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)), | 335 | .id = AB8500_LDO_AUX1, |
330 | AB8500_LDO(INTCORE, 1100, 3300, 0x03, 0x80, 0x4, 0x4, 0x03, 0x80, 0x38, | 336 | .owner = THIS_MODULE, |
331 | ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)), | 337 | .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), |
338 | }, | ||
339 | .min_uV = 1100000, | ||
340 | .max_uV = 3300000, | ||
341 | .update_bank = 0x04, | ||
342 | .update_reg = 0x09, | ||
343 | .update_mask = 0x03, | ||
344 | .update_val_enable = 0x01, | ||
345 | .voltage_bank = 0x04, | ||
346 | .voltage_reg = 0x1f, | ||
347 | .voltage_mask = 0x0f, | ||
348 | .voltages = ldo_vauxn_voltages, | ||
349 | .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), | ||
350 | }, | ||
351 | [AB8500_LDO_AUX2] = { | ||
352 | .desc = { | ||
353 | .name = "LDO-AUX2", | ||
354 | .ops = &ab8500_regulator_ops, | ||
355 | .type = REGULATOR_VOLTAGE, | ||
356 | .id = AB8500_LDO_AUX2, | ||
357 | .owner = THIS_MODULE, | ||
358 | .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), | ||
359 | }, | ||
360 | .min_uV = 1100000, | ||
361 | .max_uV = 3300000, | ||
362 | .update_bank = 0x04, | ||
363 | .update_reg = 0x09, | ||
364 | .update_mask = 0x0c, | ||
365 | .update_val_enable = 0x04, | ||
366 | .voltage_bank = 0x04, | ||
367 | .voltage_reg = 0x20, | ||
368 | .voltage_mask = 0x0f, | ||
369 | .voltages = ldo_vauxn_voltages, | ||
370 | .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), | ||
371 | }, | ||
372 | [AB8500_LDO_AUX3] = { | ||
373 | .desc = { | ||
374 | .name = "LDO-AUX3", | ||
375 | .ops = &ab8500_regulator_ops, | ||
376 | .type = REGULATOR_VOLTAGE, | ||
377 | .id = AB8500_LDO_AUX3, | ||
378 | .owner = THIS_MODULE, | ||
379 | .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), | ||
380 | }, | ||
381 | .min_uV = 1100000, | ||
382 | .max_uV = 3300000, | ||
383 | .update_bank = 0x04, | ||
384 | .update_reg = 0x0a, | ||
385 | .update_mask = 0x03, | ||
386 | .update_val_enable = 0x01, | ||
387 | .voltage_bank = 0x04, | ||
388 | .voltage_reg = 0x21, | ||
389 | .voltage_mask = 0x07, | ||
390 | .voltages = ldo_vaux3_voltages, | ||
391 | .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages), | ||
392 | }, | ||
393 | [AB8500_LDO_INTCORE] = { | ||
394 | .desc = { | ||
395 | .name = "LDO-INTCORE", | ||
396 | .ops = &ab8500_regulator_ops, | ||
397 | .type = REGULATOR_VOLTAGE, | ||
398 | .id = AB8500_LDO_INTCORE, | ||
399 | .owner = THIS_MODULE, | ||
400 | .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), | ||
401 | }, | ||
402 | .min_uV = 1100000, | ||
403 | .max_uV = 3300000, | ||
404 | .update_bank = 0x03, | ||
405 | .update_reg = 0x80, | ||
406 | .update_mask = 0x44, | ||
407 | .update_val_enable = 0x04, | ||
408 | .voltage_bank = 0x03, | ||
409 | .voltage_reg = 0x80, | ||
410 | .voltage_mask = 0x38, | ||
411 | .voltages = ldo_vintcore_voltages, | ||
412 | .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), | ||
413 | }, | ||
332 | 414 | ||
333 | /* | 415 | /* |
334 | * Fixed Voltage LDOs | 416 | * Fixed Voltage Regulators |
335 | * name, o/p uV, ctrl bank, ctrl reg, enable, disable | 417 | * name, fixed mV, |
418 | * update bank, reg, mask, enable val | ||
336 | */ | 419 | */ |
337 | AB8500_FIXED_LDO(TVOUT, 2000, 0x03, 0x80, 0x2, 0x2), | 420 | [AB8500_LDO_TVOUT] = { |
338 | AB8500_FIXED_LDO(AUDIO, 2000, 0x03, 0x83, 0x2, 0x2), | 421 | .desc = { |
339 | AB8500_FIXED_LDO(ANAMIC1, 2050, 0x03, 0x83, 0x4, 0x4), | 422 | .name = "LDO-TVOUT", |
340 | AB8500_FIXED_LDO(ANAMIC2, 2050, 0x03, 0x83, 0x8, 0x8), | 423 | .ops = &ab8500_regulator_fixed_ops, |
341 | AB8500_FIXED_LDO(DMIC, 1800, 0x03, 0x83, 0x10, 0x10), | 424 | .type = REGULATOR_VOLTAGE, |
342 | AB8500_FIXED_LDO(ANA, 1200, 0x03, 0x83, 0xc, 0x4), | 425 | .id = AB8500_LDO_TVOUT, |
343 | }; | 426 | .owner = THIS_MODULE, |
427 | .n_voltages = 1, | ||
428 | }, | ||
429 | .fixed_uV = 2000000, | ||
430 | .update_bank = 0x03, | ||
431 | .update_reg = 0x80, | ||
432 | .update_mask = 0x82, | ||
433 | .update_val_enable = 0x02, | ||
434 | }, | ||
435 | [AB8500_LDO_AUDIO] = { | ||
436 | .desc = { | ||
437 | .name = "LDO-AUDIO", | ||
438 | .ops = &ab8500_regulator_fixed_ops, | ||
439 | .type = REGULATOR_VOLTAGE, | ||
440 | .id = AB8500_LDO_AUDIO, | ||
441 | .owner = THIS_MODULE, | ||
442 | .n_voltages = 1, | ||
443 | }, | ||
444 | .fixed_uV = 2000000, | ||
445 | .update_bank = 0x03, | ||
446 | .update_reg = 0x83, | ||
447 | .update_mask = 0x02, | ||
448 | .update_val_enable = 0x02, | ||
449 | }, | ||
450 | [AB8500_LDO_ANAMIC1] = { | ||
451 | .desc = { | ||
452 | .name = "LDO-ANAMIC1", | ||
453 | .ops = &ab8500_regulator_fixed_ops, | ||
454 | .type = REGULATOR_VOLTAGE, | ||
455 | .id = AB8500_LDO_ANAMIC1, | ||
456 | .owner = THIS_MODULE, | ||
457 | .n_voltages = 1, | ||
458 | }, | ||
459 | .fixed_uV = 2050000, | ||
460 | .update_bank = 0x03, | ||
461 | .update_reg = 0x83, | ||
462 | .update_mask = 0x08, | ||
463 | .update_val_enable = 0x08, | ||
464 | }, | ||
465 | [AB8500_LDO_ANAMIC2] = { | ||
466 | .desc = { | ||
467 | .name = "LDO-ANAMIC2", | ||
468 | .ops = &ab8500_regulator_fixed_ops, | ||
469 | .type = REGULATOR_VOLTAGE, | ||
470 | .id = AB8500_LDO_ANAMIC2, | ||
471 | .owner = THIS_MODULE, | ||
472 | .n_voltages = 1, | ||
473 | }, | ||
474 | .fixed_uV = 2050000, | ||
475 | .update_bank = 0x03, | ||
476 | .update_reg = 0x83, | ||
477 | .update_mask = 0x10, | ||
478 | .update_val_enable = 0x10, | ||
479 | }, | ||
480 | [AB8500_LDO_DMIC] = { | ||
481 | .desc = { | ||
482 | .name = "LDO-DMIC", | ||
483 | .ops = &ab8500_regulator_fixed_ops, | ||
484 | .type = REGULATOR_VOLTAGE, | ||
485 | .id = AB8500_LDO_DMIC, | ||
486 | .owner = THIS_MODULE, | ||
487 | .n_voltages = 1, | ||
488 | }, | ||
489 | .fixed_uV = 1800000, | ||
490 | .update_bank = 0x03, | ||
491 | .update_reg = 0x83, | ||
492 | .update_mask = 0x04, | ||
493 | .update_val_enable = 0x04, | ||
494 | }, | ||
495 | [AB8500_LDO_ANA] = { | ||
496 | .desc = { | ||
497 | .name = "LDO-ANA", | ||
498 | .ops = &ab8500_regulator_fixed_ops, | ||
499 | .type = REGULATOR_VOLTAGE, | ||
500 | .id = AB8500_LDO_ANA, | ||
501 | .owner = THIS_MODULE, | ||
502 | .n_voltages = 1, | ||
503 | }, | ||
504 | .fixed_uV = 1200000, | ||
505 | .update_bank = 0x04, | ||
506 | .update_reg = 0x06, | ||
507 | .update_mask = 0x0c, | ||
508 | .update_val_enable = 0x04, | ||
509 | }, | ||
344 | 510 | ||
345 | static inline struct ab8500_regulator_info *find_regulator_info(int id) | ||
346 | { | ||
347 | struct ab8500_regulator_info *info; | ||
348 | int i; | ||
349 | 511 | ||
350 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | 512 | }; |
351 | info = &ab8500_regulator_info[i]; | ||
352 | if (info->desc.id == id) | ||
353 | return info; | ||
354 | } | ||
355 | return NULL; | ||
356 | } | ||
357 | 513 | ||
358 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | 514 | static __devinit int ab8500_regulator_probe(struct platform_device *pdev) |
359 | { | 515 | { |
@@ -366,6 +522,16 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | |||
366 | return -EINVAL; | 522 | return -EINVAL; |
367 | } | 523 | } |
368 | pdata = dev_get_platdata(ab8500->dev); | 524 | pdata = dev_get_platdata(ab8500->dev); |
525 | if (!pdata) { | ||
526 | dev_err(&pdev->dev, "null pdata\n"); | ||
527 | return -EINVAL; | ||
528 | } | ||
529 | |||
530 | /* make sure the platform data has the correct size */ | ||
531 | if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) { | ||
532 | dev_err(&pdev->dev, "platform configuration error\n"); | ||
533 | return -EINVAL; | ||
534 | } | ||
369 | 535 | ||
370 | /* register all regulators */ | 536 | /* register all regulators */ |
371 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | 537 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { |
@@ -374,10 +540,22 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | |||
374 | /* assign per-regulator data */ | 540 | /* assign per-regulator data */ |
375 | info = &ab8500_regulator_info[i]; | 541 | info = &ab8500_regulator_info[i]; |
376 | info->dev = &pdev->dev; | 542 | info->dev = &pdev->dev; |
377 | info->ab8500 = ab8500; | ||
378 | 543 | ||
544 | /* fix for hardware before ab8500v2.0 */ | ||
545 | if (abx500_get_chip_id(info->dev) < 0x20) { | ||
546 | if (info->desc.id == AB8500_LDO_AUX3) { | ||
547 | info->desc.n_voltages = | ||
548 | ARRAY_SIZE(ldo_vauxn_voltages); | ||
549 | info->voltages = ldo_vauxn_voltages; | ||
550 | info->voltages_len = | ||
551 | ARRAY_SIZE(ldo_vauxn_voltages); | ||
552 | info->voltage_mask = 0xf; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* register regulator with framework */ | ||
379 | info->regulator = regulator_register(&info->desc, &pdev->dev, | 557 | info->regulator = regulator_register(&info->desc, &pdev->dev, |
380 | pdata->regulator[i], info); | 558 | &pdata->regulator[i], info); |
381 | if (IS_ERR(info->regulator)) { | 559 | if (IS_ERR(info->regulator)) { |
382 | err = PTR_ERR(info->regulator); | 560 | err = PTR_ERR(info->regulator); |
383 | dev_err(&pdev->dev, "failed to register regulator %s\n", | 561 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
@@ -389,6 +567,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) | |||
389 | } | 567 | } |
390 | return err; | 568 | return err; |
391 | } | 569 | } |
570 | |||
571 | dev_vdbg(rdev_get_dev(info->regulator), | ||
572 | "%s-probed\n", info->desc.name); | ||
392 | } | 573 | } |
393 | 574 | ||
394 | return 0; | 575 | return 0; |
@@ -401,6 +582,10 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev) | |||
401 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { | 582 | for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { |
402 | struct ab8500_regulator_info *info = NULL; | 583 | struct ab8500_regulator_info *info = NULL; |
403 | info = &ab8500_regulator_info[i]; | 584 | info = &ab8500_regulator_info[i]; |
585 | |||
586 | dev_vdbg(rdev_get_dev(info->regulator), | ||
587 | "%s-remove\n", info->desc.name); | ||
588 | |||
404 | regulator_unregister(info->regulator); | 589 | regulator_unregister(info->regulator); |
405 | } | 590 | } |
406 | 591 | ||
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ba521f0f0fac..9fa20957847d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -13,8 +13,11 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #define pr_fmt(fmt) "%s: " fmt, __func__ | ||
17 | |||
16 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
17 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/debugfs.h> | ||
18 | #include <linux/device.h> | 21 | #include <linux/device.h> |
19 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
20 | #include <linux/err.h> | 23 | #include <linux/err.h> |
@@ -25,16 +28,30 @@ | |||
25 | #include <linux/regulator/driver.h> | 28 | #include <linux/regulator/driver.h> |
26 | #include <linux/regulator/machine.h> | 29 | #include <linux/regulator/machine.h> |
27 | 30 | ||
31 | #define CREATE_TRACE_POINTS | ||
32 | #include <trace/events/regulator.h> | ||
33 | |||
28 | #include "dummy.h" | 34 | #include "dummy.h" |
29 | 35 | ||
30 | #define REGULATOR_VERSION "0.5" | 36 | #define rdev_err(rdev, fmt, ...) \ |
37 | pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) | ||
38 | #define rdev_warn(rdev, fmt, ...) \ | ||
39 | pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) | ||
40 | #define rdev_info(rdev, fmt, ...) \ | ||
41 | pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) | ||
42 | #define rdev_dbg(rdev, fmt, ...) \ | ||
43 | pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) | ||
31 | 44 | ||
32 | static DEFINE_MUTEX(regulator_list_mutex); | 45 | static DEFINE_MUTEX(regulator_list_mutex); |
33 | static LIST_HEAD(regulator_list); | 46 | static LIST_HEAD(regulator_list); |
34 | static LIST_HEAD(regulator_map_list); | 47 | static LIST_HEAD(regulator_map_list); |
35 | static int has_full_constraints; | 48 | static bool has_full_constraints; |
36 | static bool board_wants_dummy_regulator; | 49 | static bool board_wants_dummy_regulator; |
37 | 50 | ||
51 | #ifdef CONFIG_DEBUG_FS | ||
52 | static struct dentry *debugfs_root; | ||
53 | #endif | ||
54 | |||
38 | /* | 55 | /* |
39 | * struct regulator_map | 56 | * struct regulator_map |
40 | * | 57 | * |
@@ -71,6 +88,8 @@ static int _regulator_get_current_limit(struct regulator_dev *rdev); | |||
71 | static unsigned int _regulator_get_mode(struct regulator_dev *rdev); | 88 | static unsigned int _regulator_get_mode(struct regulator_dev *rdev); |
72 | static void _notifier_call_chain(struct regulator_dev *rdev, | 89 | static void _notifier_call_chain(struct regulator_dev *rdev, |
73 | unsigned long event, void *data); | 90 | unsigned long event, void *data); |
91 | static int _regulator_do_set_voltage(struct regulator_dev *rdev, | ||
92 | int min_uV, int max_uV); | ||
74 | 93 | ||
75 | static const char *rdev_get_name(struct regulator_dev *rdev) | 94 | static const char *rdev_get_name(struct regulator_dev *rdev) |
76 | { | 95 | { |
@@ -111,13 +130,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev, | |||
111 | BUG_ON(*min_uV > *max_uV); | 130 | BUG_ON(*min_uV > *max_uV); |
112 | 131 | ||
113 | if (!rdev->constraints) { | 132 | if (!rdev->constraints) { |
114 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 133 | rdev_err(rdev, "no constraints\n"); |
115 | rdev_get_name(rdev)); | ||
116 | return -ENODEV; | 134 | return -ENODEV; |
117 | } | 135 | } |
118 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { | 136 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { |
119 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 137 | rdev_err(rdev, "operation not allowed\n"); |
120 | __func__, rdev_get_name(rdev)); | ||
121 | return -EPERM; | 138 | return -EPERM; |
122 | } | 139 | } |
123 | 140 | ||
@@ -132,6 +149,27 @@ static int regulator_check_voltage(struct regulator_dev *rdev, | |||
132 | return 0; | 149 | return 0; |
133 | } | 150 | } |
134 | 151 | ||
152 | /* Make sure we select a voltage that suits the needs of all | ||
153 | * regulator consumers | ||
154 | */ | ||
155 | static int regulator_check_consumers(struct regulator_dev *rdev, | ||
156 | int *min_uV, int *max_uV) | ||
157 | { | ||
158 | struct regulator *regulator; | ||
159 | |||
160 | list_for_each_entry(regulator, &rdev->consumer_list, list) { | ||
161 | if (*max_uV > regulator->max_uV) | ||
162 | *max_uV = regulator->max_uV; | ||
163 | if (*min_uV < regulator->min_uV) | ||
164 | *min_uV = regulator->min_uV; | ||
165 | } | ||
166 | |||
167 | if (*min_uV > *max_uV) | ||
168 | return -EINVAL; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
135 | /* current constraint check */ | 173 | /* current constraint check */ |
136 | static int regulator_check_current_limit(struct regulator_dev *rdev, | 174 | static int regulator_check_current_limit(struct regulator_dev *rdev, |
137 | int *min_uA, int *max_uA) | 175 | int *min_uA, int *max_uA) |
@@ -139,13 +177,11 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, | |||
139 | BUG_ON(*min_uA > *max_uA); | 177 | BUG_ON(*min_uA > *max_uA); |
140 | 178 | ||
141 | if (!rdev->constraints) { | 179 | if (!rdev->constraints) { |
142 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 180 | rdev_err(rdev, "no constraints\n"); |
143 | rdev_get_name(rdev)); | ||
144 | return -ENODEV; | 181 | return -ENODEV; |
145 | } | 182 | } |
146 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { | 183 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { |
147 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 184 | rdev_err(rdev, "operation not allowed\n"); |
148 | __func__, rdev_get_name(rdev)); | ||
149 | return -EPERM; | 185 | return -EPERM; |
150 | } | 186 | } |
151 | 187 | ||
@@ -174,18 +210,15 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode) | |||
174 | } | 210 | } |
175 | 211 | ||
176 | if (!rdev->constraints) { | 212 | if (!rdev->constraints) { |
177 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 213 | rdev_err(rdev, "no constraints\n"); |
178 | rdev_get_name(rdev)); | ||
179 | return -ENODEV; | 214 | return -ENODEV; |
180 | } | 215 | } |
181 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { | 216 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { |
182 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 217 | rdev_err(rdev, "operation not allowed\n"); |
183 | __func__, rdev_get_name(rdev)); | ||
184 | return -EPERM; | 218 | return -EPERM; |
185 | } | 219 | } |
186 | if (!(rdev->constraints->valid_modes_mask & mode)) { | 220 | if (!(rdev->constraints->valid_modes_mask & mode)) { |
187 | printk(KERN_ERR "%s: invalid mode %x for %s\n", | 221 | rdev_err(rdev, "invalid mode %x\n", mode); |
188 | __func__, mode, rdev_get_name(rdev)); | ||
189 | return -EINVAL; | 222 | return -EINVAL; |
190 | } | 223 | } |
191 | return 0; | 224 | return 0; |
@@ -195,13 +228,11 @@ static int regulator_check_mode(struct regulator_dev *rdev, int mode) | |||
195 | static int regulator_check_drms(struct regulator_dev *rdev) | 228 | static int regulator_check_drms(struct regulator_dev *rdev) |
196 | { | 229 | { |
197 | if (!rdev->constraints) { | 230 | if (!rdev->constraints) { |
198 | printk(KERN_ERR "%s: no constraints for %s\n", __func__, | 231 | rdev_err(rdev, "no constraints\n"); |
199 | rdev_get_name(rdev)); | ||
200 | return -ENODEV; | 232 | return -ENODEV; |
201 | } | 233 | } |
202 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { | 234 | if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { |
203 | printk(KERN_ERR "%s: operation not allowed for %s\n", | 235 | rdev_err(rdev, "operation not allowed\n"); |
204 | __func__, rdev_get_name(rdev)); | ||
205 | return -EPERM; | 236 | return -EPERM; |
206 | } | 237 | } |
207 | return 0; | 238 | return 0; |
@@ -553,18 +584,21 @@ static void drms_uA_update(struct regulator_dev *rdev) | |||
553 | 584 | ||
554 | err = regulator_check_drms(rdev); | 585 | err = regulator_check_drms(rdev); |
555 | if (err < 0 || !rdev->desc->ops->get_optimum_mode || | 586 | if (err < 0 || !rdev->desc->ops->get_optimum_mode || |
556 | !rdev->desc->ops->get_voltage || !rdev->desc->ops->set_mode) | 587 | (!rdev->desc->ops->get_voltage && |
588 | !rdev->desc->ops->get_voltage_sel) || | ||
589 | !rdev->desc->ops->set_mode) | ||
557 | return; | 590 | return; |
558 | 591 | ||
559 | /* get output voltage */ | 592 | /* get output voltage */ |
560 | output_uV = rdev->desc->ops->get_voltage(rdev); | 593 | output_uV = _regulator_get_voltage(rdev); |
561 | if (output_uV <= 0) | 594 | if (output_uV <= 0) |
562 | return; | 595 | return; |
563 | 596 | ||
564 | /* get input voltage */ | 597 | /* get input voltage */ |
565 | if (rdev->supply && rdev->supply->desc->ops->get_voltage) | 598 | input_uV = 0; |
566 | input_uV = rdev->supply->desc->ops->get_voltage(rdev->supply); | 599 | if (rdev->supply) |
567 | else | 600 | input_uV = _regulator_get_voltage(rdev); |
601 | if (input_uV <= 0) | ||
568 | input_uV = rdev->constraints->input_uV; | 602 | input_uV = rdev->constraints->input_uV; |
569 | if (input_uV <= 0) | 603 | if (input_uV <= 0) |
570 | return; | 604 | return; |
@@ -598,20 +632,17 @@ static int suspend_set_state(struct regulator_dev *rdev, | |||
598 | */ | 632 | */ |
599 | if (!rstate->enabled && !rstate->disabled) { | 633 | if (!rstate->enabled && !rstate->disabled) { |
600 | if (can_set_state) | 634 | if (can_set_state) |
601 | printk(KERN_WARNING "%s: No configuration for %s\n", | 635 | rdev_warn(rdev, "No configuration\n"); |
602 | __func__, rdev_get_name(rdev)); | ||
603 | return 0; | 636 | return 0; |
604 | } | 637 | } |
605 | 638 | ||
606 | if (rstate->enabled && rstate->disabled) { | 639 | if (rstate->enabled && rstate->disabled) { |
607 | printk(KERN_ERR "%s: invalid configuration for %s\n", | 640 | rdev_err(rdev, "invalid configuration\n"); |
608 | __func__, rdev_get_name(rdev)); | ||
609 | return -EINVAL; | 641 | return -EINVAL; |
610 | } | 642 | } |
611 | 643 | ||
612 | if (!can_set_state) { | 644 | if (!can_set_state) { |
613 | printk(KERN_ERR "%s: no way to set suspend state\n", | 645 | rdev_err(rdev, "no way to set suspend state\n"); |
614 | __func__); | ||
615 | return -EINVAL; | 646 | return -EINVAL; |
616 | } | 647 | } |
617 | 648 | ||
@@ -620,15 +651,14 @@ static int suspend_set_state(struct regulator_dev *rdev, | |||
620 | else | 651 | else |
621 | ret = rdev->desc->ops->set_suspend_disable(rdev); | 652 | ret = rdev->desc->ops->set_suspend_disable(rdev); |
622 | if (ret < 0) { | 653 | if (ret < 0) { |
623 | printk(KERN_ERR "%s: failed to enabled/disable\n", __func__); | 654 | rdev_err(rdev, "failed to enabled/disable\n"); |
624 | return ret; | 655 | return ret; |
625 | } | 656 | } |
626 | 657 | ||
627 | if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { | 658 | if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { |
628 | ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); | 659 | ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); |
629 | if (ret < 0) { | 660 | if (ret < 0) { |
630 | printk(KERN_ERR "%s: failed to set voltage\n", | 661 | rdev_err(rdev, "failed to set voltage\n"); |
631 | __func__); | ||
632 | return ret; | 662 | return ret; |
633 | } | 663 | } |
634 | } | 664 | } |
@@ -636,7 +666,7 @@ static int suspend_set_state(struct regulator_dev *rdev, | |||
636 | if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { | 666 | if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { |
637 | ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); | 667 | ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); |
638 | if (ret < 0) { | 668 | if (ret < 0) { |
639 | printk(KERN_ERR "%s: failed to set mode\n", __func__); | 669 | rdev_err(rdev, "failed to set mode\n"); |
640 | return ret; | 670 | return ret; |
641 | } | 671 | } |
642 | } | 672 | } |
@@ -714,29 +744,27 @@ static void print_constraints(struct regulator_dev *rdev) | |||
714 | if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) | 744 | if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) |
715 | count += sprintf(buf + count, "standby"); | 745 | count += sprintf(buf + count, "standby"); |
716 | 746 | ||
717 | printk(KERN_INFO "regulator: %s: %s\n", rdev_get_name(rdev), buf); | 747 | rdev_info(rdev, "%s\n", buf); |
718 | } | 748 | } |
719 | 749 | ||
720 | static int machine_constraints_voltage(struct regulator_dev *rdev, | 750 | static int machine_constraints_voltage(struct regulator_dev *rdev, |
721 | struct regulation_constraints *constraints) | 751 | struct regulation_constraints *constraints) |
722 | { | 752 | { |
723 | struct regulator_ops *ops = rdev->desc->ops; | 753 | struct regulator_ops *ops = rdev->desc->ops; |
724 | const char *name = rdev_get_name(rdev); | ||
725 | int ret; | 754 | int ret; |
726 | 755 | ||
727 | /* do we need to apply the constraint voltage */ | 756 | /* do we need to apply the constraint voltage */ |
728 | if (rdev->constraints->apply_uV && | 757 | if (rdev->constraints->apply_uV && |
729 | rdev->constraints->min_uV == rdev->constraints->max_uV && | 758 | rdev->constraints->min_uV == rdev->constraints->max_uV) { |
730 | ops->set_voltage) { | 759 | ret = _regulator_do_set_voltage(rdev, |
731 | ret = ops->set_voltage(rdev, | 760 | rdev->constraints->min_uV, |
732 | rdev->constraints->min_uV, rdev->constraints->max_uV); | 761 | rdev->constraints->max_uV); |
733 | if (ret < 0) { | 762 | if (ret < 0) { |
734 | printk(KERN_ERR "%s: failed to apply %duV constraint to %s\n", | 763 | rdev_err(rdev, "failed to apply %duV constraint\n", |
735 | __func__, | 764 | rdev->constraints->min_uV); |
736 | rdev->constraints->min_uV, name); | 765 | rdev->constraints = NULL; |
737 | rdev->constraints = NULL; | 766 | return ret; |
738 | return ret; | 767 | } |
739 | } | ||
740 | } | 768 | } |
741 | 769 | ||
742 | /* constrain machine-level voltage specs to fit | 770 | /* constrain machine-level voltage specs to fit |
@@ -765,8 +793,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, | |||
765 | 793 | ||
766 | /* else require explicit machine-level constraints */ | 794 | /* else require explicit machine-level constraints */ |
767 | if (cmin <= 0 || cmax <= 0 || cmax < cmin) { | 795 | if (cmin <= 0 || cmax <= 0 || cmax < cmin) { |
768 | pr_err("%s: %s '%s' voltage constraints\n", | 796 | rdev_err(rdev, "invalid voltage constraints\n"); |
769 | __func__, "invalid", name); | ||
770 | return -EINVAL; | 797 | return -EINVAL; |
771 | } | 798 | } |
772 | 799 | ||
@@ -787,22 +814,19 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, | |||
787 | 814 | ||
788 | /* final: [min_uV..max_uV] valid iff constraints valid */ | 815 | /* final: [min_uV..max_uV] valid iff constraints valid */ |
789 | if (max_uV < min_uV) { | 816 | if (max_uV < min_uV) { |
790 | pr_err("%s: %s '%s' voltage constraints\n", | 817 | rdev_err(rdev, "unsupportable voltage constraints\n"); |
791 | __func__, "unsupportable", name); | ||
792 | return -EINVAL; | 818 | return -EINVAL; |
793 | } | 819 | } |
794 | 820 | ||
795 | /* use regulator's subset of machine constraints */ | 821 | /* use regulator's subset of machine constraints */ |
796 | if (constraints->min_uV < min_uV) { | 822 | if (constraints->min_uV < min_uV) { |
797 | pr_debug("%s: override '%s' %s, %d -> %d\n", | 823 | rdev_dbg(rdev, "override min_uV, %d -> %d\n", |
798 | __func__, name, "min_uV", | 824 | constraints->min_uV, min_uV); |
799 | constraints->min_uV, min_uV); | ||
800 | constraints->min_uV = min_uV; | 825 | constraints->min_uV = min_uV; |
801 | } | 826 | } |
802 | if (constraints->max_uV > max_uV) { | 827 | if (constraints->max_uV > max_uV) { |
803 | pr_debug("%s: override '%s' %s, %d -> %d\n", | 828 | rdev_dbg(rdev, "override max_uV, %d -> %d\n", |
804 | __func__, name, "max_uV", | 829 | constraints->max_uV, max_uV); |
805 | constraints->max_uV, max_uV); | ||
806 | constraints->max_uV = max_uV; | 830 | constraints->max_uV = max_uV; |
807 | } | 831 | } |
808 | } | 832 | } |
@@ -822,26 +846,25 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, | |||
822 | * set_mode. | 846 | * set_mode. |
823 | */ | 847 | */ |
824 | static int set_machine_constraints(struct regulator_dev *rdev, | 848 | static int set_machine_constraints(struct regulator_dev *rdev, |
825 | struct regulation_constraints *constraints) | 849 | const struct regulation_constraints *constraints) |
826 | { | 850 | { |
827 | int ret = 0; | 851 | int ret = 0; |
828 | const char *name; | ||
829 | struct regulator_ops *ops = rdev->desc->ops; | 852 | struct regulator_ops *ops = rdev->desc->ops; |
830 | 853 | ||
831 | rdev->constraints = constraints; | 854 | rdev->constraints = kmemdup(constraints, sizeof(*constraints), |
832 | 855 | GFP_KERNEL); | |
833 | name = rdev_get_name(rdev); | 856 | if (!rdev->constraints) |
857 | return -ENOMEM; | ||
834 | 858 | ||
835 | ret = machine_constraints_voltage(rdev, constraints); | 859 | ret = machine_constraints_voltage(rdev, rdev->constraints); |
836 | if (ret != 0) | 860 | if (ret != 0) |
837 | goto out; | 861 | goto out; |
838 | 862 | ||
839 | /* do we need to setup our suspend state */ | 863 | /* do we need to setup our suspend state */ |
840 | if (constraints->initial_state) { | 864 | if (constraints->initial_state) { |
841 | ret = suspend_prepare(rdev, constraints->initial_state); | 865 | ret = suspend_prepare(rdev, rdev->constraints->initial_state); |
842 | if (ret < 0) { | 866 | if (ret < 0) { |
843 | printk(KERN_ERR "%s: failed to set suspend state for %s\n", | 867 | rdev_err(rdev, "failed to set suspend state\n"); |
844 | __func__, name); | ||
845 | rdev->constraints = NULL; | 868 | rdev->constraints = NULL; |
846 | goto out; | 869 | goto out; |
847 | } | 870 | } |
@@ -849,17 +872,14 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
849 | 872 | ||
850 | if (constraints->initial_mode) { | 873 | if (constraints->initial_mode) { |
851 | if (!ops->set_mode) { | 874 | if (!ops->set_mode) { |
852 | printk(KERN_ERR "%s: no set_mode operation for %s\n", | 875 | rdev_err(rdev, "no set_mode operation\n"); |
853 | __func__, name); | ||
854 | ret = -EINVAL; | 876 | ret = -EINVAL; |
855 | goto out; | 877 | goto out; |
856 | } | 878 | } |
857 | 879 | ||
858 | ret = ops->set_mode(rdev, constraints->initial_mode); | 880 | ret = ops->set_mode(rdev, rdev->constraints->initial_mode); |
859 | if (ret < 0) { | 881 | if (ret < 0) { |
860 | printk(KERN_ERR | 882 | rdev_err(rdev, "failed to set initial mode: %d\n", ret); |
861 | "%s: failed to set initial mode for %s: %d\n", | ||
862 | __func__, name, ret); | ||
863 | goto out; | 883 | goto out; |
864 | } | 884 | } |
865 | } | 885 | } |
@@ -867,11 +887,11 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
867 | /* If the constraints say the regulator should be on at this point | 887 | /* If the constraints say the regulator should be on at this point |
868 | * and we have control then make sure it is enabled. | 888 | * and we have control then make sure it is enabled. |
869 | */ | 889 | */ |
870 | if ((constraints->always_on || constraints->boot_on) && ops->enable) { | 890 | if ((rdev->constraints->always_on || rdev->constraints->boot_on) && |
891 | ops->enable) { | ||
871 | ret = ops->enable(rdev); | 892 | ret = ops->enable(rdev); |
872 | if (ret < 0) { | 893 | if (ret < 0) { |
873 | printk(KERN_ERR "%s: failed to enable %s\n", | 894 | rdev_err(rdev, "failed to enable\n"); |
874 | __func__, name); | ||
875 | rdev->constraints = NULL; | 895 | rdev->constraints = NULL; |
876 | goto out; | 896 | goto out; |
877 | } | 897 | } |
@@ -899,9 +919,8 @@ static int set_supply(struct regulator_dev *rdev, | |||
899 | err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, | 919 | err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj, |
900 | "supply"); | 920 | "supply"); |
901 | if (err) { | 921 | if (err) { |
902 | printk(KERN_ERR | 922 | rdev_err(rdev, "could not add device link %s err %d\n", |
903 | "%s: could not add device link %s err %d\n", | 923 | supply_rdev->dev.kobj.name, err); |
904 | __func__, supply_rdev->dev.kobj.name, err); | ||
905 | goto out; | 924 | goto out; |
906 | } | 925 | } |
907 | rdev->supply = supply_rdev; | 926 | rdev->supply = supply_rdev; |
@@ -957,10 +976,10 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, | |||
957 | continue; | 976 | continue; |
958 | 977 | ||
959 | dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n", | 978 | dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n", |
960 | dev_name(&node->regulator->dev), | 979 | dev_name(&node->regulator->dev), |
961 | node->regulator->desc->name, | 980 | node->regulator->desc->name, |
962 | supply, | 981 | supply, |
963 | dev_name(&rdev->dev), rdev_get_name(rdev)); | 982 | dev_name(&rdev->dev), rdev_get_name(rdev)); |
964 | return -EBUSY; | 983 | return -EBUSY; |
965 | } | 984 | } |
966 | 985 | ||
@@ -1031,8 +1050,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, | |||
1031 | regulator->dev_attr.show = device_requested_uA_show; | 1050 | regulator->dev_attr.show = device_requested_uA_show; |
1032 | err = device_create_file(dev, ®ulator->dev_attr); | 1051 | err = device_create_file(dev, ®ulator->dev_attr); |
1033 | if (err < 0) { | 1052 | if (err < 0) { |
1034 | printk(KERN_WARNING "%s: could not add regulator_dev" | 1053 | rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n"); |
1035 | " load sysfs\n", __func__); | ||
1036 | goto attr_name_err; | 1054 | goto attr_name_err; |
1037 | } | 1055 | } |
1038 | 1056 | ||
@@ -1049,9 +1067,8 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, | |||
1049 | err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, | 1067 | err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, |
1050 | buf); | 1068 | buf); |
1051 | if (err) { | 1069 | if (err) { |
1052 | printk(KERN_WARNING | 1070 | rdev_warn(rdev, "could not add device link %s err %d\n", |
1053 | "%s: could not add device link %s err %d\n", | 1071 | dev->kobj.name, err); |
1054 | __func__, dev->kobj.name, err); | ||
1055 | goto link_name_err; | 1072 | goto link_name_err; |
1056 | } | 1073 | } |
1057 | } | 1074 | } |
@@ -1088,7 +1105,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, | |||
1088 | int ret; | 1105 | int ret; |
1089 | 1106 | ||
1090 | if (id == NULL) { | 1107 | if (id == NULL) { |
1091 | printk(KERN_ERR "regulator: get() with no identifier\n"); | 1108 | pr_err("get() with no identifier\n"); |
1092 | return regulator; | 1109 | return regulator; |
1093 | } | 1110 | } |
1094 | 1111 | ||
@@ -1122,8 +1139,8 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, | |||
1122 | * substitute in a dummy regulator so consumers can continue. | 1139 | * substitute in a dummy regulator so consumers can continue. |
1123 | */ | 1140 | */ |
1124 | if (!has_full_constraints) { | 1141 | if (!has_full_constraints) { |
1125 | pr_warning("%s supply %s not found, using dummy regulator\n", | 1142 | pr_warn("%s supply %s not found, using dummy regulator\n", |
1126 | devname, id); | 1143 | devname, id); |
1127 | rdev = dummy_regulator_rdev; | 1144 | rdev = dummy_regulator_rdev; |
1128 | goto found; | 1145 | goto found; |
1129 | } | 1146 | } |
@@ -1274,8 +1291,7 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
1274 | ret = _regulator_enable(rdev->supply); | 1291 | ret = _regulator_enable(rdev->supply); |
1275 | mutex_unlock(&rdev->supply->mutex); | 1292 | mutex_unlock(&rdev->supply->mutex); |
1276 | if (ret < 0) { | 1293 | if (ret < 0) { |
1277 | printk(KERN_ERR "%s: failed to enable %s: %d\n", | 1294 | rdev_err(rdev, "failed to enable: %d\n", ret); |
1278 | __func__, rdev_get_name(rdev), ret); | ||
1279 | return ret; | 1295 | return ret; |
1280 | } | 1296 | } |
1281 | } | 1297 | } |
@@ -1302,13 +1318,13 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
1302 | if (ret >= 0) { | 1318 | if (ret >= 0) { |
1303 | delay = ret; | 1319 | delay = ret; |
1304 | } else { | 1320 | } else { |
1305 | printk(KERN_WARNING | 1321 | rdev_warn(rdev, "enable_time() failed: %d\n", |
1306 | "%s: enable_time() failed for %s: %d\n", | 1322 | ret); |
1307 | __func__, rdev_get_name(rdev), | ||
1308 | ret); | ||
1309 | delay = 0; | 1323 | delay = 0; |
1310 | } | 1324 | } |
1311 | 1325 | ||
1326 | trace_regulator_enable(rdev_get_name(rdev)); | ||
1327 | |||
1312 | /* Allow the regulator to ramp; it would be useful | 1328 | /* Allow the regulator to ramp; it would be useful |
1313 | * to extend this for bulk operations so that the | 1329 | * to extend this for bulk operations so that the |
1314 | * regulators can ramp together. */ | 1330 | * regulators can ramp together. */ |
@@ -1316,6 +1332,8 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
1316 | if (ret < 0) | 1332 | if (ret < 0) |
1317 | return ret; | 1333 | return ret; |
1318 | 1334 | ||
1335 | trace_regulator_enable_delay(rdev_get_name(rdev)); | ||
1336 | |||
1319 | if (delay >= 1000) { | 1337 | if (delay >= 1000) { |
1320 | mdelay(delay / 1000); | 1338 | mdelay(delay / 1000); |
1321 | udelay(delay % 1000); | 1339 | udelay(delay % 1000); |
@@ -1323,9 +1341,10 @@ static int _regulator_enable(struct regulator_dev *rdev) | |||
1323 | udelay(delay); | 1341 | udelay(delay); |
1324 | } | 1342 | } |
1325 | 1343 | ||
1344 | trace_regulator_enable_complete(rdev_get_name(rdev)); | ||
1345 | |||
1326 | } else if (ret < 0) { | 1346 | } else if (ret < 0) { |
1327 | printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", | 1347 | rdev_err(rdev, "is_enabled() failed: %d\n", ret); |
1328 | __func__, rdev_get_name(rdev), ret); | ||
1329 | return ret; | 1348 | return ret; |
1330 | } | 1349 | } |
1331 | /* Fallthrough on positive return values - already enabled */ | 1350 | /* Fallthrough on positive return values - already enabled */ |
@@ -1367,8 +1386,7 @@ static int _regulator_disable(struct regulator_dev *rdev, | |||
1367 | *supply_rdev_ptr = NULL; | 1386 | *supply_rdev_ptr = NULL; |
1368 | 1387 | ||
1369 | if (WARN(rdev->use_count <= 0, | 1388 | if (WARN(rdev->use_count <= 0, |
1370 | "unbalanced disables for %s\n", | 1389 | "unbalanced disables for %s\n", rdev_get_name(rdev))) |
1371 | rdev_get_name(rdev))) | ||
1372 | return -EIO; | 1390 | return -EIO; |
1373 | 1391 | ||
1374 | /* are we the last user and permitted to disable ? */ | 1392 | /* are we the last user and permitted to disable ? */ |
@@ -1378,13 +1396,16 @@ static int _regulator_disable(struct regulator_dev *rdev, | |||
1378 | /* we are last user */ | 1396 | /* we are last user */ |
1379 | if (_regulator_can_change_status(rdev) && | 1397 | if (_regulator_can_change_status(rdev) && |
1380 | rdev->desc->ops->disable) { | 1398 | rdev->desc->ops->disable) { |
1399 | trace_regulator_disable(rdev_get_name(rdev)); | ||
1400 | |||
1381 | ret = rdev->desc->ops->disable(rdev); | 1401 | ret = rdev->desc->ops->disable(rdev); |
1382 | if (ret < 0) { | 1402 | if (ret < 0) { |
1383 | printk(KERN_ERR "%s: failed to disable %s\n", | 1403 | rdev_err(rdev, "failed to disable\n"); |
1384 | __func__, rdev_get_name(rdev)); | ||
1385 | return ret; | 1404 | return ret; |
1386 | } | 1405 | } |
1387 | 1406 | ||
1407 | trace_regulator_disable_complete(rdev_get_name(rdev)); | ||
1408 | |||
1388 | _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, | 1409 | _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, |
1389 | NULL); | 1410 | NULL); |
1390 | } | 1411 | } |
@@ -1451,8 +1472,7 @@ static int _regulator_force_disable(struct regulator_dev *rdev, | |||
1451 | /* ah well, who wants to live forever... */ | 1472 | /* ah well, who wants to live forever... */ |
1452 | ret = rdev->desc->ops->disable(rdev); | 1473 | ret = rdev->desc->ops->disable(rdev); |
1453 | if (ret < 0) { | 1474 | if (ret < 0) { |
1454 | printk(KERN_ERR "%s: failed to force disable %s\n", | 1475 | rdev_err(rdev, "failed to force disable\n"); |
1455 | __func__, rdev_get_name(rdev)); | ||
1456 | return ret; | 1476 | return ret; |
1457 | } | 1477 | } |
1458 | /* notify other consumers that power has been forced off */ | 1478 | /* notify other consumers that power has been forced off */ |
@@ -1605,6 +1625,62 @@ int regulator_is_supported_voltage(struct regulator *regulator, | |||
1605 | return 0; | 1625 | return 0; |
1606 | } | 1626 | } |
1607 | 1627 | ||
1628 | static int _regulator_do_set_voltage(struct regulator_dev *rdev, | ||
1629 | int min_uV, int max_uV) | ||
1630 | { | ||
1631 | int ret; | ||
1632 | unsigned int selector; | ||
1633 | |||
1634 | trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); | ||
1635 | |||
1636 | if (rdev->desc->ops->set_voltage) { | ||
1637 | ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, | ||
1638 | &selector); | ||
1639 | |||
1640 | if (rdev->desc->ops->list_voltage) | ||
1641 | selector = rdev->desc->ops->list_voltage(rdev, | ||
1642 | selector); | ||
1643 | else | ||
1644 | selector = -1; | ||
1645 | } else if (rdev->desc->ops->set_voltage_sel) { | ||
1646 | int best_val = INT_MAX; | ||
1647 | int i; | ||
1648 | |||
1649 | selector = 0; | ||
1650 | |||
1651 | /* Find the smallest voltage that falls within the specified | ||
1652 | * range. | ||
1653 | */ | ||
1654 | for (i = 0; i < rdev->desc->n_voltages; i++) { | ||
1655 | ret = rdev->desc->ops->list_voltage(rdev, i); | ||
1656 | if (ret < 0) | ||
1657 | continue; | ||
1658 | |||
1659 | if (ret < best_val && ret >= min_uV && ret <= max_uV) { | ||
1660 | best_val = ret; | ||
1661 | selector = i; | ||
1662 | } | ||
1663 | } | ||
1664 | |||
1665 | if (best_val != INT_MAX) { | ||
1666 | ret = rdev->desc->ops->set_voltage_sel(rdev, selector); | ||
1667 | selector = best_val; | ||
1668 | } else { | ||
1669 | ret = -EINVAL; | ||
1670 | } | ||
1671 | } else { | ||
1672 | ret = -EINVAL; | ||
1673 | } | ||
1674 | |||
1675 | if (ret == 0) | ||
1676 | _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, | ||
1677 | NULL); | ||
1678 | |||
1679 | trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector); | ||
1680 | |||
1681 | return ret; | ||
1682 | } | ||
1683 | |||
1608 | /** | 1684 | /** |
1609 | * regulator_set_voltage - set regulator output voltage | 1685 | * regulator_set_voltage - set regulator output voltage |
1610 | * @regulator: regulator source | 1686 | * @regulator: regulator source |
@@ -1626,12 +1702,20 @@ int regulator_is_supported_voltage(struct regulator *regulator, | |||
1626 | int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) | 1702 | int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) |
1627 | { | 1703 | { |
1628 | struct regulator_dev *rdev = regulator->rdev; | 1704 | struct regulator_dev *rdev = regulator->rdev; |
1629 | int ret; | 1705 | int ret = 0; |
1630 | 1706 | ||
1631 | mutex_lock(&rdev->mutex); | 1707 | mutex_lock(&rdev->mutex); |
1632 | 1708 | ||
1709 | /* If we're setting the same range as last time the change | ||
1710 | * should be a noop (some cpufreq implementations use the same | ||
1711 | * voltage for multiple frequencies, for example). | ||
1712 | */ | ||
1713 | if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) | ||
1714 | goto out; | ||
1715 | |||
1633 | /* sanity check */ | 1716 | /* sanity check */ |
1634 | if (!rdev->desc->ops->set_voltage) { | 1717 | if (!rdev->desc->ops->set_voltage && |
1718 | !rdev->desc->ops->set_voltage_sel) { | ||
1635 | ret = -EINVAL; | 1719 | ret = -EINVAL; |
1636 | goto out; | 1720 | goto out; |
1637 | } | 1721 | } |
@@ -1642,18 +1726,76 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) | |||
1642 | goto out; | 1726 | goto out; |
1643 | regulator->min_uV = min_uV; | 1727 | regulator->min_uV = min_uV; |
1644 | regulator->max_uV = max_uV; | 1728 | regulator->max_uV = max_uV; |
1645 | ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV); | 1729 | |
1730 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV); | ||
1731 | if (ret < 0) | ||
1732 | goto out; | ||
1733 | |||
1734 | ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); | ||
1646 | 1735 | ||
1647 | out: | 1736 | out: |
1648 | _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL); | ||
1649 | mutex_unlock(&rdev->mutex); | 1737 | mutex_unlock(&rdev->mutex); |
1650 | return ret; | 1738 | return ret; |
1651 | } | 1739 | } |
1652 | EXPORT_SYMBOL_GPL(regulator_set_voltage); | 1740 | EXPORT_SYMBOL_GPL(regulator_set_voltage); |
1653 | 1741 | ||
1742 | /** | ||
1743 | * regulator_sync_voltage - re-apply last regulator output voltage | ||
1744 | * @regulator: regulator source | ||
1745 | * | ||
1746 | * Re-apply the last configured voltage. This is intended to be used | ||
1747 | * where some external control source the consumer is cooperating with | ||
1748 | * has caused the configured voltage to change. | ||
1749 | */ | ||
1750 | int regulator_sync_voltage(struct regulator *regulator) | ||
1751 | { | ||
1752 | struct regulator_dev *rdev = regulator->rdev; | ||
1753 | int ret, min_uV, max_uV; | ||
1754 | |||
1755 | mutex_lock(&rdev->mutex); | ||
1756 | |||
1757 | if (!rdev->desc->ops->set_voltage && | ||
1758 | !rdev->desc->ops->set_voltage_sel) { | ||
1759 | ret = -EINVAL; | ||
1760 | goto out; | ||
1761 | } | ||
1762 | |||
1763 | /* This is only going to work if we've had a voltage configured. */ | ||
1764 | if (!regulator->min_uV && !regulator->max_uV) { | ||
1765 | ret = -EINVAL; | ||
1766 | goto out; | ||
1767 | } | ||
1768 | |||
1769 | min_uV = regulator->min_uV; | ||
1770 | max_uV = regulator->max_uV; | ||
1771 | |||
1772 | /* This should be a paranoia check... */ | ||
1773 | ret = regulator_check_voltage(rdev, &min_uV, &max_uV); | ||
1774 | if (ret < 0) | ||
1775 | goto out; | ||
1776 | |||
1777 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV); | ||
1778 | if (ret < 0) | ||
1779 | goto out; | ||
1780 | |||
1781 | ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); | ||
1782 | |||
1783 | out: | ||
1784 | mutex_unlock(&rdev->mutex); | ||
1785 | return ret; | ||
1786 | } | ||
1787 | EXPORT_SYMBOL_GPL(regulator_sync_voltage); | ||
1788 | |||
1654 | static int _regulator_get_voltage(struct regulator_dev *rdev) | 1789 | static int _regulator_get_voltage(struct regulator_dev *rdev) |
1655 | { | 1790 | { |
1656 | /* sanity check */ | 1791 | int sel; |
1792 | |||
1793 | if (rdev->desc->ops->get_voltage_sel) { | ||
1794 | sel = rdev->desc->ops->get_voltage_sel(rdev); | ||
1795 | if (sel < 0) | ||
1796 | return sel; | ||
1797 | return rdev->desc->ops->list_voltage(rdev, sel); | ||
1798 | } | ||
1657 | if (rdev->desc->ops->get_voltage) | 1799 | if (rdev->desc->ops->get_voltage) |
1658 | return rdev->desc->ops->get_voltage(rdev); | 1800 | return rdev->desc->ops->get_voltage(rdev); |
1659 | else | 1801 | else |
@@ -1880,21 +2022,20 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
1880 | goto out; | 2022 | goto out; |
1881 | 2023 | ||
1882 | /* get output voltage */ | 2024 | /* get output voltage */ |
1883 | output_uV = rdev->desc->ops->get_voltage(rdev); | 2025 | output_uV = _regulator_get_voltage(rdev); |
1884 | if (output_uV <= 0) { | 2026 | if (output_uV <= 0) { |
1885 | printk(KERN_ERR "%s: invalid output voltage found for %s\n", | 2027 | rdev_err(rdev, "invalid output voltage found\n"); |
1886 | __func__, rdev_get_name(rdev)); | ||
1887 | goto out; | 2028 | goto out; |
1888 | } | 2029 | } |
1889 | 2030 | ||
1890 | /* get input voltage */ | 2031 | /* get input voltage */ |
1891 | if (rdev->supply && rdev->supply->desc->ops->get_voltage) | 2032 | input_uV = 0; |
1892 | input_uV = rdev->supply->desc->ops->get_voltage(rdev->supply); | 2033 | if (rdev->supply) |
1893 | else | 2034 | input_uV = _regulator_get_voltage(rdev->supply); |
2035 | if (input_uV <= 0) | ||
1894 | input_uV = rdev->constraints->input_uV; | 2036 | input_uV = rdev->constraints->input_uV; |
1895 | if (input_uV <= 0) { | 2037 | if (input_uV <= 0) { |
1896 | printk(KERN_ERR "%s: invalid input voltage found for %s\n", | 2038 | rdev_err(rdev, "invalid input voltage found\n"); |
1897 | __func__, rdev_get_name(rdev)); | ||
1898 | goto out; | 2039 | goto out; |
1899 | } | 2040 | } |
1900 | 2041 | ||
@@ -1907,16 +2048,14 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) | |||
1907 | total_uA_load); | 2048 | total_uA_load); |
1908 | ret = regulator_check_mode(rdev, mode); | 2049 | ret = regulator_check_mode(rdev, mode); |
1909 | if (ret < 0) { | 2050 | if (ret < 0) { |
1910 | printk(KERN_ERR "%s: failed to get optimum mode for %s @" | 2051 | rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", |
1911 | " %d uA %d -> %d uV\n", __func__, rdev_get_name(rdev), | 2052 | total_uA_load, input_uV, output_uV); |
1912 | total_uA_load, input_uV, output_uV); | ||
1913 | goto out; | 2053 | goto out; |
1914 | } | 2054 | } |
1915 | 2055 | ||
1916 | ret = rdev->desc->ops->set_mode(rdev, mode); | 2056 | ret = rdev->desc->ops->set_mode(rdev, mode); |
1917 | if (ret < 0) { | 2057 | if (ret < 0) { |
1918 | printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n", | 2058 | rdev_err(rdev, "failed to set optimum mode %x\n", mode); |
1919 | __func__, mode, rdev_get_name(rdev)); | ||
1920 | goto out; | 2059 | goto out; |
1921 | } | 2060 | } |
1922 | ret = mode; | 2061 | ret = mode; |
@@ -2047,7 +2186,7 @@ int regulator_bulk_enable(int num_consumers, | |||
2047 | return 0; | 2186 | return 0; |
2048 | 2187 | ||
2049 | err: | 2188 | err: |
2050 | printk(KERN_ERR "Failed to enable %s: %d\n", consumers[i].supply, ret); | 2189 | pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); |
2051 | for (--i; i >= 0; --i) | 2190 | for (--i; i >= 0; --i) |
2052 | regulator_disable(consumers[i].consumer); | 2191 | regulator_disable(consumers[i].consumer); |
2053 | 2192 | ||
@@ -2082,8 +2221,7 @@ int regulator_bulk_disable(int num_consumers, | |||
2082 | return 0; | 2221 | return 0; |
2083 | 2222 | ||
2084 | err: | 2223 | err: |
2085 | printk(KERN_ERR "Failed to disable %s: %d\n", consumers[i].supply, | 2224 | pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); |
2086 | ret); | ||
2087 | for (--i; i >= 0; --i) | 2225 | for (--i; i >= 0; --i) |
2088 | regulator_enable(consumers[i].consumer); | 2226 | regulator_enable(consumers[i].consumer); |
2089 | 2227 | ||
@@ -2166,7 +2304,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
2166 | int status = 0; | 2304 | int status = 0; |
2167 | 2305 | ||
2168 | /* some attributes need specific methods to be displayed */ | 2306 | /* some attributes need specific methods to be displayed */ |
2169 | if (ops->get_voltage) { | 2307 | if (ops->get_voltage || ops->get_voltage_sel) { |
2170 | status = device_create_file(dev, &dev_attr_microvolts); | 2308 | status = device_create_file(dev, &dev_attr_microvolts); |
2171 | if (status < 0) | 2309 | if (status < 0) |
2172 | return status; | 2310 | return status; |
@@ -2207,7 +2345,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
2207 | return status; | 2345 | return status; |
2208 | 2346 | ||
2209 | /* constraints need specific supporting methods */ | 2347 | /* constraints need specific supporting methods */ |
2210 | if (ops->set_voltage) { | 2348 | if (ops->set_voltage || ops->set_voltage_sel) { |
2211 | status = device_create_file(dev, &dev_attr_min_microvolts); | 2349 | status = device_create_file(dev, &dev_attr_min_microvolts); |
2212 | if (status < 0) | 2350 | if (status < 0) |
2213 | return status; | 2351 | return status; |
@@ -2271,6 +2409,23 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
2271 | return status; | 2409 | return status; |
2272 | } | 2410 | } |
2273 | 2411 | ||
2412 | static void rdev_init_debugfs(struct regulator_dev *rdev) | ||
2413 | { | ||
2414 | #ifdef CONFIG_DEBUG_FS | ||
2415 | rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); | ||
2416 | if (IS_ERR(rdev->debugfs) || !rdev->debugfs) { | ||
2417 | rdev_warn(rdev, "Failed to create debugfs directory\n"); | ||
2418 | rdev->debugfs = NULL; | ||
2419 | return; | ||
2420 | } | ||
2421 | |||
2422 | debugfs_create_u32("use_count", 0444, rdev->debugfs, | ||
2423 | &rdev->use_count); | ||
2424 | debugfs_create_u32("open_count", 0444, rdev->debugfs, | ||
2425 | &rdev->open_count); | ||
2426 | #endif | ||
2427 | } | ||
2428 | |||
2274 | /** | 2429 | /** |
2275 | * regulator_register - register regulator | 2430 | * regulator_register - register regulator |
2276 | * @regulator_desc: regulator to register | 2431 | * @regulator_desc: regulator to register |
@@ -2282,7 +2437,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
2282 | * Returns 0 on success. | 2437 | * Returns 0 on success. |
2283 | */ | 2438 | */ |
2284 | struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | 2439 | struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, |
2285 | struct device *dev, struct regulator_init_data *init_data, | 2440 | struct device *dev, const struct regulator_init_data *init_data, |
2286 | void *driver_data) | 2441 | void *driver_data) |
2287 | { | 2442 | { |
2288 | static atomic_t regulator_no = ATOMIC_INIT(0); | 2443 | static atomic_t regulator_no = ATOMIC_INIT(0); |
@@ -2302,6 +2457,22 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2302 | if (!init_data) | 2457 | if (!init_data) |
2303 | return ERR_PTR(-EINVAL); | 2458 | return ERR_PTR(-EINVAL); |
2304 | 2459 | ||
2460 | /* Only one of each should be implemented */ | ||
2461 | WARN_ON(regulator_desc->ops->get_voltage && | ||
2462 | regulator_desc->ops->get_voltage_sel); | ||
2463 | WARN_ON(regulator_desc->ops->set_voltage && | ||
2464 | regulator_desc->ops->set_voltage_sel); | ||
2465 | |||
2466 | /* If we're using selectors we must implement list_voltage. */ | ||
2467 | if (regulator_desc->ops->get_voltage_sel && | ||
2468 | !regulator_desc->ops->list_voltage) { | ||
2469 | return ERR_PTR(-EINVAL); | ||
2470 | } | ||
2471 | if (regulator_desc->ops->set_voltage_sel && | ||
2472 | !regulator_desc->ops->list_voltage) { | ||
2473 | return ERR_PTR(-EINVAL); | ||
2474 | } | ||
2475 | |||
2305 | rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); | 2476 | rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); |
2306 | if (rdev == NULL) | 2477 | if (rdev == NULL) |
2307 | return ERR_PTR(-ENOMEM); | 2478 | return ERR_PTR(-ENOMEM); |
@@ -2399,6 +2570,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2399 | } | 2570 | } |
2400 | 2571 | ||
2401 | list_add(&rdev->list, ®ulator_list); | 2572 | list_add(&rdev->list, ®ulator_list); |
2573 | |||
2574 | rdev_init_debugfs(rdev); | ||
2402 | out: | 2575 | out: |
2403 | mutex_unlock(®ulator_list_mutex); | 2576 | mutex_unlock(®ulator_list_mutex); |
2404 | return rdev; | 2577 | return rdev; |
@@ -2431,12 +2604,16 @@ void regulator_unregister(struct regulator_dev *rdev) | |||
2431 | return; | 2604 | return; |
2432 | 2605 | ||
2433 | mutex_lock(®ulator_list_mutex); | 2606 | mutex_lock(®ulator_list_mutex); |
2607 | #ifdef CONFIG_DEBUG_FS | ||
2608 | debugfs_remove_recursive(rdev->debugfs); | ||
2609 | #endif | ||
2434 | WARN_ON(rdev->open_count); | 2610 | WARN_ON(rdev->open_count); |
2435 | unset_regulator_supplies(rdev); | 2611 | unset_regulator_supplies(rdev); |
2436 | list_del(&rdev->list); | 2612 | list_del(&rdev->list); |
2437 | if (rdev->supply) | 2613 | if (rdev->supply) |
2438 | sysfs_remove_link(&rdev->dev.kobj, "supply"); | 2614 | sysfs_remove_link(&rdev->dev.kobj, "supply"); |
2439 | device_unregister(&rdev->dev); | 2615 | device_unregister(&rdev->dev); |
2616 | kfree(rdev->constraints); | ||
2440 | mutex_unlock(®ulator_list_mutex); | 2617 | mutex_unlock(®ulator_list_mutex); |
2441 | } | 2618 | } |
2442 | EXPORT_SYMBOL_GPL(regulator_unregister); | 2619 | EXPORT_SYMBOL_GPL(regulator_unregister); |
@@ -2465,8 +2642,7 @@ int regulator_suspend_prepare(suspend_state_t state) | |||
2465 | mutex_unlock(&rdev->mutex); | 2642 | mutex_unlock(&rdev->mutex); |
2466 | 2643 | ||
2467 | if (ret < 0) { | 2644 | if (ret < 0) { |
2468 | printk(KERN_ERR "%s: failed to prepare %s\n", | 2645 | rdev_err(rdev, "failed to prepare\n"); |
2469 | __func__, rdev_get_name(rdev)); | ||
2470 | goto out; | 2646 | goto out; |
2471 | } | 2647 | } |
2472 | } | 2648 | } |
@@ -2572,10 +2748,16 @@ static int __init regulator_init(void) | |||
2572 | { | 2748 | { |
2573 | int ret; | 2749 | int ret; |
2574 | 2750 | ||
2575 | printk(KERN_INFO "regulator: core version %s\n", REGULATOR_VERSION); | ||
2576 | |||
2577 | ret = class_register(®ulator_class); | 2751 | ret = class_register(®ulator_class); |
2578 | 2752 | ||
2753 | #ifdef CONFIG_DEBUG_FS | ||
2754 | debugfs_root = debugfs_create_dir("regulator", NULL); | ||
2755 | if (IS_ERR(debugfs_root) || !debugfs_root) { | ||
2756 | pr_warn("regulator: Failed to create debugfs directory\n"); | ||
2757 | debugfs_root = NULL; | ||
2758 | } | ||
2759 | #endif | ||
2760 | |||
2579 | regulator_dummy_init(); | 2761 | regulator_dummy_init(); |
2580 | 2762 | ||
2581 | return ret; | 2763 | return ret; |
@@ -2590,7 +2772,6 @@ static int __init regulator_init_complete(void) | |||
2590 | struct regulator_ops *ops; | 2772 | struct regulator_ops *ops; |
2591 | struct regulation_constraints *c; | 2773 | struct regulation_constraints *c; |
2592 | int enabled, ret; | 2774 | int enabled, ret; |
2593 | const char *name; | ||
2594 | 2775 | ||
2595 | mutex_lock(®ulator_list_mutex); | 2776 | mutex_lock(®ulator_list_mutex); |
2596 | 2777 | ||
@@ -2602,8 +2783,6 @@ static int __init regulator_init_complete(void) | |||
2602 | ops = rdev->desc->ops; | 2783 | ops = rdev->desc->ops; |
2603 | c = rdev->constraints; | 2784 | c = rdev->constraints; |
2604 | 2785 | ||
2605 | name = rdev_get_name(rdev); | ||
2606 | |||
2607 | if (!ops->disable || (c && c->always_on)) | 2786 | if (!ops->disable || (c && c->always_on)) |
2608 | continue; | 2787 | continue; |
2609 | 2788 | ||
@@ -2624,13 +2803,10 @@ static int __init regulator_init_complete(void) | |||
2624 | if (has_full_constraints) { | 2803 | if (has_full_constraints) { |
2625 | /* We log since this may kill the system if it | 2804 | /* We log since this may kill the system if it |
2626 | * goes wrong. */ | 2805 | * goes wrong. */ |
2627 | printk(KERN_INFO "%s: disabling %s\n", | 2806 | rdev_info(rdev, "disabling\n"); |
2628 | __func__, name); | ||
2629 | ret = ops->disable(rdev); | 2807 | ret = ops->disable(rdev); |
2630 | if (ret != 0) { | 2808 | if (ret != 0) { |
2631 | printk(KERN_ERR | 2809 | rdev_err(rdev, "couldn't disable: %d\n", ret); |
2632 | "%s: couldn't disable %s: %d\n", | ||
2633 | __func__, name, ret); | ||
2634 | } | 2810 | } |
2635 | } else { | 2811 | } else { |
2636 | /* The intention is that in future we will | 2812 | /* The intention is that in future we will |
@@ -2638,9 +2814,7 @@ static int __init regulator_init_complete(void) | |||
2638 | * so warn even if we aren't going to do | 2814 | * so warn even if we aren't going to do |
2639 | * anything here. | 2815 | * anything here. |
2640 | */ | 2816 | */ |
2641 | printk(KERN_WARNING | 2817 | rdev_warn(rdev, "incomplete constraints, leaving on\n"); |
2642 | "%s: incomplete constraints, leaving %s on\n", | ||
2643 | __func__, name); | ||
2644 | } | 2818 | } |
2645 | 2819 | ||
2646 | unlock: | 2820 | unlock: |
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index f8c4661a7a81..362e08221085 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c | |||
@@ -107,7 +107,7 @@ static inline int check_range(struct da903x_regulator_info *info, | |||
107 | 107 | ||
108 | /* DA9030/DA9034 common operations */ | 108 | /* DA9030/DA9034 common operations */ |
109 | static int da903x_set_ldo_voltage(struct regulator_dev *rdev, | 109 | static int da903x_set_ldo_voltage(struct regulator_dev *rdev, |
110 | int min_uV, int max_uV) | 110 | int min_uV, int max_uV, unsigned *selector) |
111 | { | 111 | { |
112 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | 112 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); |
113 | struct device *da9034_dev = to_da903x_dev(rdev); | 113 | struct device *da9034_dev = to_da903x_dev(rdev); |
@@ -119,6 +119,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev, | |||
119 | } | 119 | } |
120 | 120 | ||
121 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; | 121 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; |
122 | *selector = val; | ||
122 | val <<= info->vol_shift; | 123 | val <<= info->vol_shift; |
123 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 124 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
124 | 125 | ||
@@ -187,7 +188,8 @@ static int da903x_list_voltage(struct regulator_dev *rdev, unsigned selector) | |||
187 | 188 | ||
188 | /* DA9030 specific operations */ | 189 | /* DA9030 specific operations */ |
189 | static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, | 190 | static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, |
190 | int min_uV, int max_uV) | 191 | int min_uV, int max_uV, |
192 | unsigned *selector) | ||
191 | { | 193 | { |
192 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | 194 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); |
193 | struct device *da903x_dev = to_da903x_dev(rdev); | 195 | struct device *da903x_dev = to_da903x_dev(rdev); |
@@ -200,6 +202,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, | |||
200 | } | 202 | } |
201 | 203 | ||
202 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; | 204 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; |
205 | *selector = val; | ||
203 | val <<= info->vol_shift; | 206 | val <<= info->vol_shift; |
204 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 207 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
205 | val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */ | 208 | val |= DA9030_LDO_UNLOCK; /* have to set UNLOCK bits */ |
@@ -214,7 +217,8 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, | |||
214 | } | 217 | } |
215 | 218 | ||
216 | static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, | 219 | static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, |
217 | int min_uV, int max_uV) | 220 | int min_uV, int max_uV, |
221 | unsigned *selector) | ||
218 | { | 222 | { |
219 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | 223 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); |
220 | struct device *da903x_dev = to_da903x_dev(rdev); | 224 | struct device *da903x_dev = to_da903x_dev(rdev); |
@@ -234,6 +238,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, | |||
234 | val = (min_uV - thresh + info->step_uV - 1) / info->step_uV; | 238 | val = (min_uV - thresh + info->step_uV - 1) / info->step_uV; |
235 | } | 239 | } |
236 | 240 | ||
241 | *selector = val; | ||
237 | val <<= info->vol_shift; | 242 | val <<= info->vol_shift; |
238 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 243 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
239 | 244 | ||
@@ -263,7 +268,7 @@ static int da9030_get_ldo14_voltage(struct regulator_dev *rdev) | |||
263 | 268 | ||
264 | /* DA9034 specific operations */ | 269 | /* DA9034 specific operations */ |
265 | static int da9034_set_dvc_voltage(struct regulator_dev *rdev, | 270 | static int da9034_set_dvc_voltage(struct regulator_dev *rdev, |
266 | int min_uV, int max_uV) | 271 | int min_uV, int max_uV, unsigned *selector) |
267 | { | 272 | { |
268 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | 273 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); |
269 | struct device *da9034_dev = to_da903x_dev(rdev); | 274 | struct device *da9034_dev = to_da903x_dev(rdev); |
@@ -276,6 +281,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, | |||
276 | } | 281 | } |
277 | 282 | ||
278 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; | 283 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; |
284 | *selector = val; | ||
279 | val <<= info->vol_shift; | 285 | val <<= info->vol_shift; |
280 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 286 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
281 | 287 | ||
@@ -289,7 +295,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, | |||
289 | } | 295 | } |
290 | 296 | ||
291 | static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, | 297 | static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, |
292 | int min_uV, int max_uV) | 298 | int min_uV, int max_uV, unsigned *selector) |
293 | { | 299 | { |
294 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | 300 | struct da903x_regulator_info *info = rdev_get_drvdata(rdev); |
295 | struct device *da9034_dev = to_da903x_dev(rdev); | 301 | struct device *da9034_dev = to_da903x_dev(rdev); |
@@ -302,6 +308,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, | |||
302 | 308 | ||
303 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; | 309 | val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; |
304 | val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val); | 310 | val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val); |
311 | *selector = val; | ||
305 | val <<= info->vol_shift; | 312 | val <<= info->vol_shift; |
306 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 313 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
307 | 314 | ||
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index b8cc6389a541..e4b3592e8176 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c | |||
@@ -58,7 +58,9 @@ out: | |||
58 | return data; | 58 | return data; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV) | 61 | static int isl6271a_set_voltage(struct regulator_dev *dev, |
62 | int minuV, int maxuV, | ||
63 | unsigned *selector) | ||
62 | { | 64 | { |
63 | struct isl_pmic *pmic = rdev_get_drvdata(dev); | 65 | struct isl_pmic *pmic = rdev_get_drvdata(dev); |
64 | int vsel, err, data; | 66 | int vsel, err, data; |
@@ -78,6 +80,8 @@ static int isl6271a_set_voltage(struct regulator_dev *dev, int minuV, int maxuV) | |||
78 | /* Convert the microvolts to data for the chip */ | 80 | /* Convert the microvolts to data for the chip */ |
79 | data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP; | 81 | data = (vsel - ISL6271A_VOLTAGE_MIN) / ISL6271A_VOLTAGE_STEP; |
80 | 82 | ||
83 | *selector = data; | ||
84 | |||
81 | mutex_lock(&pmic->mtx); | 85 | mutex_lock(&pmic->mtx); |
82 | 86 | ||
83 | err = i2c_smbus_write_byte(pmic->client, data); | 87 | err = i2c_smbus_write_byte(pmic->client, data); |
@@ -169,7 +173,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, | |||
169 | init_data, pmic); | 173 | init_data, pmic); |
170 | if (IS_ERR(pmic->rdev[i])) { | 174 | if (IS_ERR(pmic->rdev[i])) { |
171 | dev_err(&i2c->dev, "failed to register %s\n", id->name); | 175 | dev_err(&i2c->dev, "failed to register %s\n", id->name); |
172 | err = PTR_ERR(pmic->rdev); | 176 | err = PTR_ERR(pmic->rdev[i]); |
173 | goto error; | 177 | goto error; |
174 | } | 178 | } |
175 | } | 179 | } |
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 3bb82b624e19..0f22ef12601c 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c | |||
@@ -168,7 +168,8 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev) | |||
168 | } | 168 | } |
169 | 169 | ||
170 | static int lp3971_ldo_set_voltage(struct regulator_dev *dev, | 170 | static int lp3971_ldo_set_voltage(struct regulator_dev *dev, |
171 | int min_uV, int max_uV) | 171 | int min_uV, int max_uV, |
172 | unsigned int *selector) | ||
172 | { | 173 | { |
173 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | 174 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); |
174 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | 175 | int ldo = rdev_get_id(dev) - LP3971_LDO1; |
@@ -187,6 +188,8 @@ static int lp3971_ldo_set_voltage(struct regulator_dev *dev, | |||
187 | if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol) | 188 | if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol) |
188 | return -EINVAL; | 189 | return -EINVAL; |
189 | 190 | ||
191 | *selector = val; | ||
192 | |||
190 | return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo), | 193 | return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo), |
191 | LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), | 194 | LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), |
192 | val << LDO_VOL_CONTR_SHIFT(ldo)); | 195 | val << LDO_VOL_CONTR_SHIFT(ldo)); |
@@ -256,7 +259,8 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) | |||
256 | } | 259 | } |
257 | 260 | ||
258 | static int lp3971_dcdc_set_voltage(struct regulator_dev *dev, | 261 | static int lp3971_dcdc_set_voltage(struct regulator_dev *dev, |
259 | int min_uV, int max_uV) | 262 | int min_uV, int max_uV, |
263 | unsigned int *selector) | ||
260 | { | 264 | { |
261 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | 265 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); |
262 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | 266 | int buck = rdev_get_id(dev) - LP3971_DCDC1; |
@@ -277,6 +281,8 @@ static int lp3971_dcdc_set_voltage(struct regulator_dev *dev, | |||
277 | if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol) | 281 | if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol) |
278 | return -EINVAL; | 282 | return -EINVAL; |
279 | 283 | ||
284 | *selector = val; | ||
285 | |||
280 | ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), | 286 | ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), |
281 | BUCK_TARGET_VOL_MASK, val); | 287 | BUCK_TARGET_VOL_MASK, val); |
282 | if (ret) | 288 | if (ret) |
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index e07062fd0b42..6aa1b506fb5d 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c | |||
@@ -292,7 +292,8 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev) | |||
292 | } | 292 | } |
293 | 293 | ||
294 | static int lp3972_ldo_set_voltage(struct regulator_dev *dev, | 294 | static int lp3972_ldo_set_voltage(struct regulator_dev *dev, |
295 | int min_uV, int max_uV) | 295 | int min_uV, int max_uV, |
296 | unsigned int *selector) | ||
296 | { | 297 | { |
297 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); | 298 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); |
298 | int ldo = rdev_get_id(dev) - LP3972_LDO1; | 299 | int ldo = rdev_get_id(dev) - LP3972_LDO1; |
@@ -313,6 +314,8 @@ static int lp3972_ldo_set_voltage(struct regulator_dev *dev, | |||
313 | if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol) | 314 | if (val > LP3972_LDO_VOL_MAX_IDX(ldo) || vol_map[val] > max_vol) |
314 | return -EINVAL; | 315 | return -EINVAL; |
315 | 316 | ||
317 | *selector = val; | ||
318 | |||
316 | shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo); | 319 | shift = LP3972_LDO_VOL_CONTR_SHIFT(ldo); |
317 | ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo), | 320 | ret = lp3972_set_bits(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo), |
318 | LP3972_LDO_VOL_MASK(ldo) << shift, val << shift); | 321 | LP3972_LDO_VOL_MASK(ldo) << shift, val << shift); |
@@ -416,7 +419,8 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev) | |||
416 | } | 419 | } |
417 | 420 | ||
418 | static int lp3972_dcdc_set_voltage(struct regulator_dev *dev, | 421 | static int lp3972_dcdc_set_voltage(struct regulator_dev *dev, |
419 | int min_uV, int max_uV) | 422 | int min_uV, int max_uV, |
423 | unsigned int *selector) | ||
420 | { | 424 | { |
421 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); | 425 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); |
422 | int buck = rdev_get_id(dev) - LP3972_DCDC1; | 426 | int buck = rdev_get_id(dev) - LP3972_DCDC1; |
@@ -438,6 +442,8 @@ static int lp3972_dcdc_set_voltage(struct regulator_dev *dev, | |||
438 | vol_map[val] > max_vol) | 442 | vol_map[val] > max_vol) |
439 | return -EINVAL; | 443 | return -EINVAL; |
440 | 444 | ||
445 | *selector = val; | ||
446 | |||
441 | ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck), | 447 | ret = lp3972_set_bits(lp3972, LP3972_BUCK_VOL1_REG(buck), |
442 | LP3972_BUCK_VOL_MASK, val); | 448 | LP3972_BUCK_VOL_MASK, val); |
443 | if (ret) | 449 | if (ret) |
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 559cfa271a44..3f49512c5134 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c | |||
@@ -63,12 +63,12 @@ static int max1586_v3_calc_voltage(struct max1586_data *max1586, | |||
63 | return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL); | 63 | return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL); |
64 | } | 64 | } |
65 | 65 | ||
66 | static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV) | 66 | static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV, |
67 | unsigned *selector) | ||
67 | { | 68 | { |
68 | struct max1586_data *max1586 = rdev_get_drvdata(rdev); | 69 | struct max1586_data *max1586 = rdev_get_drvdata(rdev); |
69 | struct i2c_client *client = max1586->client; | 70 | struct i2c_client *client = max1586->client; |
70 | unsigned range_uV = max1586->max_uV - max1586->min_uV; | 71 | unsigned range_uV = max1586->max_uV - max1586->min_uV; |
71 | unsigned selector; | ||
72 | u8 v3_prog; | 72 | u8 v3_prog; |
73 | 73 | ||
74 | if (min_uV > max1586->max_uV || max_uV < max1586->min_uV) | 74 | if (min_uV > max1586->max_uV || max_uV < max1586->min_uV) |
@@ -76,15 +76,15 @@ static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
76 | if (min_uV < max1586->min_uV) | 76 | if (min_uV < max1586->min_uV) |
77 | min_uV = max1586->min_uV; | 77 | min_uV = max1586->min_uV; |
78 | 78 | ||
79 | selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL + | 79 | *selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL + |
80 | range_uV - 1) / range_uV; | 80 | range_uV - 1) / range_uV; |
81 | if (max1586_v3_calc_voltage(max1586, selector) > max_uV) | 81 | if (max1586_v3_calc_voltage(max1586, *selector) > max_uV) |
82 | return -EINVAL; | 82 | return -EINVAL; |
83 | 83 | ||
84 | dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", | 84 | dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", |
85 | max1586_v3_calc_voltage(max1586, selector) / 1000); | 85 | max1586_v3_calc_voltage(max1586, *selector) / 1000); |
86 | 86 | ||
87 | v3_prog = I2C_V3_SELECT | (u8) selector; | 87 | v3_prog = I2C_V3_SELECT | (u8) *selector; |
88 | return i2c_smbus_write_byte(client, v3_prog); | 88 | return i2c_smbus_write_byte(client, v3_prog); |
89 | } | 89 | } |
90 | 90 | ||
@@ -110,10 +110,10 @@ static int max1586_v6_calc_voltage(unsigned selector) | |||
110 | return voltages_uv[selector]; | 110 | return voltages_uv[selector]; |
111 | } | 111 | } |
112 | 112 | ||
113 | static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) | 113 | static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV, |
114 | unsigned int *selector) | ||
114 | { | 115 | { |
115 | struct i2c_client *client = rdev_get_drvdata(rdev); | 116 | struct i2c_client *client = rdev_get_drvdata(rdev); |
116 | unsigned selector; | ||
117 | u8 v6_prog; | 117 | u8 v6_prog; |
118 | 118 | ||
119 | if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV) | 119 | if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV) |
@@ -122,21 +122,21 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
122 | return -EINVAL; | 122 | return -EINVAL; |
123 | 123 | ||
124 | if (min_uV < 1800000) | 124 | if (min_uV < 1800000) |
125 | selector = 0; | 125 | *selector = 0; |
126 | else if (min_uV < 2500000) | 126 | else if (min_uV < 2500000) |
127 | selector = 1; | 127 | *selector = 1; |
128 | else if (min_uV < 3000000) | 128 | else if (min_uV < 3000000) |
129 | selector = 2; | 129 | *selector = 2; |
130 | else if (min_uV >= 3000000) | 130 | else if (min_uV >= 3000000) |
131 | selector = 3; | 131 | *selector = 3; |
132 | 132 | ||
133 | if (max1586_v6_calc_voltage(selector) > max_uV) | 133 | if (max1586_v6_calc_voltage(*selector) > max_uV) |
134 | return -EINVAL; | 134 | return -EINVAL; |
135 | 135 | ||
136 | dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", | 136 | dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", |
137 | max1586_v6_calc_voltage(selector) / 1000); | 137 | max1586_v6_calc_voltage(*selector) / 1000); |
138 | 138 | ||
139 | v6_prog = I2C_V6_SELECT | (u8) selector; | 139 | v6_prog = I2C_V6_SELECT | (u8) *selector; |
140 | return i2c_smbus_write_byte(client, v6_prog); | 140 | return i2c_smbus_write_byte(client, v6_prog); |
141 | } | 141 | } |
142 | 142 | ||
diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 6b60a9c0366b..30eb9e54f7ec 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c | |||
@@ -155,7 +155,7 @@ static int max8649_get_voltage(struct regulator_dev *rdev) | |||
155 | } | 155 | } |
156 | 156 | ||
157 | static int max8649_set_voltage(struct regulator_dev *rdev, | 157 | static int max8649_set_voltage(struct regulator_dev *rdev, |
158 | int min_uV, int max_uV) | 158 | int min_uV, int max_uV, unsigned *selector) |
159 | { | 159 | { |
160 | struct max8649_regulator_info *info = rdev_get_drvdata(rdev); | 160 | struct max8649_regulator_info *info = rdev_get_drvdata(rdev); |
161 | unsigned char data, mask; | 161 | unsigned char data, mask; |
@@ -168,6 +168,7 @@ static int max8649_set_voltage(struct regulator_dev *rdev, | |||
168 | data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1) | 168 | data = (min_uV - MAX8649_DCDC_VMIN + MAX8649_DCDC_STEP - 1) |
169 | / MAX8649_DCDC_STEP; | 169 | / MAX8649_DCDC_STEP; |
170 | mask = MAX8649_VOL_MASK; | 170 | mask = MAX8649_VOL_MASK; |
171 | *selector = data & mask; | ||
171 | 172 | ||
172 | return max8649_set_bits(info->i2c, info->vol_reg, mask, data); | 173 | return max8649_set_bits(info->i2c, info->vol_reg, mask, data); |
173 | } | 174 | } |
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index c570e6eb0db2..33f5d9a492ef 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c | |||
@@ -141,7 +141,8 @@ static int max8660_dcdc_get(struct regulator_dev *rdev) | |||
141 | return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; | 141 | return MAX8660_DCDC_MIN_UV + selector * MAX8660_DCDC_STEP; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV) | 144 | static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV, |
145 | unsigned int *s) | ||
145 | { | 146 | { |
146 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | 147 | struct max8660 *max8660 = rdev_get_drvdata(rdev); |
147 | u8 reg, selector, bits; | 148 | u8 reg, selector, bits; |
@@ -154,6 +155,7 @@ static int max8660_dcdc_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
154 | 155 | ||
155 | selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1)) | 156 | selector = (min_uV - (MAX8660_DCDC_MIN_UV - MAX8660_DCDC_STEP + 1)) |
156 | / MAX8660_DCDC_STEP; | 157 | / MAX8660_DCDC_STEP; |
158 | *s = selector; | ||
157 | 159 | ||
158 | ret = max8660_dcdc_list(rdev, selector); | 160 | ret = max8660_dcdc_list(rdev, selector); |
159 | if (ret < 0 || ret > max_uV) | 161 | if (ret < 0 || ret > max_uV) |
@@ -196,7 +198,8 @@ static int max8660_ldo5_get(struct regulator_dev *rdev) | |||
196 | return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; | 198 | return MAX8660_LDO5_MIN_UV + selector * MAX8660_LDO5_STEP; |
197 | } | 199 | } |
198 | 200 | ||
199 | static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV) | 201 | static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV, |
202 | unsigned int *s) | ||
200 | { | 203 | { |
201 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | 204 | struct max8660 *max8660 = rdev_get_drvdata(rdev); |
202 | u8 selector; | 205 | u8 selector; |
@@ -213,6 +216,8 @@ static int max8660_ldo5_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
213 | if (ret < 0 || ret > max_uV) | 216 | if (ret < 0 || ret > max_uV) |
214 | return -EINVAL; | 217 | return -EINVAL; |
215 | 218 | ||
219 | *s = selector; | ||
220 | |||
216 | ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector); | 221 | ret = max8660_write(max8660, MAX8660_MDTV2, 0, selector); |
217 | if (ret) | 222 | if (ret) |
218 | return ret; | 223 | return ret; |
@@ -270,7 +275,8 @@ static int max8660_ldo67_get(struct regulator_dev *rdev) | |||
270 | return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; | 275 | return MAX8660_LDO67_MIN_UV + selector * MAX8660_LDO67_STEP; |
271 | } | 276 | } |
272 | 277 | ||
273 | static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV) | 278 | static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, |
279 | int max_uV, unsigned int *s) | ||
274 | { | 280 | { |
275 | struct max8660 *max8660 = rdev_get_drvdata(rdev); | 281 | struct max8660 *max8660 = rdev_get_drvdata(rdev); |
276 | u8 selector; | 282 | u8 selector; |
@@ -288,6 +294,8 @@ static int max8660_ldo67_set(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
288 | if (ret < 0 || ret > max_uV) | 294 | if (ret < 0 || ret > max_uV) |
289 | return -EINVAL; | 295 | return -EINVAL; |
290 | 296 | ||
297 | *s = selector; | ||
298 | |||
291 | if (rdev_get_id(rdev) == MAX8660_V6) | 299 | if (rdev_get_id(rdev) == MAX8660_V6) |
292 | return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector); | 300 | return max8660_write(max8660, MAX8660_L12VCR, 0xf0, selector); |
293 | else | 301 | else |
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 552cad85ae5a..8ae147549c6a 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c | |||
@@ -55,7 +55,7 @@ static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | static int max8925_set_voltage(struct regulator_dev *rdev, | 57 | static int max8925_set_voltage(struct regulator_dev *rdev, |
58 | int min_uV, int max_uV) | 58 | int min_uV, int max_uV, unsigned int *selector) |
59 | { | 59 | { |
60 | struct max8925_regulator_info *info = rdev_get_drvdata(rdev); | 60 | struct max8925_regulator_info *info = rdev_get_drvdata(rdev); |
61 | unsigned char data, mask; | 61 | unsigned char data, mask; |
@@ -66,6 +66,7 @@ static int max8925_set_voltage(struct regulator_dev *rdev, | |||
66 | return -EINVAL; | 66 | return -EINVAL; |
67 | } | 67 | } |
68 | data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; | 68 | data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; |
69 | *selector = data; | ||
69 | data <<= info->vol_shift; | 70 | data <<= info->vol_shift; |
70 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; | 71 | mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; |
71 | 72 | ||
diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 0d5dda4fd911..a8f4ecfb0843 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c | |||
@@ -133,7 +133,7 @@ static int max8952_get_voltage(struct regulator_dev *rdev) | |||
133 | } | 133 | } |
134 | 134 | ||
135 | static int max8952_set_voltage(struct regulator_dev *rdev, | 135 | static int max8952_set_voltage(struct regulator_dev *rdev, |
136 | int min_uV, int max_uV) | 136 | int min_uV, int max_uV, unsigned *selector) |
137 | { | 137 | { |
138 | struct max8952_data *max8952 = rdev_get_drvdata(rdev); | 138 | struct max8952_data *max8952 = rdev_get_drvdata(rdev); |
139 | s8 vid = -1, i; | 139 | s8 vid = -1, i; |
@@ -156,6 +156,7 @@ static int max8952_set_voltage(struct regulator_dev *rdev, | |||
156 | if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) { | 156 | if (vid >= 0 && vid < MAX8952_NUM_DVS_MODE) { |
157 | max8952->vid0 = (vid % 2 == 1); | 157 | max8952->vid0 = (vid % 2 == 1); |
158 | max8952->vid1 = (((vid >> 1) % 2) == 1); | 158 | max8952->vid1 = (((vid >> 1) % 2) == 1); |
159 | *selector = vid; | ||
159 | gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); | 160 | gpio_set_value(max8952->pdata->gpio_vid0, max8952->vid0); |
160 | gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); | 161 | gpio_set_value(max8952->pdata->gpio_vid1, max8952->vid1); |
161 | } else | 162 | } else |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 5c20756db607..7568df6122ab 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
@@ -304,7 +304,7 @@ static int max8998_get_voltage(struct regulator_dev *rdev) | |||
304 | } | 304 | } |
305 | 305 | ||
306 | static int max8998_set_voltage_ldo(struct regulator_dev *rdev, | 306 | static int max8998_set_voltage_ldo(struct regulator_dev *rdev, |
307 | int min_uV, int max_uV) | 307 | int min_uV, int max_uV, unsigned *selector) |
308 | { | 308 | { |
309 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 309 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
310 | struct i2c_client *i2c = max8998->iodev->i2c; | 310 | struct i2c_client *i2c = max8998->iodev->i2c; |
@@ -331,6 +331,8 @@ static int max8998_set_voltage_ldo(struct regulator_dev *rdev, | |||
331 | if (desc->min + desc->step*i > max_vol) | 331 | if (desc->min + desc->step*i > max_vol) |
332 | return -EINVAL; | 332 | return -EINVAL; |
333 | 333 | ||
334 | *selector = i; | ||
335 | |||
334 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | 336 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); |
335 | if (ret) | 337 | if (ret) |
336 | return ret; | 338 | return ret; |
@@ -352,7 +354,7 @@ static inline void buck2_gpio_set(int gpio, int v) | |||
352 | } | 354 | } |
353 | 355 | ||
354 | static int max8998_set_voltage_buck(struct regulator_dev *rdev, | 356 | static int max8998_set_voltage_buck(struct regulator_dev *rdev, |
355 | int min_uV, int max_uV) | 357 | int min_uV, int max_uV, unsigned *selector) |
356 | { | 358 | { |
357 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); | 359 | struct max8998_data *max8998 = rdev_get_drvdata(rdev); |
358 | struct max8998_platform_data *pdata = | 360 | struct max8998_platform_data *pdata = |
@@ -384,6 +386,8 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev, | |||
384 | if (desc->min + desc->step*i > max_vol) | 386 | if (desc->min + desc->step*i > max_vol) |
385 | return -EINVAL; | 387 | return -EINVAL; |
386 | 388 | ||
389 | *selector = i; | ||
390 | |||
387 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | 391 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); |
388 | if (ret) | 392 | if (ret) |
389 | return ret; | 393 | return ret; |
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index ecd99f59dba8..3e5d0c3b4e53 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Regulator Driver for Freescale MC13783 PMIC | 2 | * Regulator Driver for Freescale MC13783 PMIC |
3 | * | 3 | * |
4 | * Copyright 2010 Yong Shen <yong.shen@linaro.org> | ||
4 | * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | 5 | * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> |
5 | * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> | 6 | * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> |
6 | * | 7 | * |
@@ -17,6 +18,7 @@ | |||
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include "mc13xxx.h" | ||
20 | 22 | ||
21 | #define MC13783_REG_SWITCHERS5 29 | 23 | #define MC13783_REG_SWITCHERS5 29 |
22 | #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) | 24 | #define MC13783_REG_SWITCHERS5_SW3EN (1 << 20) |
@@ -89,154 +91,106 @@ | |||
89 | #define MC13783_REG_POWERMISC_PWGTSPI_M (3 << 15) | 91 | #define MC13783_REG_POWERMISC_PWGTSPI_M (3 << 15) |
90 | 92 | ||
91 | 93 | ||
92 | struct mc13783_regulator { | ||
93 | struct regulator_desc desc; | ||
94 | int reg; | ||
95 | int enable_bit; | ||
96 | int vsel_reg; | ||
97 | int vsel_shift; | ||
98 | int vsel_mask; | ||
99 | int const *voltages; | ||
100 | }; | ||
101 | |||
102 | /* Voltage Values */ | 94 | /* Voltage Values */ |
103 | static const int const mc13783_sw3_val[] = { | 95 | static const int mc13783_sw3_val[] = { |
104 | 5000000, 5000000, 5000000, 5500000, | 96 | 5000000, 5000000, 5000000, 5500000, |
105 | }; | 97 | }; |
106 | 98 | ||
107 | static const int const mc13783_vaudio_val[] = { | 99 | static const int mc13783_vaudio_val[] = { |
108 | 2775000, | 100 | 2775000, |
109 | }; | 101 | }; |
110 | 102 | ||
111 | static const int const mc13783_viohi_val[] = { | 103 | static const int mc13783_viohi_val[] = { |
112 | 2775000, | 104 | 2775000, |
113 | }; | 105 | }; |
114 | 106 | ||
115 | static const int const mc13783_violo_val[] = { | 107 | static const int mc13783_violo_val[] = { |
116 | 1200000, 1300000, 1500000, 1800000, | 108 | 1200000, 1300000, 1500000, 1800000, |
117 | }; | 109 | }; |
118 | 110 | ||
119 | static const int const mc13783_vdig_val[] = { | 111 | static const int mc13783_vdig_val[] = { |
120 | 1200000, 1300000, 1500000, 1800000, | 112 | 1200000, 1300000, 1500000, 1800000, |
121 | }; | 113 | }; |
122 | 114 | ||
123 | static const int const mc13783_vgen_val[] = { | 115 | static const int mc13783_vgen_val[] = { |
124 | 1200000, 1300000, 1500000, 1800000, | 116 | 1200000, 1300000, 1500000, 1800000, |
125 | 1100000, 2000000, 2775000, 2400000, | 117 | 1100000, 2000000, 2775000, 2400000, |
126 | }; | 118 | }; |
127 | 119 | ||
128 | static const int const mc13783_vrfdig_val[] = { | 120 | static const int mc13783_vrfdig_val[] = { |
129 | 1200000, 1500000, 1800000, 1875000, | 121 | 1200000, 1500000, 1800000, 1875000, |
130 | }; | 122 | }; |
131 | 123 | ||
132 | static const int const mc13783_vrfref_val[] = { | 124 | static const int mc13783_vrfref_val[] = { |
133 | 2475000, 2600000, 2700000, 2775000, | 125 | 2475000, 2600000, 2700000, 2775000, |
134 | }; | 126 | }; |
135 | 127 | ||
136 | static const int const mc13783_vrfcp_val[] = { | 128 | static const int mc13783_vrfcp_val[] = { |
137 | 2700000, 2775000, | 129 | 2700000, 2775000, |
138 | }; | 130 | }; |
139 | 131 | ||
140 | static const int const mc13783_vsim_val[] = { | 132 | static const int mc13783_vsim_val[] = { |
141 | 1800000, 2900000, 3000000, | 133 | 1800000, 2900000, 3000000, |
142 | }; | 134 | }; |
143 | 135 | ||
144 | static const int const mc13783_vesim_val[] = { | 136 | static const int mc13783_vesim_val[] = { |
145 | 1800000, 2900000, | 137 | 1800000, 2900000, |
146 | }; | 138 | }; |
147 | 139 | ||
148 | static const int const mc13783_vcam_val[] = { | 140 | static const int mc13783_vcam_val[] = { |
149 | 1500000, 1800000, 2500000, 2550000, | 141 | 1500000, 1800000, 2500000, 2550000, |
150 | 2600000, 2750000, 2800000, 3000000, | 142 | 2600000, 2750000, 2800000, 3000000, |
151 | }; | 143 | }; |
152 | 144 | ||
153 | static const int const mc13783_vrfbg_val[] = { | 145 | static const int mc13783_vrfbg_val[] = { |
154 | 1250000, | 146 | 1250000, |
155 | }; | 147 | }; |
156 | 148 | ||
157 | static const int const mc13783_vvib_val[] = { | 149 | static const int mc13783_vvib_val[] = { |
158 | 1300000, 1800000, 2000000, 3000000, | 150 | 1300000, 1800000, 2000000, 3000000, |
159 | }; | 151 | }; |
160 | 152 | ||
161 | static const int const mc13783_vmmc_val[] = { | 153 | static const int mc13783_vmmc_val[] = { |
162 | 1600000, 1800000, 2000000, 2600000, | 154 | 1600000, 1800000, 2000000, 2600000, |
163 | 2700000, 2800000, 2900000, 3000000, | 155 | 2700000, 2800000, 2900000, 3000000, |
164 | }; | 156 | }; |
165 | 157 | ||
166 | static const int const mc13783_vrf_val[] = { | 158 | static const int mc13783_vrf_val[] = { |
167 | 1500000, 1875000, 2700000, 2775000, | 159 | 1500000, 1875000, 2700000, 2775000, |
168 | }; | 160 | }; |
169 | 161 | ||
170 | static const int const mc13783_gpo_val[] = { | 162 | static const int mc13783_gpo_val[] = { |
171 | 3100000, | 163 | 3100000, |
172 | }; | 164 | }; |
173 | 165 | ||
174 | static const int const mc13783_pwgtdrv_val[] = { | 166 | static const int mc13783_pwgtdrv_val[] = { |
175 | 5500000, | 167 | 5500000, |
176 | }; | 168 | }; |
177 | 169 | ||
178 | static struct regulator_ops mc13783_regulator_ops; | ||
179 | static struct regulator_ops mc13783_fixed_regulator_ops; | ||
180 | static struct regulator_ops mc13783_gpo_regulator_ops; | 170 | static struct regulator_ops mc13783_gpo_regulator_ops; |
181 | 171 | ||
182 | #define MC13783_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages) \ | 172 | #define MC13783_DEFINE(prefix, name, reg, vsel_reg, voltages) \ |
183 | [MC13783_ ## prefix ## _ ## _name] = { \ | 173 | MC13xxx_DEFINE(MC13783_REG_, name, reg, vsel_reg, voltages, \ |
184 | .desc = { \ | 174 | mc13xxx_regulator_ops) |
185 | .name = #prefix "_" #_name, \ | ||
186 | .n_voltages = ARRAY_SIZE(_voltages), \ | ||
187 | .ops = &mc13783_regulator_ops, \ | ||
188 | .type = REGULATOR_VOLTAGE, \ | ||
189 | .id = MC13783_ ## prefix ## _ ## _name, \ | ||
190 | .owner = THIS_MODULE, \ | ||
191 | }, \ | ||
192 | .reg = MC13783_REG_ ## _reg, \ | ||
193 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | ||
194 | .vsel_reg = MC13783_REG_ ## _vsel_reg, \ | ||
195 | .vsel_shift = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL,\ | ||
196 | .vsel_mask = MC13783_REG_ ## _vsel_reg ## _ ## _name ## VSEL_M,\ | ||
197 | .voltages = _voltages, \ | ||
198 | } | ||
199 | 175 | ||
200 | #define MC13783_FIXED_DEFINE(prefix, _name, _reg, _voltages) \ | 176 | #define MC13783_FIXED_DEFINE(prefix, name, reg, voltages) \ |
201 | [MC13783_ ## prefix ## _ ## _name] = { \ | 177 | MC13xxx_FIXED_DEFINE(MC13783_REG_, name, reg, voltages, \ |
202 | .desc = { \ | 178 | mc13xxx_fixed_regulator_ops) |
203 | .name = #prefix "_" #_name, \ | ||
204 | .n_voltages = ARRAY_SIZE(_voltages), \ | ||
205 | .ops = &mc13783_fixed_regulator_ops, \ | ||
206 | .type = REGULATOR_VOLTAGE, \ | ||
207 | .id = MC13783_ ## prefix ## _ ## _name, \ | ||
208 | .owner = THIS_MODULE, \ | ||
209 | }, \ | ||
210 | .reg = MC13783_REG_ ## _reg, \ | ||
211 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | ||
212 | .voltages = _voltages, \ | ||
213 | } | ||
214 | 179 | ||
215 | #define MC13783_GPO_DEFINE(prefix, _name, _reg, _voltages) \ | 180 | #define MC13783_GPO_DEFINE(prefix, name, reg, voltages) \ |
216 | [MC13783_ ## prefix ## _ ## _name] = { \ | 181 | MC13xxx_GPO_DEFINE(MC13783_REG_, name, reg, voltages, \ |
217 | .desc = { \ | 182 | mc13783_gpo_regulator_ops) |
218 | .name = #prefix "_" #_name, \ | ||
219 | .n_voltages = ARRAY_SIZE(_voltages), \ | ||
220 | .ops = &mc13783_gpo_regulator_ops, \ | ||
221 | .type = REGULATOR_VOLTAGE, \ | ||
222 | .id = MC13783_ ## prefix ## _ ## _name, \ | ||
223 | .owner = THIS_MODULE, \ | ||
224 | }, \ | ||
225 | .reg = MC13783_REG_ ## _reg, \ | ||
226 | .enable_bit = MC13783_REG_ ## _reg ## _ ## _name ## EN, \ | ||
227 | .voltages = _voltages, \ | ||
228 | } | ||
229 | 183 | ||
230 | #define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \ | 184 | #define MC13783_DEFINE_SW(_name, _reg, _vsel_reg, _voltages) \ |
231 | MC13783_DEFINE(SW, _name, _reg, _vsel_reg, _voltages) | 185 | MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages) |
232 | #define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \ | 186 | #define MC13783_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages) \ |
233 | MC13783_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages) | 187 | MC13783_DEFINE(REG, _name, _reg, _vsel_reg, _voltages) |
234 | 188 | ||
235 | static struct mc13783_regulator mc13783_regulators[] = { | 189 | static struct mc13xxx_regulator mc13783_regulators[] = { |
236 | MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), | 190 | MC13783_DEFINE_SW(SW3, SWITCHERS5, SWITCHERS5, mc13783_sw3_val), |
237 | 191 | ||
238 | MC13783_FIXED_DEFINE(REGU, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), | 192 | MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val), |
239 | MC13783_FIXED_DEFINE(REGU, VIOHI, REGULATORMODE0, mc13783_viohi_val), | 193 | MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val), |
240 | MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \ | 194 | MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \ |
241 | mc13783_violo_val), | 195 | mc13783_violo_val), |
242 | MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ | 196 | MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ |
@@ -255,7 +209,7 @@ static struct mc13783_regulator mc13783_regulators[] = { | |||
255 | mc13783_vesim_val), | 209 | mc13783_vesim_val), |
256 | MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ | 210 | MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ |
257 | mc13783_vcam_val), | 211 | mc13783_vcam_val), |
258 | MC13783_FIXED_DEFINE(REGU, VRFBG, REGULATORMODE1, mc13783_vrfbg_val), | 212 | MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val), |
259 | MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \ | 213 | MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \ |
260 | mc13783_vvib_val), | 214 | mc13783_vvib_val), |
261 | MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \ | 215 | MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \ |
@@ -266,215 +220,24 @@ static struct mc13783_regulator mc13783_regulators[] = { | |||
266 | mc13783_vmmc_val), | 220 | mc13783_vmmc_val), |
267 | MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \ | 221 | MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \ |
268 | mc13783_vmmc_val), | 222 | mc13783_vmmc_val), |
269 | MC13783_GPO_DEFINE(REGU, GPO1, POWERMISC, mc13783_gpo_val), | 223 | MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val), |
270 | MC13783_GPO_DEFINE(REGU, GPO2, POWERMISC, mc13783_gpo_val), | 224 | MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val), |
271 | MC13783_GPO_DEFINE(REGU, GPO3, POWERMISC, mc13783_gpo_val), | 225 | MC13783_GPO_DEFINE(REG, GPO3, POWERMISC, mc13783_gpo_val), |
272 | MC13783_GPO_DEFINE(REGU, GPO4, POWERMISC, mc13783_gpo_val), | 226 | MC13783_GPO_DEFINE(REG, GPO4, POWERMISC, mc13783_gpo_val), |
273 | MC13783_GPO_DEFINE(REGU, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val), | 227 | MC13783_GPO_DEFINE(REG, PWGT1SPI, POWERMISC, mc13783_pwgtdrv_val), |
274 | MC13783_GPO_DEFINE(REGU, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val), | 228 | MC13783_GPO_DEFINE(REG, PWGT2SPI, POWERMISC, mc13783_pwgtdrv_val), |
275 | }; | ||
276 | |||
277 | struct mc13783_regulator_priv { | ||
278 | struct mc13783 *mc13783; | ||
279 | u32 powermisc_pwgt_state; | ||
280 | struct regulator_dev *regulators[]; | ||
281 | }; | ||
282 | |||
283 | static int mc13783_regulator_enable(struct regulator_dev *rdev) | ||
284 | { | ||
285 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
286 | int id = rdev_get_id(rdev); | ||
287 | int ret; | ||
288 | |||
289 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
290 | |||
291 | mc13783_lock(priv->mc13783); | ||
292 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg, | ||
293 | mc13783_regulators[id].enable_bit, | ||
294 | mc13783_regulators[id].enable_bit); | ||
295 | mc13783_unlock(priv->mc13783); | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int mc13783_regulator_disable(struct regulator_dev *rdev) | ||
301 | { | ||
302 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
303 | int id = rdev_get_id(rdev); | ||
304 | int ret; | ||
305 | |||
306 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
307 | |||
308 | mc13783_lock(priv->mc13783); | ||
309 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].reg, | ||
310 | mc13783_regulators[id].enable_bit, 0); | ||
311 | mc13783_unlock(priv->mc13783); | ||
312 | |||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | static int mc13783_regulator_is_enabled(struct regulator_dev *rdev) | ||
317 | { | ||
318 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
319 | int ret, id = rdev_get_id(rdev); | ||
320 | unsigned int val; | ||
321 | |||
322 | mc13783_lock(priv->mc13783); | ||
323 | ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); | ||
324 | mc13783_unlock(priv->mc13783); | ||
325 | |||
326 | if (ret) | ||
327 | return ret; | ||
328 | |||
329 | return (val & mc13783_regulators[id].enable_bit) != 0; | ||
330 | } | ||
331 | |||
332 | static int mc13783_regulator_list_voltage(struct regulator_dev *rdev, | ||
333 | unsigned selector) | ||
334 | { | ||
335 | int id = rdev_get_id(rdev); | ||
336 | |||
337 | if (selector >= mc13783_regulators[id].desc.n_voltages) | ||
338 | return -EINVAL; | ||
339 | |||
340 | return mc13783_regulators[id].voltages[selector]; | ||
341 | } | ||
342 | |||
343 | static int mc13783_get_best_voltage_index(struct regulator_dev *rdev, | ||
344 | int min_uV, int max_uV) | ||
345 | { | ||
346 | int reg_id = rdev_get_id(rdev); | ||
347 | int i; | ||
348 | int bestmatch; | ||
349 | int bestindex; | ||
350 | |||
351 | /* | ||
352 | * Locate the minimum voltage fitting the criteria on | ||
353 | * this regulator. The switchable voltages are not | ||
354 | * in strict falling order so we need to check them | ||
355 | * all for the best match. | ||
356 | */ | ||
357 | bestmatch = INT_MAX; | ||
358 | bestindex = -1; | ||
359 | for (i = 0; i < mc13783_regulators[reg_id].desc.n_voltages; i++) { | ||
360 | if (mc13783_regulators[reg_id].voltages[i] >= min_uV && | ||
361 | mc13783_regulators[reg_id].voltages[i] < bestmatch) { | ||
362 | bestmatch = mc13783_regulators[reg_id].voltages[i]; | ||
363 | bestindex = i; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (bestindex < 0 || bestmatch > max_uV) { | ||
368 | dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", | ||
369 | min_uV, max_uV); | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | return bestindex; | ||
373 | } | ||
374 | |||
375 | static int mc13783_regulator_set_voltage(struct regulator_dev *rdev, | ||
376 | int min_uV, int max_uV) | ||
377 | { | ||
378 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
379 | int value, id = rdev_get_id(rdev); | ||
380 | int ret; | ||
381 | |||
382 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | ||
383 | __func__, id, min_uV, max_uV); | ||
384 | |||
385 | /* Find the best index */ | ||
386 | value = mc13783_get_best_voltage_index(rdev, min_uV, max_uV); | ||
387 | dev_dbg(rdev_get_dev(rdev), "%s best value: %d \n", __func__, value); | ||
388 | if (value < 0) | ||
389 | return value; | ||
390 | |||
391 | mc13783_lock(priv->mc13783); | ||
392 | ret = mc13783_reg_rmw(priv->mc13783, mc13783_regulators[id].vsel_reg, | ||
393 | mc13783_regulators[id].vsel_mask, | ||
394 | value << mc13783_regulators[id].vsel_shift); | ||
395 | mc13783_unlock(priv->mc13783); | ||
396 | |||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | static int mc13783_regulator_get_voltage(struct regulator_dev *rdev) | ||
401 | { | ||
402 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
403 | int ret, id = rdev_get_id(rdev); | ||
404 | unsigned int val; | ||
405 | |||
406 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
407 | |||
408 | mc13783_lock(priv->mc13783); | ||
409 | ret = mc13783_reg_read(priv->mc13783, | ||
410 | mc13783_regulators[id].vsel_reg, &val); | ||
411 | mc13783_unlock(priv->mc13783); | ||
412 | |||
413 | if (ret) | ||
414 | return ret; | ||
415 | |||
416 | val = (val & mc13783_regulators[id].vsel_mask) | ||
417 | >> mc13783_regulators[id].vsel_shift; | ||
418 | |||
419 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); | ||
420 | |||
421 | BUG_ON(val < 0 || val > mc13783_regulators[id].desc.n_voltages); | ||
422 | |||
423 | return mc13783_regulators[id].voltages[val]; | ||
424 | } | ||
425 | |||
426 | static struct regulator_ops mc13783_regulator_ops = { | ||
427 | .enable = mc13783_regulator_enable, | ||
428 | .disable = mc13783_regulator_disable, | ||
429 | .is_enabled = mc13783_regulator_is_enabled, | ||
430 | .list_voltage = mc13783_regulator_list_voltage, | ||
431 | .set_voltage = mc13783_regulator_set_voltage, | ||
432 | .get_voltage = mc13783_regulator_get_voltage, | ||
433 | }; | ||
434 | |||
435 | static int mc13783_fixed_regulator_set_voltage(struct regulator_dev *rdev, | ||
436 | int min_uV, int max_uV) | ||
437 | { | ||
438 | int id = rdev_get_id(rdev); | ||
439 | |||
440 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | ||
441 | __func__, id, min_uV, max_uV); | ||
442 | |||
443 | if (min_uV >= mc13783_regulators[id].voltages[0] && | ||
444 | max_uV <= mc13783_regulators[id].voltages[0]) | ||
445 | return 0; | ||
446 | else | ||
447 | return -EINVAL; | ||
448 | } | ||
449 | |||
450 | static int mc13783_fixed_regulator_get_voltage(struct regulator_dev *rdev) | ||
451 | { | ||
452 | int id = rdev_get_id(rdev); | ||
453 | |||
454 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
455 | |||
456 | return mc13783_regulators[id].voltages[0]; | ||
457 | } | ||
458 | |||
459 | static struct regulator_ops mc13783_fixed_regulator_ops = { | ||
460 | .enable = mc13783_regulator_enable, | ||
461 | .disable = mc13783_regulator_disable, | ||
462 | .is_enabled = mc13783_regulator_is_enabled, | ||
463 | .list_voltage = mc13783_regulator_list_voltage, | ||
464 | .set_voltage = mc13783_fixed_regulator_set_voltage, | ||
465 | .get_voltage = mc13783_fixed_regulator_get_voltage, | ||
466 | }; | 229 | }; |
467 | 230 | ||
468 | static int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask, | 231 | static int mc13783_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, |
469 | u32 val) | 232 | u32 val) |
470 | { | 233 | { |
471 | struct mc13783 *mc13783 = priv->mc13783; | 234 | struct mc13xxx *mc13783 = priv->mc13xxx; |
472 | int ret; | 235 | int ret; |
473 | u32 valread; | 236 | u32 valread; |
474 | 237 | ||
475 | BUG_ON(val & ~mask); | 238 | BUG_ON(val & ~mask); |
476 | 239 | ||
477 | ret = mc13783_reg_read(mc13783, MC13783_REG_POWERMISC, &valread); | 240 | ret = mc13xxx_reg_read(mc13783, MC13783_REG_POWERMISC, &valread); |
478 | if (ret) | 241 | if (ret) |
479 | return ret; | 242 | return ret; |
480 | 243 | ||
@@ -489,34 +252,36 @@ static int mc13783_powermisc_rmw(struct mc13783_regulator_priv *priv, u32 mask, | |||
489 | valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) | | 252 | valread = (valread & ~MC13783_REG_POWERMISC_PWGTSPI_M) | |
490 | priv->powermisc_pwgt_state; | 253 | priv->powermisc_pwgt_state; |
491 | 254 | ||
492 | return mc13783_reg_write(mc13783, MC13783_REG_POWERMISC, valread); | 255 | return mc13xxx_reg_write(mc13783, MC13783_REG_POWERMISC, valread); |
493 | } | 256 | } |
494 | 257 | ||
495 | static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) | 258 | static int mc13783_gpo_regulator_enable(struct regulator_dev *rdev) |
496 | { | 259 | { |
497 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | 260 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); |
261 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
498 | int id = rdev_get_id(rdev); | 262 | int id = rdev_get_id(rdev); |
499 | int ret; | 263 | int ret; |
500 | u32 en_val = mc13783_regulators[id].enable_bit; | 264 | u32 en_val = mc13xxx_regulators[id].enable_bit; |
501 | 265 | ||
502 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | 266 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); |
503 | 267 | ||
504 | /* Power Gate enable value is 0 */ | 268 | /* Power Gate enable value is 0 */ |
505 | if (id == MC13783_REGU_PWGT1SPI || | 269 | if (id == MC13783_REG_PWGT1SPI || |
506 | id == MC13783_REGU_PWGT2SPI) | 270 | id == MC13783_REG_PWGT2SPI) |
507 | en_val = 0; | 271 | en_val = 0; |
508 | 272 | ||
509 | mc13783_lock(priv->mc13783); | 273 | mc13xxx_lock(priv->mc13xxx); |
510 | ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit, | 274 | ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, |
511 | en_val); | 275 | en_val); |
512 | mc13783_unlock(priv->mc13783); | 276 | mc13xxx_unlock(priv->mc13xxx); |
513 | 277 | ||
514 | return ret; | 278 | return ret; |
515 | } | 279 | } |
516 | 280 | ||
517 | static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) | 281 | static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) |
518 | { | 282 | { |
519 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | 283 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); |
284 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
520 | int id = rdev_get_id(rdev); | 285 | int id = rdev_get_id(rdev); |
521 | int ret; | 286 | int ret; |
522 | u32 dis_val = 0; | 287 | u32 dis_val = 0; |
@@ -524,27 +289,28 @@ static int mc13783_gpo_regulator_disable(struct regulator_dev *rdev) | |||
524 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | 289 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); |
525 | 290 | ||
526 | /* Power Gate disable value is 1 */ | 291 | /* Power Gate disable value is 1 */ |
527 | if (id == MC13783_REGU_PWGT1SPI || | 292 | if (id == MC13783_REG_PWGT1SPI || |
528 | id == MC13783_REGU_PWGT2SPI) | 293 | id == MC13783_REG_PWGT2SPI) |
529 | dis_val = mc13783_regulators[id].enable_bit; | 294 | dis_val = mc13xxx_regulators[id].enable_bit; |
530 | 295 | ||
531 | mc13783_lock(priv->mc13783); | 296 | mc13xxx_lock(priv->mc13xxx); |
532 | ret = mc13783_powermisc_rmw(priv, mc13783_regulators[id].enable_bit, | 297 | ret = mc13783_powermisc_rmw(priv, mc13xxx_regulators[id].enable_bit, |
533 | dis_val); | 298 | dis_val); |
534 | mc13783_unlock(priv->mc13783); | 299 | mc13xxx_unlock(priv->mc13xxx); |
535 | 300 | ||
536 | return ret; | 301 | return ret; |
537 | } | 302 | } |
538 | 303 | ||
539 | static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) | 304 | static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) |
540 | { | 305 | { |
541 | struct mc13783_regulator_priv *priv = rdev_get_drvdata(rdev); | 306 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); |
307 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
542 | int ret, id = rdev_get_id(rdev); | 308 | int ret, id = rdev_get_id(rdev); |
543 | unsigned int val; | 309 | unsigned int val; |
544 | 310 | ||
545 | mc13783_lock(priv->mc13783); | 311 | mc13xxx_lock(priv->mc13xxx); |
546 | ret = mc13783_reg_read(priv->mc13783, mc13783_regulators[id].reg, &val); | 312 | ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val); |
547 | mc13783_unlock(priv->mc13783); | 313 | mc13xxx_unlock(priv->mc13xxx); |
548 | 314 | ||
549 | if (ret) | 315 | if (ret) |
550 | return ret; | 316 | return ret; |
@@ -554,22 +320,22 @@ static int mc13783_gpo_regulator_is_enabled(struct regulator_dev *rdev) | |||
554 | val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) | | 320 | val = (val & ~MC13783_REG_POWERMISC_PWGTSPI_M) | |
555 | (priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M); | 321 | (priv->powermisc_pwgt_state ^ MC13783_REG_POWERMISC_PWGTSPI_M); |
556 | 322 | ||
557 | return (val & mc13783_regulators[id].enable_bit) != 0; | 323 | return (val & mc13xxx_regulators[id].enable_bit) != 0; |
558 | } | 324 | } |
559 | 325 | ||
560 | static struct regulator_ops mc13783_gpo_regulator_ops = { | 326 | static struct regulator_ops mc13783_gpo_regulator_ops = { |
561 | .enable = mc13783_gpo_regulator_enable, | 327 | .enable = mc13783_gpo_regulator_enable, |
562 | .disable = mc13783_gpo_regulator_disable, | 328 | .disable = mc13783_gpo_regulator_disable, |
563 | .is_enabled = mc13783_gpo_regulator_is_enabled, | 329 | .is_enabled = mc13783_gpo_regulator_is_enabled, |
564 | .list_voltage = mc13783_regulator_list_voltage, | 330 | .list_voltage = mc13xxx_regulator_list_voltage, |
565 | .set_voltage = mc13783_fixed_regulator_set_voltage, | 331 | .set_voltage = mc13xxx_fixed_regulator_set_voltage, |
566 | .get_voltage = mc13783_fixed_regulator_get_voltage, | 332 | .get_voltage = mc13xxx_fixed_regulator_get_voltage, |
567 | }; | 333 | }; |
568 | 334 | ||
569 | static int __devinit mc13783_regulator_probe(struct platform_device *pdev) | 335 | static int __devinit mc13783_regulator_probe(struct platform_device *pdev) |
570 | { | 336 | { |
571 | struct mc13783_regulator_priv *priv; | 337 | struct mc13xxx_regulator_priv *priv; |
572 | struct mc13783 *mc13783 = dev_get_drvdata(pdev->dev.parent); | 338 | struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); |
573 | struct mc13783_regulator_platform_data *pdata = | 339 | struct mc13783_regulator_platform_data *pdata = |
574 | dev_get_platdata(&pdev->dev); | 340 | dev_get_platdata(&pdev->dev); |
575 | struct mc13783_regulator_init_data *init_data; | 341 | struct mc13783_regulator_init_data *init_data; |
@@ -583,7 +349,8 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) | |||
583 | if (!priv) | 349 | if (!priv) |
584 | return -ENOMEM; | 350 | return -ENOMEM; |
585 | 351 | ||
586 | priv->mc13783 = mc13783; | 352 | priv->mc13xxx_regulators = mc13783_regulators; |
353 | priv->mc13xxx = mc13783; | ||
587 | 354 | ||
588 | for (i = 0; i < pdata->num_regulators; i++) { | 355 | for (i = 0; i < pdata->num_regulators; i++) { |
589 | init_data = &pdata->regulators[i]; | 356 | init_data = &pdata->regulators[i]; |
@@ -613,7 +380,7 @@ err: | |||
613 | 380 | ||
614 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) | 381 | static int __devexit mc13783_regulator_remove(struct platform_device *pdev) |
615 | { | 382 | { |
616 | struct mc13783_regulator_priv *priv = platform_get_drvdata(pdev); | 383 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); |
617 | struct mc13783_regulator_platform_data *pdata = | 384 | struct mc13783_regulator_platform_data *pdata = |
618 | dev_get_platdata(&pdev->dev); | 385 | dev_get_platdata(&pdev->dev); |
619 | int i; | 386 | int i; |
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c new file mode 100644 index 000000000000..1b8f7398a4a8 --- /dev/null +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -0,0 +1,635 @@ | |||
1 | /* | ||
2 | * Regulator Driver for Freescale MC13892 PMIC | ||
3 | * | ||
4 | * Copyright 2010 Yong Shen <yong.shen@linaro.org> | ||
5 | * | ||
6 | * Based on draft driver from Arnaud Patard <arnaud.patard@rtp-net.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/mfd/mc13892.h> | ||
14 | #include <linux/regulator/machine.h> | ||
15 | #include <linux/regulator/driver.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/err.h> | ||
21 | #include "mc13xxx.h" | ||
22 | |||
23 | #define MC13892_REVISION 7 | ||
24 | |||
25 | #define MC13892_POWERCTL0 13 | ||
26 | #define MC13892_POWERCTL0_USEROFFSPI 3 | ||
27 | #define MC13892_POWERCTL0_VCOINCELLVSEL 20 | ||
28 | #define MC13892_POWERCTL0_VCOINCELLVSEL_M (7<<20) | ||
29 | #define MC13892_POWERCTL0_VCOINCELLEN (1<<23) | ||
30 | |||
31 | #define MC13892_SWITCHERS0_SWxHI (1<<23) | ||
32 | |||
33 | #define MC13892_SWITCHERS0 24 | ||
34 | #define MC13892_SWITCHERS0_SW1VSEL 0 | ||
35 | #define MC13892_SWITCHERS0_SW1VSEL_M (0x1f<<0) | ||
36 | #define MC13892_SWITCHERS0_SW1HI (1<<23) | ||
37 | #define MC13892_SWITCHERS0_SW1EN 0 | ||
38 | |||
39 | #define MC13892_SWITCHERS1 25 | ||
40 | #define MC13892_SWITCHERS1_SW2VSEL 0 | ||
41 | #define MC13892_SWITCHERS1_SW2VSEL_M (0x1f<<0) | ||
42 | #define MC13892_SWITCHERS1_SW2HI (1<<23) | ||
43 | #define MC13892_SWITCHERS1_SW2EN 0 | ||
44 | |||
45 | #define MC13892_SWITCHERS2 26 | ||
46 | #define MC13892_SWITCHERS2_SW3VSEL 0 | ||
47 | #define MC13892_SWITCHERS2_SW3VSEL_M (0x1f<<0) | ||
48 | #define MC13892_SWITCHERS2_SW3HI (1<<23) | ||
49 | #define MC13892_SWITCHERS2_SW3EN 0 | ||
50 | |||
51 | #define MC13892_SWITCHERS3 27 | ||
52 | #define MC13892_SWITCHERS3_SW4VSEL 0 | ||
53 | #define MC13892_SWITCHERS3_SW4VSEL_M (0x1f<<0) | ||
54 | #define MC13892_SWITCHERS3_SW4HI (1<<23) | ||
55 | #define MC13892_SWITCHERS3_SW4EN 0 | ||
56 | |||
57 | #define MC13892_SWITCHERS4 28 | ||
58 | #define MC13892_SWITCHERS4_SW1MODE 0 | ||
59 | #define MC13892_SWITCHERS4_SW1MODE_AUTO (8<<0) | ||
60 | #define MC13892_SWITCHERS4_SW1MODE_M (0xf<<0) | ||
61 | #define MC13892_SWITCHERS4_SW2MODE 10 | ||
62 | #define MC13892_SWITCHERS4_SW2MODE_AUTO (8<<10) | ||
63 | #define MC13892_SWITCHERS4_SW2MODE_M (0xf<<10) | ||
64 | |||
65 | #define MC13892_SWITCHERS5 29 | ||
66 | #define MC13892_SWITCHERS5_SW3MODE 0 | ||
67 | #define MC13892_SWITCHERS5_SW3MODE_AUTO (8<<0) | ||
68 | #define MC13892_SWITCHERS5_SW3MODE_M (0xf<<0) | ||
69 | #define MC13892_SWITCHERS5_SW4MODE 8 | ||
70 | #define MC13892_SWITCHERS5_SW4MODE_AUTO (8<<8) | ||
71 | #define MC13892_SWITCHERS5_SW4MODE_M (0xf<<8) | ||
72 | #define MC13892_SWITCHERS5_SWBSTEN (1<<20) | ||
73 | |||
74 | #define MC13892_REGULATORSETTING0 30 | ||
75 | #define MC13892_REGULATORSETTING0_VGEN1VSEL 0 | ||
76 | #define MC13892_REGULATORSETTING0_VDIGVSEL 4 | ||
77 | #define MC13892_REGULATORSETTING0_VGEN2VSEL 6 | ||
78 | #define MC13892_REGULATORSETTING0_VPLLVSEL 9 | ||
79 | #define MC13892_REGULATORSETTING0_VUSB2VSEL 11 | ||
80 | #define MC13892_REGULATORSETTING0_VGEN3VSEL 14 | ||
81 | #define MC13892_REGULATORSETTING0_VCAMVSEL 16 | ||
82 | |||
83 | #define MC13892_REGULATORSETTING0_VGEN1VSEL_M (3<<0) | ||
84 | #define MC13892_REGULATORSETTING0_VDIGVSEL_M (3<<4) | ||
85 | #define MC13892_REGULATORSETTING0_VGEN2VSEL_M (7<<6) | ||
86 | #define MC13892_REGULATORSETTING0_VPLLVSEL_M (3<<9) | ||
87 | #define MC13892_REGULATORSETTING0_VUSB2VSEL_M (3<<11) | ||
88 | #define MC13892_REGULATORSETTING0_VGEN3VSEL_M (1<<14) | ||
89 | #define MC13892_REGULATORSETTING0_VCAMVSEL_M (3<<16) | ||
90 | |||
91 | #define MC13892_REGULATORSETTING1 31 | ||
92 | #define MC13892_REGULATORSETTING1_VVIDEOVSEL 2 | ||
93 | #define MC13892_REGULATORSETTING1_VAUDIOVSEL 4 | ||
94 | #define MC13892_REGULATORSETTING1_VSDVSEL 6 | ||
95 | |||
96 | #define MC13892_REGULATORSETTING1_VVIDEOVSEL_M (3<<2) | ||
97 | #define MC13892_REGULATORSETTING1_VAUDIOVSEL_M (3<<4) | ||
98 | #define MC13892_REGULATORSETTING1_VSDVSEL_M (7<<6) | ||
99 | |||
100 | #define MC13892_REGULATORMODE0 32 | ||
101 | #define MC13892_REGULATORMODE0_VGEN1EN (1<<0) | ||
102 | #define MC13892_REGULATORMODE0_VGEN1STDBY (1<<1) | ||
103 | #define MC13892_REGULATORMODE0_VGEN1MODE (1<<2) | ||
104 | #define MC13892_REGULATORMODE0_VIOHIEN (1<<3) | ||
105 | #define MC13892_REGULATORMODE0_VIOHISTDBY (1<<4) | ||
106 | #define MC13892_REGULATORMODE0_VIOHIMODE (1<<5) | ||
107 | #define MC13892_REGULATORMODE0_VDIGEN (1<<9) | ||
108 | #define MC13892_REGULATORMODE0_VDIGSTDBY (1<<10) | ||
109 | #define MC13892_REGULATORMODE0_VDIGMODE (1<<11) | ||
110 | #define MC13892_REGULATORMODE0_VGEN2EN (1<<12) | ||
111 | #define MC13892_REGULATORMODE0_VGEN2STDBY (1<<13) | ||
112 | #define MC13892_REGULATORMODE0_VGEN2MODE (1<<14) | ||
113 | #define MC13892_REGULATORMODE0_VPLLEN (1<<15) | ||
114 | #define MC13892_REGULATORMODE0_VPLLSTDBY (1<<16) | ||
115 | #define MC13892_REGULATORMODE0_VPLLMODE (1<<17) | ||
116 | #define MC13892_REGULATORMODE0_VUSB2EN (1<<18) | ||
117 | #define MC13892_REGULATORMODE0_VUSB2STDBY (1<<19) | ||
118 | #define MC13892_REGULATORMODE0_VUSB2MODE (1<<20) | ||
119 | |||
120 | #define MC13892_REGULATORMODE1 33 | ||
121 | #define MC13892_REGULATORMODE1_VGEN3EN (1<<0) | ||
122 | #define MC13892_REGULATORMODE1_VGEN3STDBY (1<<1) | ||
123 | #define MC13892_REGULATORMODE1_VGEN3MODE (1<<2) | ||
124 | #define MC13892_REGULATORMODE1_VCAMEN (1<<6) | ||
125 | #define MC13892_REGULATORMODE1_VCAMSTDBY (1<<7) | ||
126 | #define MC13892_REGULATORMODE1_VCAMMODE (1<<8) | ||
127 | #define MC13892_REGULATORMODE1_VCAMCONFIGEN (1<<9) | ||
128 | #define MC13892_REGULATORMODE1_VVIDEOEN (1<<12) | ||
129 | #define MC13892_REGULATORMODE1_VVIDEOSTDBY (1<<13) | ||
130 | #define MC13892_REGULATORMODE1_VVIDEOMODE (1<<14) | ||
131 | #define MC13892_REGULATORMODE1_VAUDIOEN (1<<15) | ||
132 | #define MC13892_REGULATORMODE1_VAUDIOSTDBY (1<<16) | ||
133 | #define MC13892_REGULATORMODE1_VAUDIOMODE (1<<17) | ||
134 | #define MC13892_REGULATORMODE1_VSDEN (1<<18) | ||
135 | #define MC13892_REGULATORMODE1_VSDSTDBY (1<<19) | ||
136 | #define MC13892_REGULATORMODE1_VSDMODE (1<<20) | ||
137 | |||
138 | #define MC13892_POWERMISC 34 | ||
139 | #define MC13892_POWERMISC_GPO1EN (1<<6) | ||
140 | #define MC13892_POWERMISC_GPO2EN (1<<8) | ||
141 | #define MC13892_POWERMISC_GPO3EN (1<<10) | ||
142 | #define MC13892_POWERMISC_GPO4EN (1<<12) | ||
143 | #define MC13892_POWERMISC_PWGT1SPIEN (1<<15) | ||
144 | #define MC13892_POWERMISC_PWGT2SPIEN (1<<16) | ||
145 | #define MC13892_POWERMISC_GPO4ADINEN (1<<21) | ||
146 | |||
147 | #define MC13892_POWERMISC_PWGTSPI_M (3 << 15) | ||
148 | |||
149 | #define MC13892_USB1 50 | ||
150 | #define MC13892_USB1_VUSBEN (1<<3) | ||
151 | |||
152 | static const int mc13892_vcoincell[] = { | ||
153 | 2500000, 2700000, 2800000, 2900000, 3000000, 3100000, | ||
154 | 3200000, 3300000, | ||
155 | }; | ||
156 | |||
157 | static const int mc13892_sw1[] = { | ||
158 | 600000, 625000, 650000, 675000, 700000, 725000, | ||
159 | 750000, 775000, 800000, 825000, 850000, 875000, | ||
160 | 900000, 925000, 950000, 975000, 1000000, 1025000, | ||
161 | 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, | ||
162 | 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, | ||
163 | 1350000, 1375000 | ||
164 | }; | ||
165 | |||
166 | static const int mc13892_sw[] = { | ||
167 | 600000, 625000, 650000, 675000, 700000, 725000, | ||
168 | 750000, 775000, 800000, 825000, 850000, 875000, | ||
169 | 900000, 925000, 950000, 975000, 1000000, 1025000, | ||
170 | 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, | ||
171 | 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, | ||
172 | 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, | ||
173 | 1500000, 1525000, 1550000, 1575000, 1600000, 1625000, | ||
174 | 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, | ||
175 | 1800000, 1825000, 1850000, 1875000 | ||
176 | }; | ||
177 | |||
178 | static const int mc13892_swbst[] = { | ||
179 | 5000000, | ||
180 | }; | ||
181 | |||
182 | static const int mc13892_viohi[] = { | ||
183 | 2775000, | ||
184 | }; | ||
185 | |||
186 | static const int mc13892_vpll[] = { | ||
187 | 1050000, 1250000, 1650000, 1800000, | ||
188 | }; | ||
189 | |||
190 | static const int mc13892_vdig[] = { | ||
191 | 1050000, 1250000, 1650000, 1800000, | ||
192 | }; | ||
193 | |||
194 | static const int mc13892_vsd[] = { | ||
195 | 1800000, 2000000, 2600000, 2700000, | ||
196 | 2800000, 2900000, 3000000, 3150000, | ||
197 | }; | ||
198 | |||
199 | static const int mc13892_vusb2[] = { | ||
200 | 2400000, 2600000, 2700000, 2775000, | ||
201 | }; | ||
202 | |||
203 | static const int mc13892_vvideo[] = { | ||
204 | 2700000, 2775000, 2500000, 2600000, | ||
205 | }; | ||
206 | |||
207 | static const int mc13892_vaudio[] = { | ||
208 | 2300000, 2500000, 2775000, 3000000, | ||
209 | }; | ||
210 | |||
211 | static const int mc13892_vcam[] = { | ||
212 | 2500000, 2600000, 2750000, 3000000, | ||
213 | }; | ||
214 | |||
215 | static const int mc13892_vgen1[] = { | ||
216 | 1200000, 1500000, 2775000, 3150000, | ||
217 | }; | ||
218 | |||
219 | static const int mc13892_vgen2[] = { | ||
220 | 1200000, 1500000, 1600000, 1800000, | ||
221 | 2700000, 2800000, 3000000, 3150000, | ||
222 | }; | ||
223 | |||
224 | static const int mc13892_vgen3[] = { | ||
225 | 1800000, 2900000, | ||
226 | }; | ||
227 | |||
228 | static const int mc13892_vusb[] = { | ||
229 | 3300000, | ||
230 | }; | ||
231 | |||
232 | static const int mc13892_gpo[] = { | ||
233 | 2750000, | ||
234 | }; | ||
235 | |||
236 | static const int mc13892_pwgtdrv[] = { | ||
237 | 5000000, | ||
238 | }; | ||
239 | |||
240 | static struct regulator_ops mc13892_gpo_regulator_ops; | ||
241 | /* sw regulators need special care due to the "hi bit" */ | ||
242 | static struct regulator_ops mc13892_sw_regulator_ops; | ||
243 | |||
244 | |||
245 | #define MC13892_FIXED_DEFINE(name, reg, voltages) \ | ||
246 | MC13xxx_FIXED_DEFINE(MC13892_, name, reg, voltages, \ | ||
247 | mc13xxx_fixed_regulator_ops) | ||
248 | |||
249 | #define MC13892_GPO_DEFINE(name, reg, voltages) \ | ||
250 | MC13xxx_GPO_DEFINE(MC13892_, name, reg, voltages, \ | ||
251 | mc13892_gpo_regulator_ops) | ||
252 | |||
253 | #define MC13892_SW_DEFINE(name, reg, vsel_reg, voltages) \ | ||
254 | MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \ | ||
255 | mc13892_sw_regulator_ops) | ||
256 | |||
257 | #define MC13892_DEFINE_REGU(name, reg, vsel_reg, voltages) \ | ||
258 | MC13xxx_DEFINE(MC13892_, name, reg, vsel_reg, voltages, \ | ||
259 | mc13xxx_regulator_ops) | ||
260 | |||
261 | static struct mc13xxx_regulator mc13892_regulators[] = { | ||
262 | MC13892_DEFINE_REGU(VCOINCELL, POWERCTL0, POWERCTL0, mc13892_vcoincell), | ||
263 | MC13892_SW_DEFINE(SW1, SWITCHERS0, SWITCHERS0, mc13892_sw1), | ||
264 | MC13892_SW_DEFINE(SW2, SWITCHERS1, SWITCHERS1, mc13892_sw), | ||
265 | MC13892_SW_DEFINE(SW3, SWITCHERS2, SWITCHERS2, mc13892_sw), | ||
266 | MC13892_SW_DEFINE(SW4, SWITCHERS3, SWITCHERS3, mc13892_sw), | ||
267 | MC13892_FIXED_DEFINE(SWBST, SWITCHERS5, mc13892_swbst), | ||
268 | MC13892_FIXED_DEFINE(VIOHI, REGULATORMODE0, mc13892_viohi), | ||
269 | MC13892_DEFINE_REGU(VPLL, REGULATORMODE0, REGULATORSETTING0, \ | ||
270 | mc13892_vpll), | ||
271 | MC13892_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \ | ||
272 | mc13892_vdig), | ||
273 | MC13892_DEFINE_REGU(VSD, REGULATORMODE1, REGULATORSETTING1, \ | ||
274 | mc13892_vsd), | ||
275 | MC13892_DEFINE_REGU(VUSB2, REGULATORMODE0, REGULATORSETTING0, \ | ||
276 | mc13892_vusb2), | ||
277 | MC13892_DEFINE_REGU(VVIDEO, REGULATORMODE1, REGULATORSETTING1, \ | ||
278 | mc13892_vvideo), | ||
279 | MC13892_DEFINE_REGU(VAUDIO, REGULATORMODE1, REGULATORSETTING1, \ | ||
280 | mc13892_vaudio), | ||
281 | MC13892_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \ | ||
282 | mc13892_vcam), | ||
283 | MC13892_DEFINE_REGU(VGEN1, REGULATORMODE0, REGULATORSETTING0, \ | ||
284 | mc13892_vgen1), | ||
285 | MC13892_DEFINE_REGU(VGEN2, REGULATORMODE0, REGULATORSETTING0, \ | ||
286 | mc13892_vgen2), | ||
287 | MC13892_DEFINE_REGU(VGEN3, REGULATORMODE1, REGULATORSETTING0, \ | ||
288 | mc13892_vgen3), | ||
289 | MC13892_FIXED_DEFINE(VUSB, USB1, mc13892_vusb), | ||
290 | MC13892_GPO_DEFINE(GPO1, POWERMISC, mc13892_gpo), | ||
291 | MC13892_GPO_DEFINE(GPO2, POWERMISC, mc13892_gpo), | ||
292 | MC13892_GPO_DEFINE(GPO3, POWERMISC, mc13892_gpo), | ||
293 | MC13892_GPO_DEFINE(GPO4, POWERMISC, mc13892_gpo), | ||
294 | MC13892_GPO_DEFINE(PWGT1SPI, POWERMISC, mc13892_pwgtdrv), | ||
295 | MC13892_GPO_DEFINE(PWGT2SPI, POWERMISC, mc13892_pwgtdrv), | ||
296 | }; | ||
297 | |||
298 | static int mc13892_powermisc_rmw(struct mc13xxx_regulator_priv *priv, u32 mask, | ||
299 | u32 val) | ||
300 | { | ||
301 | struct mc13xxx *mc13892 = priv->mc13xxx; | ||
302 | int ret; | ||
303 | u32 valread; | ||
304 | |||
305 | BUG_ON(val & ~mask); | ||
306 | |||
307 | ret = mc13xxx_reg_read(mc13892, MC13892_POWERMISC, &valread); | ||
308 | if (ret) | ||
309 | return ret; | ||
310 | |||
311 | /* Update the stored state for Power Gates. */ | ||
312 | priv->powermisc_pwgt_state = | ||
313 | (priv->powermisc_pwgt_state & ~mask) | val; | ||
314 | priv->powermisc_pwgt_state &= MC13892_POWERMISC_PWGTSPI_M; | ||
315 | |||
316 | /* Construct the new register value */ | ||
317 | valread = (valread & ~mask) | val; | ||
318 | /* Overwrite the PWGTxEN with the stored version */ | ||
319 | valread = (valread & ~MC13892_POWERMISC_PWGTSPI_M) | | ||
320 | priv->powermisc_pwgt_state; | ||
321 | |||
322 | return mc13xxx_reg_write(mc13892, MC13892_POWERMISC, valread); | ||
323 | } | ||
324 | |||
325 | static int mc13892_gpo_regulator_enable(struct regulator_dev *rdev) | ||
326 | { | ||
327 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
328 | int id = rdev_get_id(rdev); | ||
329 | int ret; | ||
330 | u32 en_val = mc13892_regulators[id].enable_bit; | ||
331 | u32 mask = mc13892_regulators[id].enable_bit; | ||
332 | |||
333 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
334 | |||
335 | /* Power Gate enable value is 0 */ | ||
336 | if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) | ||
337 | en_val = 0; | ||
338 | |||
339 | if (id == MC13892_GPO4) | ||
340 | mask |= MC13892_POWERMISC_GPO4ADINEN; | ||
341 | |||
342 | mc13xxx_lock(priv->mc13xxx); | ||
343 | ret = mc13892_powermisc_rmw(priv, mask, en_val); | ||
344 | mc13xxx_unlock(priv->mc13xxx); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int mc13892_gpo_regulator_disable(struct regulator_dev *rdev) | ||
350 | { | ||
351 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
352 | int id = rdev_get_id(rdev); | ||
353 | int ret; | ||
354 | u32 dis_val = 0; | ||
355 | |||
356 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
357 | |||
358 | /* Power Gate disable value is 1 */ | ||
359 | if (id == MC13892_PWGT1SPI || id == MC13892_PWGT2SPI) | ||
360 | dis_val = mc13892_regulators[id].enable_bit; | ||
361 | |||
362 | mc13xxx_lock(priv->mc13xxx); | ||
363 | ret = mc13892_powermisc_rmw(priv, mc13892_regulators[id].enable_bit, | ||
364 | dis_val); | ||
365 | mc13xxx_unlock(priv->mc13xxx); | ||
366 | |||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | static int mc13892_gpo_regulator_is_enabled(struct regulator_dev *rdev) | ||
371 | { | ||
372 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
373 | int ret, id = rdev_get_id(rdev); | ||
374 | unsigned int val; | ||
375 | |||
376 | mc13xxx_lock(priv->mc13xxx); | ||
377 | ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); | ||
378 | mc13xxx_unlock(priv->mc13xxx); | ||
379 | |||
380 | if (ret) | ||
381 | return ret; | ||
382 | |||
383 | /* Power Gates state is stored in powermisc_pwgt_state | ||
384 | * where the meaning of bits is negated */ | ||
385 | val = (val & ~MC13892_POWERMISC_PWGTSPI_M) | | ||
386 | (priv->powermisc_pwgt_state ^ MC13892_POWERMISC_PWGTSPI_M); | ||
387 | |||
388 | return (val & mc13892_regulators[id].enable_bit) != 0; | ||
389 | } | ||
390 | |||
391 | |||
392 | static struct regulator_ops mc13892_gpo_regulator_ops = { | ||
393 | .enable = mc13892_gpo_regulator_enable, | ||
394 | .disable = mc13892_gpo_regulator_disable, | ||
395 | .is_enabled = mc13892_gpo_regulator_is_enabled, | ||
396 | .list_voltage = mc13xxx_regulator_list_voltage, | ||
397 | .set_voltage = mc13xxx_fixed_regulator_set_voltage, | ||
398 | .get_voltage = mc13xxx_fixed_regulator_get_voltage, | ||
399 | }; | ||
400 | |||
401 | static int mc13892_sw_regulator_get_voltage(struct regulator_dev *rdev) | ||
402 | { | ||
403 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
404 | int ret, id = rdev_get_id(rdev); | ||
405 | unsigned int val, hi; | ||
406 | |||
407 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
408 | |||
409 | mc13xxx_lock(priv->mc13xxx); | ||
410 | ret = mc13xxx_reg_read(priv->mc13xxx, | ||
411 | mc13892_regulators[id].vsel_reg, &val); | ||
412 | mc13xxx_unlock(priv->mc13xxx); | ||
413 | if (ret) | ||
414 | return ret; | ||
415 | |||
416 | hi = val & MC13892_SWITCHERS0_SWxHI; | ||
417 | val = (val & mc13892_regulators[id].vsel_mask) | ||
418 | >> mc13892_regulators[id].vsel_shift; | ||
419 | |||
420 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); | ||
421 | |||
422 | if (hi) | ||
423 | val = (25000 * val) + 1100000; | ||
424 | else | ||
425 | val = (25000 * val) + 600000; | ||
426 | |||
427 | return val; | ||
428 | } | ||
429 | |||
430 | static int mc13892_sw_regulator_set_voltage(struct regulator_dev *rdev, | ||
431 | int min_uV, int max_uV, unsigned *selector) | ||
432 | { | ||
433 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
434 | int hi, value, val, mask, id = rdev_get_id(rdev); | ||
435 | int ret; | ||
436 | |||
437 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | ||
438 | __func__, id, min_uV, max_uV); | ||
439 | |||
440 | /* Find the best index */ | ||
441 | value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV); | ||
442 | dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value); | ||
443 | if (value < 0) | ||
444 | return value; | ||
445 | |||
446 | value = mc13892_regulators[id].voltages[value]; | ||
447 | |||
448 | mc13xxx_lock(priv->mc13xxx); | ||
449 | ret = mc13xxx_reg_read(priv->mc13xxx, | ||
450 | mc13892_regulators[id].vsel_reg, &val); | ||
451 | if (ret) | ||
452 | goto err; | ||
453 | |||
454 | hi = val & MC13892_SWITCHERS0_SWxHI; | ||
455 | if (value > 1375) | ||
456 | hi = 1; | ||
457 | if (value < 1100) | ||
458 | hi = 0; | ||
459 | |||
460 | if (hi) { | ||
461 | value = (value - 1100000) / 25000; | ||
462 | value |= MC13892_SWITCHERS0_SWxHI; | ||
463 | } else | ||
464 | value = (value - 600000) / 25000; | ||
465 | |||
466 | mask = mc13892_regulators[id].vsel_mask | MC13892_SWITCHERS0_SWxHI; | ||
467 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, | ||
468 | mask, value << mc13892_regulators[id].vsel_shift); | ||
469 | err: | ||
470 | mc13xxx_unlock(priv->mc13xxx); | ||
471 | |||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | static struct regulator_ops mc13892_sw_regulator_ops = { | ||
476 | .is_enabled = mc13xxx_sw_regulator_is_enabled, | ||
477 | .list_voltage = mc13xxx_regulator_list_voltage, | ||
478 | .set_voltage = mc13892_sw_regulator_set_voltage, | ||
479 | .get_voltage = mc13892_sw_regulator_get_voltage, | ||
480 | }; | ||
481 | |||
482 | static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode) | ||
483 | { | ||
484 | unsigned int en_val = 0; | ||
485 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
486 | int ret, id = rdev_get_id(rdev); | ||
487 | |||
488 | if (mode == REGULATOR_MODE_FAST) | ||
489 | en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN; | ||
490 | |||
491 | mc13xxx_lock(priv->mc13xxx); | ||
492 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, | ||
493 | MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val); | ||
494 | mc13xxx_unlock(priv->mc13xxx); | ||
495 | |||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) | ||
500 | { | ||
501 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
502 | int ret, id = rdev_get_id(rdev); | ||
503 | unsigned int val; | ||
504 | |||
505 | mc13xxx_lock(priv->mc13xxx); | ||
506 | ret = mc13xxx_reg_read(priv->mc13xxx, mc13892_regulators[id].reg, &val); | ||
507 | mc13xxx_unlock(priv->mc13xxx); | ||
508 | |||
509 | if (ret) | ||
510 | return ret; | ||
511 | |||
512 | if (val & MC13892_REGULATORMODE1_VCAMCONFIGEN) | ||
513 | return REGULATOR_MODE_FAST; | ||
514 | |||
515 | return REGULATOR_MODE_NORMAL; | ||
516 | } | ||
517 | |||
518 | |||
519 | static int __devinit mc13892_regulator_probe(struct platform_device *pdev) | ||
520 | { | ||
521 | struct mc13xxx_regulator_priv *priv; | ||
522 | struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); | ||
523 | struct mc13xxx_regulator_platform_data *pdata = | ||
524 | dev_get_platdata(&pdev->dev); | ||
525 | struct mc13xxx_regulator_init_data *init_data; | ||
526 | int i, ret; | ||
527 | u32 val; | ||
528 | |||
529 | priv = kzalloc(sizeof(*priv) + | ||
530 | pdata->num_regulators * sizeof(priv->regulators[0]), | ||
531 | GFP_KERNEL); | ||
532 | if (!priv) | ||
533 | return -ENOMEM; | ||
534 | |||
535 | priv->mc13xxx_regulators = mc13892_regulators; | ||
536 | priv->mc13xxx = mc13892; | ||
537 | |||
538 | mc13xxx_lock(mc13892); | ||
539 | ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); | ||
540 | if (ret) | ||
541 | goto err_free; | ||
542 | |||
543 | /* enable switch auto mode */ | ||
544 | if ((val & 0x0000FFFF) == 0x45d0) { | ||
545 | ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4, | ||
546 | MC13892_SWITCHERS4_SW1MODE_M | | ||
547 | MC13892_SWITCHERS4_SW2MODE_M, | ||
548 | MC13892_SWITCHERS4_SW1MODE_AUTO | | ||
549 | MC13892_SWITCHERS4_SW2MODE_AUTO); | ||
550 | if (ret) | ||
551 | goto err_free; | ||
552 | |||
553 | ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5, | ||
554 | MC13892_SWITCHERS5_SW3MODE_M | | ||
555 | MC13892_SWITCHERS5_SW4MODE_M, | ||
556 | MC13892_SWITCHERS5_SW3MODE_AUTO | | ||
557 | MC13892_SWITCHERS5_SW4MODE_AUTO); | ||
558 | if (ret) | ||
559 | goto err_free; | ||
560 | } | ||
561 | mc13xxx_unlock(mc13892); | ||
562 | |||
563 | mc13892_regulators[MC13892_VCAM].desc.ops->set_mode | ||
564 | = mc13892_vcam_set_mode; | ||
565 | mc13892_regulators[MC13892_VCAM].desc.ops->get_mode | ||
566 | = mc13892_vcam_get_mode; | ||
567 | for (i = 0; i < pdata->num_regulators; i++) { | ||
568 | init_data = &pdata->regulators[i]; | ||
569 | priv->regulators[i] = regulator_register( | ||
570 | &mc13892_regulators[init_data->id].desc, | ||
571 | &pdev->dev, init_data->init_data, priv); | ||
572 | |||
573 | if (IS_ERR(priv->regulators[i])) { | ||
574 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
575 | mc13892_regulators[i].desc.name); | ||
576 | ret = PTR_ERR(priv->regulators[i]); | ||
577 | goto err; | ||
578 | } | ||
579 | } | ||
580 | |||
581 | platform_set_drvdata(pdev, priv); | ||
582 | |||
583 | return 0; | ||
584 | err: | ||
585 | while (--i >= 0) | ||
586 | regulator_unregister(priv->regulators[i]); | ||
587 | |||
588 | err_free: | ||
589 | mc13xxx_unlock(mc13892); | ||
590 | kfree(priv); | ||
591 | |||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | static int __devexit mc13892_regulator_remove(struct platform_device *pdev) | ||
596 | { | ||
597 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); | ||
598 | struct mc13xxx_regulator_platform_data *pdata = | ||
599 | dev_get_platdata(&pdev->dev); | ||
600 | int i; | ||
601 | |||
602 | platform_set_drvdata(pdev, NULL); | ||
603 | |||
604 | for (i = 0; i < pdata->num_regulators; i++) | ||
605 | regulator_unregister(priv->regulators[i]); | ||
606 | |||
607 | kfree(priv); | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static struct platform_driver mc13892_regulator_driver = { | ||
612 | .driver = { | ||
613 | .name = "mc13892-regulator", | ||
614 | .owner = THIS_MODULE, | ||
615 | }, | ||
616 | .remove = __devexit_p(mc13892_regulator_remove), | ||
617 | .probe = mc13892_regulator_probe, | ||
618 | }; | ||
619 | |||
620 | static int __init mc13892_regulator_init(void) | ||
621 | { | ||
622 | return platform_driver_register(&mc13892_regulator_driver); | ||
623 | } | ||
624 | subsys_initcall(mc13892_regulator_init); | ||
625 | |||
626 | static void __exit mc13892_regulator_exit(void) | ||
627 | { | ||
628 | platform_driver_unregister(&mc13892_regulator_driver); | ||
629 | } | ||
630 | module_exit(mc13892_regulator_exit); | ||
631 | |||
632 | MODULE_LICENSE("GPL v2"); | ||
633 | MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); | ||
634 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13892 PMIC"); | ||
635 | MODULE_ALIAS("platform:mc13892-regulator"); | ||
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c new file mode 100644 index 000000000000..f53d31b950d4 --- /dev/null +++ b/drivers/regulator/mc13xxx-regulator-core.c | |||
@@ -0,0 +1,241 @@ | |||
1 | /* | ||
2 | * Regulator Driver for Freescale MC13xxx PMIC | ||
3 | * | ||
4 | * Copyright 2010 Yong Shen <yong.shen@linaro.org> | ||
5 | * | ||
6 | * Based on mc13783 regulator driver : | ||
7 | * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> | ||
8 | * Copyright 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * Regs infos taken from mc13xxx drivers from freescale and mc13xxx.pdf file | ||
15 | * from freescale | ||
16 | */ | ||
17 | |||
18 | #include <linux/mfd/mc13xxx.h> | ||
19 | #include <linux/regulator/machine.h> | ||
20 | #include <linux/regulator/driver.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/err.h> | ||
26 | #include "mc13xxx.h" | ||
27 | |||
28 | static int mc13xxx_regulator_enable(struct regulator_dev *rdev) | ||
29 | { | ||
30 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
31 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
32 | int id = rdev_get_id(rdev); | ||
33 | int ret; | ||
34 | |||
35 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
36 | |||
37 | mc13xxx_lock(priv->mc13xxx); | ||
38 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg, | ||
39 | mc13xxx_regulators[id].enable_bit, | ||
40 | mc13xxx_regulators[id].enable_bit); | ||
41 | mc13xxx_unlock(priv->mc13xxx); | ||
42 | |||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | static int mc13xxx_regulator_disable(struct regulator_dev *rdev) | ||
47 | { | ||
48 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
49 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
50 | int id = rdev_get_id(rdev); | ||
51 | int ret; | ||
52 | |||
53 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
54 | |||
55 | mc13xxx_lock(priv->mc13xxx); | ||
56 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg, | ||
57 | mc13xxx_regulators[id].enable_bit, 0); | ||
58 | mc13xxx_unlock(priv->mc13xxx); | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev) | ||
64 | { | ||
65 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
66 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
67 | int ret, id = rdev_get_id(rdev); | ||
68 | unsigned int val; | ||
69 | |||
70 | mc13xxx_lock(priv->mc13xxx); | ||
71 | ret = mc13xxx_reg_read(priv->mc13xxx, mc13xxx_regulators[id].reg, &val); | ||
72 | mc13xxx_unlock(priv->mc13xxx); | ||
73 | |||
74 | if (ret) | ||
75 | return ret; | ||
76 | |||
77 | return (val & mc13xxx_regulators[id].enable_bit) != 0; | ||
78 | } | ||
79 | |||
80 | int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, | ||
81 | unsigned selector) | ||
82 | { | ||
83 | int id = rdev_get_id(rdev); | ||
84 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
85 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
86 | |||
87 | if (selector >= mc13xxx_regulators[id].desc.n_voltages) | ||
88 | return -EINVAL; | ||
89 | |||
90 | return mc13xxx_regulators[id].voltages[selector]; | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage); | ||
93 | |||
94 | int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev, | ||
95 | int min_uV, int max_uV) | ||
96 | { | ||
97 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
98 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
99 | int reg_id = rdev_get_id(rdev); | ||
100 | int i; | ||
101 | int bestmatch; | ||
102 | int bestindex; | ||
103 | |||
104 | /* | ||
105 | * Locate the minimum voltage fitting the criteria on | ||
106 | * this regulator. The switchable voltages are not | ||
107 | * in strict falling order so we need to check them | ||
108 | * all for the best match. | ||
109 | */ | ||
110 | bestmatch = INT_MAX; | ||
111 | bestindex = -1; | ||
112 | for (i = 0; i < mc13xxx_regulators[reg_id].desc.n_voltages; i++) { | ||
113 | if (mc13xxx_regulators[reg_id].voltages[i] >= min_uV && | ||
114 | mc13xxx_regulators[reg_id].voltages[i] < bestmatch) { | ||
115 | bestmatch = mc13xxx_regulators[reg_id].voltages[i]; | ||
116 | bestindex = i; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | if (bestindex < 0 || bestmatch > max_uV) { | ||
121 | dev_warn(&rdev->dev, "no possible value for %d<=x<=%d uV\n", | ||
122 | min_uV, max_uV); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | return bestindex; | ||
126 | } | ||
127 | EXPORT_SYMBOL_GPL(mc13xxx_get_best_voltage_index); | ||
128 | |||
129 | static int mc13xxx_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, | ||
130 | int max_uV, unsigned *selector) | ||
131 | { | ||
132 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
133 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
134 | int value, id = rdev_get_id(rdev); | ||
135 | int ret; | ||
136 | |||
137 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | ||
138 | __func__, id, min_uV, max_uV); | ||
139 | |||
140 | /* Find the best index */ | ||
141 | value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV); | ||
142 | dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value); | ||
143 | if (value < 0) | ||
144 | return value; | ||
145 | |||
146 | mc13xxx_lock(priv->mc13xxx); | ||
147 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg, | ||
148 | mc13xxx_regulators[id].vsel_mask, | ||
149 | value << mc13xxx_regulators[id].vsel_shift); | ||
150 | mc13xxx_unlock(priv->mc13xxx); | ||
151 | |||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev) | ||
156 | { | ||
157 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
158 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
159 | int ret, id = rdev_get_id(rdev); | ||
160 | unsigned int val; | ||
161 | |||
162 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
163 | |||
164 | mc13xxx_lock(priv->mc13xxx); | ||
165 | ret = mc13xxx_reg_read(priv->mc13xxx, | ||
166 | mc13xxx_regulators[id].vsel_reg, &val); | ||
167 | mc13xxx_unlock(priv->mc13xxx); | ||
168 | |||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | val = (val & mc13xxx_regulators[id].vsel_mask) | ||
173 | >> mc13xxx_regulators[id].vsel_shift; | ||
174 | |||
175 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); | ||
176 | |||
177 | BUG_ON(val < 0 || val > mc13xxx_regulators[id].desc.n_voltages); | ||
178 | |||
179 | return mc13xxx_regulators[id].voltages[val]; | ||
180 | } | ||
181 | |||
182 | struct regulator_ops mc13xxx_regulator_ops = { | ||
183 | .enable = mc13xxx_regulator_enable, | ||
184 | .disable = mc13xxx_regulator_disable, | ||
185 | .is_enabled = mc13xxx_regulator_is_enabled, | ||
186 | .list_voltage = mc13xxx_regulator_list_voltage, | ||
187 | .set_voltage = mc13xxx_regulator_set_voltage, | ||
188 | .get_voltage = mc13xxx_regulator_get_voltage, | ||
189 | }; | ||
190 | EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops); | ||
191 | |||
192 | int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, | ||
193 | int max_uV, unsigned *selector) | ||
194 | { | ||
195 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
196 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
197 | int id = rdev_get_id(rdev); | ||
198 | |||
199 | dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n", | ||
200 | __func__, id, min_uV, max_uV); | ||
201 | |||
202 | if (min_uV >= mc13xxx_regulators[id].voltages[0] && | ||
203 | max_uV <= mc13xxx_regulators[id].voltages[0]) | ||
204 | return 0; | ||
205 | else | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage); | ||
209 | |||
210 | int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev) | ||
211 | { | ||
212 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | ||
213 | struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators; | ||
214 | int id = rdev_get_id(rdev); | ||
215 | |||
216 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | ||
217 | |||
218 | return mc13xxx_regulators[id].voltages[0]; | ||
219 | } | ||
220 | EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage); | ||
221 | |||
222 | struct regulator_ops mc13xxx_fixed_regulator_ops = { | ||
223 | .enable = mc13xxx_regulator_enable, | ||
224 | .disable = mc13xxx_regulator_disable, | ||
225 | .is_enabled = mc13xxx_regulator_is_enabled, | ||
226 | .list_voltage = mc13xxx_regulator_list_voltage, | ||
227 | .set_voltage = mc13xxx_fixed_regulator_set_voltage, | ||
228 | .get_voltage = mc13xxx_fixed_regulator_get_voltage, | ||
229 | }; | ||
230 | EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); | ||
231 | |||
232 | int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev) | ||
233 | { | ||
234 | return 1; | ||
235 | } | ||
236 | EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled); | ||
237 | |||
238 | MODULE_LICENSE("GPL v2"); | ||
239 | MODULE_AUTHOR("Yong Shen <yong.shen@linaro.org>"); | ||
240 | MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC"); | ||
241 | MODULE_ALIAS("mc13xxx-regulator-core"); | ||
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h new file mode 100644 index 000000000000..27758267e122 --- /dev/null +++ b/drivers/regulator/mc13xxx.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * mc13xxx.h - regulators for the Freescale mc13xxx PMIC | ||
3 | * | ||
4 | * Copyright (C) 2010 Yong Shen <yong.shen@linaro.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __LINUX_REGULATOR_MC13XXX_H | ||
13 | #define __LINUX_REGULATOR_MC13XXX_H | ||
14 | |||
15 | #include <linux/regulator/driver.h> | ||
16 | |||
17 | struct mc13xxx_regulator { | ||
18 | struct regulator_desc desc; | ||
19 | int reg; | ||
20 | int enable_bit; | ||
21 | int vsel_reg; | ||
22 | int vsel_shift; | ||
23 | int vsel_mask; | ||
24 | int hi_bit; | ||
25 | int const *voltages; | ||
26 | }; | ||
27 | |||
28 | struct mc13xxx_regulator_priv { | ||
29 | struct mc13xxx *mc13xxx; | ||
30 | u32 powermisc_pwgt_state; | ||
31 | struct mc13xxx_regulator *mc13xxx_regulators; | ||
32 | struct regulator_dev *regulators[]; | ||
33 | }; | ||
34 | |||
35 | extern int mc13xxx_sw_regulator(struct regulator_dev *rdev); | ||
36 | extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev); | ||
37 | extern int mc13xxx_get_best_voltage_index(struct regulator_dev *rdev, | ||
38 | int min_uV, int max_uV); | ||
39 | extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev, | ||
40 | unsigned selector); | ||
41 | extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, | ||
42 | int min_uV, int max_uV, unsigned *selector); | ||
43 | extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev); | ||
44 | |||
45 | extern struct regulator_ops mc13xxx_regulator_ops; | ||
46 | extern struct regulator_ops mc13xxx_fixed_regulator_ops; | ||
47 | |||
48 | #define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \ | ||
49 | [prefix ## _name] = { \ | ||
50 | .desc = { \ | ||
51 | .name = #prefix "_" #_name, \ | ||
52 | .n_voltages = ARRAY_SIZE(_voltages), \ | ||
53 | .ops = &_ops, \ | ||
54 | .type = REGULATOR_VOLTAGE, \ | ||
55 | .id = prefix ## _name, \ | ||
56 | .owner = THIS_MODULE, \ | ||
57 | }, \ | ||
58 | .reg = prefix ## _reg, \ | ||
59 | .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ | ||
60 | .vsel_reg = prefix ## _vsel_reg, \ | ||
61 | .vsel_shift = prefix ## _vsel_reg ## _ ## _name ## VSEL,\ | ||
62 | .vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\ | ||
63 | .voltages = _voltages, \ | ||
64 | } | ||
65 | |||
66 | #define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \ | ||
67 | [prefix ## _name] = { \ | ||
68 | .desc = { \ | ||
69 | .name = #prefix "_" #_name, \ | ||
70 | .n_voltages = ARRAY_SIZE(_voltages), \ | ||
71 | .ops = &_ops, \ | ||
72 | .type = REGULATOR_VOLTAGE, \ | ||
73 | .id = prefix ## _name, \ | ||
74 | .owner = THIS_MODULE, \ | ||
75 | }, \ | ||
76 | .reg = prefix ## _reg, \ | ||
77 | .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ | ||
78 | .voltages = _voltages, \ | ||
79 | } | ||
80 | |||
81 | #define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \ | ||
82 | [prefix ## _name] = { \ | ||
83 | .desc = { \ | ||
84 | .name = #prefix "_" #_name, \ | ||
85 | .n_voltages = ARRAY_SIZE(_voltages), \ | ||
86 | .ops = &_ops, \ | ||
87 | .type = REGULATOR_VOLTAGE, \ | ||
88 | .id = prefix ## _name, \ | ||
89 | .owner = THIS_MODULE, \ | ||
90 | }, \ | ||
91 | .reg = prefix ## _reg, \ | ||
92 | .enable_bit = prefix ## _reg ## _ ## _name ## EN, \ | ||
93 | .voltages = _voltages, \ | ||
94 | } | ||
95 | |||
96 | #define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops) \ | ||
97 | MC13xxx_DEFINE(SW, _name, _reg, _vsel_reg, _voltages, ops) | ||
98 | #define MC13xxx_DEFINE_REGU(_name, _reg, _vsel_reg, _voltages, ops) \ | ||
99 | MC13xxx_DEFINE(REGU, _name, _reg, _vsel_reg, _voltages, ops) | ||
100 | |||
101 | #endif | ||
diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 29d0566379ae..31f6e11a7f16 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c | |||
@@ -151,7 +151,8 @@ static struct pcap_regulator vreg_table[] = { | |||
151 | }; | 151 | }; |
152 | 152 | ||
153 | static int pcap_regulator_set_voltage(struct regulator_dev *rdev, | 153 | static int pcap_regulator_set_voltage(struct regulator_dev *rdev, |
154 | int min_uV, int max_uV) | 154 | int min_uV, int max_uV, |
155 | unsigned *selector) | ||
155 | { | 156 | { |
156 | struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; | 157 | struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)]; |
157 | void *pcap = rdev_get_drvdata(rdev); | 158 | void *pcap = rdev_get_drvdata(rdev); |
@@ -170,10 +171,12 @@ static int pcap_regulator_set_voltage(struct regulator_dev *rdev, | |||
170 | i = 0; | 171 | i = 0; |
171 | 172 | ||
172 | uV = vreg->voltage_table[i] * 1000; | 173 | uV = vreg->voltage_table[i] * 1000; |
173 | if (min_uV <= uV && uV <= max_uV) | 174 | if (min_uV <= uV && uV <= max_uV) { |
175 | *selector = i; | ||
174 | return ezx_pcap_set_bits(pcap, vreg->reg, | 176 | return ezx_pcap_set_bits(pcap, vreg->reg, |
175 | (vreg->n_voltages - 1) << vreg->index, | 177 | (vreg->n_voltages - 1) << vreg->index, |
176 | i << vreg->index); | 178 | i << vreg->index); |
179 | } | ||
177 | 180 | ||
178 | if (i == 0 && rdev_get_id(rdev) == V1) | 181 | if (i == 0 && rdev_get_id(rdev) == V1) |
179 | i = vreg->n_voltages - 1; | 182 | i = vreg->n_voltages - 1; |
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index c8f41dc05b76..69a11d9dd87f 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c | |||
@@ -108,7 +108,8 @@ static unsigned int ldo_voltage_value(u8 bits) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, | 110 | static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, |
111 | int min_uV, int max_uV) | 111 | int min_uV, int max_uV, |
112 | unsigned *selector) | ||
112 | { | 113 | { |
113 | struct pcf50633 *pcf; | 114 | struct pcf50633 *pcf; |
114 | int regulator_id, millivolts; | 115 | int regulator_id, millivolts; |
@@ -147,6 +148,8 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, | |||
147 | return -EINVAL; | 148 | return -EINVAL; |
148 | } | 149 | } |
149 | 150 | ||
151 | *selector = volt_bits; | ||
152 | |||
150 | return pcf50633_reg_write(pcf, regnr, volt_bits); | 153 | return pcf50633_reg_write(pcf, regnr, volt_bits); |
151 | } | 154 | } |
152 | 155 | ||
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index cd6d4fc9d74f..60a7ca5409e9 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c | |||
@@ -321,7 +321,8 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) | |||
321 | } | 321 | } |
322 | 322 | ||
323 | static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, | 323 | static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, |
324 | int min_uV, int max_uV) | 324 | int min_uV, int max_uV, |
325 | unsigned *selector) | ||
325 | { | 326 | { |
326 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 327 | struct tps_pmic *tps = rdev_get_drvdata(dev); |
327 | int dcdc = rdev_get_id(dev); | 328 | int dcdc = rdev_get_id(dev); |
@@ -346,6 +347,8 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, | |||
346 | break; | 347 | break; |
347 | } | 348 | } |
348 | 349 | ||
350 | *selector = vsel; | ||
351 | |||
349 | /* write to the register in case we found a match */ | 352 | /* write to the register in case we found a match */ |
350 | if (vsel == tps->info[dcdc]->table_len) | 353 | if (vsel == tps->info[dcdc]->table_len) |
351 | return -EINVAL; | 354 | return -EINVAL; |
@@ -371,7 +374,7 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev) | |||
371 | } | 374 | } |
372 | 375 | ||
373 | static int tps65023_ldo_set_voltage(struct regulator_dev *dev, | 376 | static int tps65023_ldo_set_voltage(struct regulator_dev *dev, |
374 | int min_uV, int max_uV) | 377 | int min_uV, int max_uV, unsigned *selector) |
375 | { | 378 | { |
376 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 379 | struct tps_pmic *tps = rdev_get_drvdata(dev); |
377 | int data, vsel, ldo = rdev_get_id(dev); | 380 | int data, vsel, ldo = rdev_get_id(dev); |
@@ -396,6 +399,8 @@ static int tps65023_ldo_set_voltage(struct regulator_dev *dev, | |||
396 | if (vsel == tps->info[ldo]->table_len) | 399 | if (vsel == tps->info[ldo]->table_len) |
397 | return -EINVAL; | 400 | return -EINVAL; |
398 | 401 | ||
402 | *selector = vsel; | ||
403 | |||
399 | data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); | 404 | data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); |
400 | if (data < 0) | 405 | if (data < 0) |
401 | return data; | 406 | return data; |
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 020f5878d7ff..064755290599 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -369,7 +369,8 @@ static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev) | |||
369 | } | 369 | } |
370 | 370 | ||
371 | static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, | 371 | static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, |
372 | int min_uV, int max_uV) | 372 | int min_uV, int max_uV, |
373 | unsigned *selector) | ||
373 | { | 374 | { |
374 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); | 375 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
375 | int data, vsel, dcdc = rdev_get_id(dev); | 376 | int data, vsel, dcdc = rdev_get_id(dev); |
@@ -415,6 +416,8 @@ static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, | |||
415 | if (vsel == tps->info[dcdc]->table_len) | 416 | if (vsel == tps->info[dcdc]->table_len) |
416 | return -EINVAL; | 417 | return -EINVAL; |
417 | 418 | ||
419 | *selector = vsel; | ||
420 | |||
418 | data = tps6507x_pmic_reg_read(tps, reg); | 421 | data = tps6507x_pmic_reg_read(tps, reg); |
419 | if (data < 0) | 422 | if (data < 0) |
420 | return data; | 423 | return data; |
@@ -450,7 +453,8 @@ static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev) | |||
450 | } | 453 | } |
451 | 454 | ||
452 | static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev, | 455 | static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev, |
453 | int min_uV, int max_uV) | 456 | int min_uV, int max_uV, |
457 | unsigned *selector) | ||
454 | { | 458 | { |
455 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); | 459 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
456 | int data, vsel, ldo = rdev_get_id(dev); | 460 | int data, vsel, ldo = rdev_get_id(dev); |
@@ -483,6 +487,8 @@ static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev, | |||
483 | if (vsel == tps->info[ldo]->table_len) | 487 | if (vsel == tps->info[ldo]->table_len) |
484 | return -EINVAL; | 488 | return -EINVAL; |
485 | 489 | ||
490 | *selector = vsel; | ||
491 | |||
486 | data = tps6507x_pmic_reg_read(tps, reg); | 492 | data = tps6507x_pmic_reg_read(tps, reg); |
487 | if (data < 0) | 493 | if (data < 0) |
488 | return data; | 494 | return data; |
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c new file mode 100644 index 000000000000..176a6be5a8ce --- /dev/null +++ b/drivers/regulator/tps6524x-regulator.c | |||
@@ -0,0 +1,693 @@ | |||
1 | /* | ||
2 | * Regulator driver for TPS6524x PMIC | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
11 | * whether express or implied; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/regulator/driver.h> | ||
23 | #include <linux/regulator/machine.h> | ||
24 | |||
25 | #define REG_LDO_SET 0x0 | ||
26 | #define LDO_ILIM_MASK 1 /* 0 = 400-800, 1 = 900-1500 */ | ||
27 | #define LDO_VSEL_MASK 0x0f | ||
28 | #define LDO2_ILIM_SHIFT 12 | ||
29 | #define LDO2_VSEL_SHIFT 4 | ||
30 | #define LDO1_ILIM_SHIFT 8 | ||
31 | #define LDO1_VSEL_SHIFT 0 | ||
32 | |||
33 | #define REG_BLOCK_EN 0x1 | ||
34 | #define BLOCK_MASK 1 | ||
35 | #define BLOCK_LDO1_SHIFT 0 | ||
36 | #define BLOCK_LDO2_SHIFT 1 | ||
37 | #define BLOCK_LCD_SHIFT 2 | ||
38 | #define BLOCK_USB_SHIFT 3 | ||
39 | |||
40 | #define REG_DCDC_SET 0x2 | ||
41 | #define DCDC_VDCDC_MASK 0x1f | ||
42 | #define DCDC_VDCDC1_SHIFT 0 | ||
43 | #define DCDC_VDCDC2_SHIFT 5 | ||
44 | #define DCDC_VDCDC3_SHIFT 10 | ||
45 | |||
46 | #define REG_DCDC_EN 0x3 | ||
47 | #define DCDCDCDC_EN_MASK 0x1 | ||
48 | #define DCDCDCDC1_EN_SHIFT 0 | ||
49 | #define DCDCDCDC1_PG_MSK BIT(1) | ||
50 | #define DCDCDCDC2_EN_SHIFT 2 | ||
51 | #define DCDCDCDC2_PG_MSK BIT(3) | ||
52 | #define DCDCDCDC3_EN_SHIFT 4 | ||
53 | #define DCDCDCDC3_PG_MSK BIT(5) | ||
54 | |||
55 | #define REG_USB 0x4 | ||
56 | #define USB_ILIM_SHIFT 0 | ||
57 | #define USB_ILIM_MASK 0x3 | ||
58 | #define USB_TSD_SHIFT 2 | ||
59 | #define USB_TSD_MASK 0x3 | ||
60 | #define USB_TWARN_SHIFT 4 | ||
61 | #define USB_TWARN_MASK 0x3 | ||
62 | #define USB_IWARN_SD BIT(6) | ||
63 | #define USB_FAST_LOOP BIT(7) | ||
64 | |||
65 | #define REG_ALARM 0x5 | ||
66 | #define ALARM_LDO1 BIT(0) | ||
67 | #define ALARM_DCDC1 BIT(1) | ||
68 | #define ALARM_DCDC2 BIT(2) | ||
69 | #define ALARM_DCDC3 BIT(3) | ||
70 | #define ALARM_LDO2 BIT(4) | ||
71 | #define ALARM_USB_WARN BIT(5) | ||
72 | #define ALARM_USB_ALARM BIT(6) | ||
73 | #define ALARM_LCD BIT(9) | ||
74 | #define ALARM_TEMP_WARM BIT(10) | ||
75 | #define ALARM_TEMP_HOT BIT(11) | ||
76 | #define ALARM_NRST BIT(14) | ||
77 | #define ALARM_POWERUP BIT(15) | ||
78 | |||
79 | #define REG_INT_ENABLE 0x6 | ||
80 | #define INT_LDO1 BIT(0) | ||
81 | #define INT_DCDC1 BIT(1) | ||
82 | #define INT_DCDC2 BIT(2) | ||
83 | #define INT_DCDC3 BIT(3) | ||
84 | #define INT_LDO2 BIT(4) | ||
85 | #define INT_USB_WARN BIT(5) | ||
86 | #define INT_USB_ALARM BIT(6) | ||
87 | #define INT_LCD BIT(9) | ||
88 | #define INT_TEMP_WARM BIT(10) | ||
89 | #define INT_TEMP_HOT BIT(11) | ||
90 | #define INT_GLOBAL_EN BIT(15) | ||
91 | |||
92 | #define REG_INT_STATUS 0x7 | ||
93 | #define STATUS_LDO1 BIT(0) | ||
94 | #define STATUS_DCDC1 BIT(1) | ||
95 | #define STATUS_DCDC2 BIT(2) | ||
96 | #define STATUS_DCDC3 BIT(3) | ||
97 | #define STATUS_LDO2 BIT(4) | ||
98 | #define STATUS_USB_WARN BIT(5) | ||
99 | #define STATUS_USB_ALARM BIT(6) | ||
100 | #define STATUS_LCD BIT(9) | ||
101 | #define STATUS_TEMP_WARM BIT(10) | ||
102 | #define STATUS_TEMP_HOT BIT(11) | ||
103 | |||
104 | #define REG_SOFTWARE_RESET 0xb | ||
105 | #define REG_WRITE_ENABLE 0xd | ||
106 | #define REG_REV_ID 0xf | ||
107 | |||
108 | #define N_DCDC 3 | ||
109 | #define N_LDO 2 | ||
110 | #define N_SWITCH 2 | ||
111 | #define N_REGULATORS (3 /* DCDC */ + \ | ||
112 | 2 /* LDO */ + \ | ||
113 | 2 /* switch */) | ||
114 | |||
115 | #define FIXED_ILIMSEL BIT(0) | ||
116 | #define FIXED_VOLTAGE BIT(1) | ||
117 | |||
118 | #define CMD_READ(reg) ((reg) << 6) | ||
119 | #define CMD_WRITE(reg) (BIT(5) | (reg) << 6) | ||
120 | #define STAT_CLK BIT(3) | ||
121 | #define STAT_WRITE BIT(2) | ||
122 | #define STAT_INVALID BIT(1) | ||
123 | #define STAT_WP BIT(0) | ||
124 | |||
125 | struct field { | ||
126 | int reg; | ||
127 | int shift; | ||
128 | int mask; | ||
129 | }; | ||
130 | |||
131 | struct supply_info { | ||
132 | const char *name; | ||
133 | int n_voltages; | ||
134 | const int *voltages; | ||
135 | int fixed_voltage; | ||
136 | int n_ilimsels; | ||
137 | const int *ilimsels; | ||
138 | int fixed_ilimsel; | ||
139 | int flags; | ||
140 | struct field enable, voltage, ilimsel; | ||
141 | }; | ||
142 | |||
143 | struct tps6524x { | ||
144 | struct device *dev; | ||
145 | struct spi_device *spi; | ||
146 | struct mutex lock; | ||
147 | struct regulator_desc desc[N_REGULATORS]; | ||
148 | struct regulator_dev *rdev[N_REGULATORS]; | ||
149 | }; | ||
150 | |||
151 | static int __read_reg(struct tps6524x *hw, int reg) | ||
152 | { | ||
153 | int error = 0; | ||
154 | u16 cmd = CMD_READ(reg), in; | ||
155 | u8 status; | ||
156 | struct spi_message m; | ||
157 | struct spi_transfer t[3]; | ||
158 | |||
159 | spi_message_init(&m); | ||
160 | memset(t, 0, sizeof(t)); | ||
161 | |||
162 | t[0].tx_buf = &cmd; | ||
163 | t[0].len = 2; | ||
164 | t[0].bits_per_word = 12; | ||
165 | spi_message_add_tail(&t[0], &m); | ||
166 | |||
167 | t[1].rx_buf = ∈ | ||
168 | t[1].len = 2; | ||
169 | t[1].bits_per_word = 16; | ||
170 | spi_message_add_tail(&t[1], &m); | ||
171 | |||
172 | t[2].rx_buf = &status; | ||
173 | t[2].len = 1; | ||
174 | t[2].bits_per_word = 4; | ||
175 | spi_message_add_tail(&t[2], &m); | ||
176 | |||
177 | error = spi_sync(hw->spi, &m); | ||
178 | if (error < 0) | ||
179 | return error; | ||
180 | |||
181 | dev_dbg(hw->dev, "read reg %d, data %x, status %x\n", | ||
182 | reg, in, status); | ||
183 | |||
184 | if (!(status & STAT_CLK) || (status & STAT_WRITE)) | ||
185 | return -EIO; | ||
186 | |||
187 | if (status & STAT_INVALID) | ||
188 | return -EINVAL; | ||
189 | |||
190 | return in; | ||
191 | } | ||
192 | |||
193 | static int read_reg(struct tps6524x *hw, int reg) | ||
194 | { | ||
195 | int ret; | ||
196 | |||
197 | mutex_lock(&hw->lock); | ||
198 | ret = __read_reg(hw, reg); | ||
199 | mutex_unlock(&hw->lock); | ||
200 | |||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static int __write_reg(struct tps6524x *hw, int reg, int val) | ||
205 | { | ||
206 | int error = 0; | ||
207 | u16 cmd = CMD_WRITE(reg), out = val; | ||
208 | u8 status; | ||
209 | struct spi_message m; | ||
210 | struct spi_transfer t[3]; | ||
211 | |||
212 | spi_message_init(&m); | ||
213 | memset(t, 0, sizeof(t)); | ||
214 | |||
215 | t[0].tx_buf = &cmd; | ||
216 | t[0].len = 2; | ||
217 | t[0].bits_per_word = 12; | ||
218 | spi_message_add_tail(&t[0], &m); | ||
219 | |||
220 | t[1].tx_buf = &out; | ||
221 | t[1].len = 2; | ||
222 | t[1].bits_per_word = 16; | ||
223 | spi_message_add_tail(&t[1], &m); | ||
224 | |||
225 | t[2].rx_buf = &status; | ||
226 | t[2].len = 1; | ||
227 | t[2].bits_per_word = 4; | ||
228 | spi_message_add_tail(&t[2], &m); | ||
229 | |||
230 | error = spi_sync(hw->spi, &m); | ||
231 | if (error < 0) | ||
232 | return error; | ||
233 | |||
234 | dev_dbg(hw->dev, "wrote reg %d, data %x, status %x\n", | ||
235 | reg, out, status); | ||
236 | |||
237 | if (!(status & STAT_CLK) || !(status & STAT_WRITE)) | ||
238 | return -EIO; | ||
239 | |||
240 | if (status & (STAT_INVALID | STAT_WP)) | ||
241 | return -EINVAL; | ||
242 | |||
243 | return error; | ||
244 | } | ||
245 | |||
246 | static int __rmw_reg(struct tps6524x *hw, int reg, int mask, int val) | ||
247 | { | ||
248 | int ret; | ||
249 | |||
250 | ret = __read_reg(hw, reg); | ||
251 | if (ret < 0) | ||
252 | return ret; | ||
253 | |||
254 | ret &= ~mask; | ||
255 | ret |= val; | ||
256 | |||
257 | ret = __write_reg(hw, reg, ret); | ||
258 | |||
259 | return (ret < 0) ? ret : 0; | ||
260 | } | ||
261 | |||
262 | static int rmw_protect(struct tps6524x *hw, int reg, int mask, int val) | ||
263 | { | ||
264 | int ret; | ||
265 | |||
266 | mutex_lock(&hw->lock); | ||
267 | |||
268 | ret = __write_reg(hw, REG_WRITE_ENABLE, 1); | ||
269 | if (ret) { | ||
270 | dev_err(hw->dev, "failed to set write enable\n"); | ||
271 | goto error; | ||
272 | } | ||
273 | |||
274 | ret = __rmw_reg(hw, reg, mask, val); | ||
275 | if (ret) | ||
276 | dev_err(hw->dev, "failed to rmw register %d\n", reg); | ||
277 | |||
278 | ret = __write_reg(hw, REG_WRITE_ENABLE, 0); | ||
279 | if (ret) { | ||
280 | dev_err(hw->dev, "failed to clear write enable\n"); | ||
281 | goto error; | ||
282 | } | ||
283 | |||
284 | error: | ||
285 | mutex_unlock(&hw->lock); | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | static int read_field(struct tps6524x *hw, const struct field *field) | ||
291 | { | ||
292 | int tmp; | ||
293 | |||
294 | tmp = read_reg(hw, field->reg); | ||
295 | if (tmp < 0) | ||
296 | return tmp; | ||
297 | |||
298 | return (tmp >> field->shift) & field->mask; | ||
299 | } | ||
300 | |||
301 | static int write_field(struct tps6524x *hw, const struct field *field, | ||
302 | int val) | ||
303 | { | ||
304 | if (val & ~field->mask) | ||
305 | return -EOVERFLOW; | ||
306 | |||
307 | return rmw_protect(hw, field->reg, | ||
308 | field->mask << field->shift, | ||
309 | val << field->shift); | ||
310 | } | ||
311 | |||
312 | static const int dcdc1_voltages[] = { | ||
313 | 800000, 825000, 850000, 875000, | ||
314 | 900000, 925000, 950000, 975000, | ||
315 | 1000000, 1025000, 1050000, 1075000, | ||
316 | 1100000, 1125000, 1150000, 1175000, | ||
317 | 1200000, 1225000, 1250000, 1275000, | ||
318 | 1300000, 1325000, 1350000, 1375000, | ||
319 | 1400000, 1425000, 1450000, 1475000, | ||
320 | 1500000, 1525000, 1550000, 1575000, | ||
321 | }; | ||
322 | |||
323 | static const int dcdc2_voltages[] = { | ||
324 | 1400000, 1450000, 1500000, 1550000, | ||
325 | 1600000, 1650000, 1700000, 1750000, | ||
326 | 1800000, 1850000, 1900000, 1950000, | ||
327 | 2000000, 2050000, 2100000, 2150000, | ||
328 | 2200000, 2250000, 2300000, 2350000, | ||
329 | 2400000, 2450000, 2500000, 2550000, | ||
330 | 2600000, 2650000, 2700000, 2750000, | ||
331 | 2800000, 2850000, 2900000, 2950000, | ||
332 | }; | ||
333 | |||
334 | static const int dcdc3_voltages[] = { | ||
335 | 2400000, 2450000, 2500000, 2550000, 2600000, | ||
336 | 2650000, 2700000, 2750000, 2800000, 2850000, | ||
337 | 2900000, 2950000, 3000000, 3050000, 3100000, | ||
338 | 3150000, 3200000, 3250000, 3300000, 3350000, | ||
339 | 3400000, 3450000, 3500000, 3550000, 3600000, | ||
340 | }; | ||
341 | |||
342 | static const int ldo1_voltages[] = { | ||
343 | 4300000, 4350000, 4400000, 4450000, | ||
344 | 4500000, 4550000, 4600000, 4650000, | ||
345 | 4700000, 4750000, 4800000, 4850000, | ||
346 | 4900000, 4950000, 5000000, 5050000, | ||
347 | }; | ||
348 | |||
349 | static const int ldo2_voltages[] = { | ||
350 | 1100000, 1150000, 1200000, 1250000, | ||
351 | 1300000, 1700000, 1750000, 1800000, | ||
352 | 1850000, 1900000, 3150000, 3200000, | ||
353 | 3250000, 3300000, 3350000, 3400000, | ||
354 | }; | ||
355 | |||
356 | static const int ldo_ilimsel[] = { | ||
357 | 400000, 1500000 | ||
358 | }; | ||
359 | |||
360 | static const int usb_ilimsel[] = { | ||
361 | 200000, 400000, 800000, 1000000 | ||
362 | }; | ||
363 | |||
364 | #define __MK_FIELD(_reg, _mask, _shift) \ | ||
365 | { .reg = (_reg), .mask = (_mask), .shift = (_shift), } | ||
366 | |||
367 | static const struct supply_info supply_info[N_REGULATORS] = { | ||
368 | { | ||
369 | .name = "DCDC1", | ||
370 | .flags = FIXED_ILIMSEL, | ||
371 | .n_voltages = ARRAY_SIZE(dcdc1_voltages), | ||
372 | .voltages = dcdc1_voltages, | ||
373 | .fixed_ilimsel = 2400000, | ||
374 | .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK, | ||
375 | DCDCDCDC1_EN_SHIFT), | ||
376 | .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, | ||
377 | DCDC_VDCDC1_SHIFT), | ||
378 | }, | ||
379 | { | ||
380 | .name = "DCDC2", | ||
381 | .flags = FIXED_ILIMSEL, | ||
382 | .n_voltages = ARRAY_SIZE(dcdc2_voltages), | ||
383 | .voltages = dcdc2_voltages, | ||
384 | .fixed_ilimsel = 1200000, | ||
385 | .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK, | ||
386 | DCDCDCDC2_EN_SHIFT), | ||
387 | .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, | ||
388 | DCDC_VDCDC2_SHIFT), | ||
389 | }, | ||
390 | { | ||
391 | .name = "DCDC3", | ||
392 | .flags = FIXED_ILIMSEL, | ||
393 | .n_voltages = ARRAY_SIZE(dcdc3_voltages), | ||
394 | .voltages = dcdc3_voltages, | ||
395 | .fixed_ilimsel = 1200000, | ||
396 | .enable = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK, | ||
397 | DCDCDCDC3_EN_SHIFT), | ||
398 | .voltage = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK, | ||
399 | DCDC_VDCDC3_SHIFT), | ||
400 | }, | ||
401 | { | ||
402 | .name = "LDO1", | ||
403 | .n_voltages = ARRAY_SIZE(ldo1_voltages), | ||
404 | .voltages = ldo1_voltages, | ||
405 | .n_ilimsels = ARRAY_SIZE(ldo_ilimsel), | ||
406 | .ilimsels = ldo_ilimsel, | ||
407 | .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, | ||
408 | BLOCK_LDO1_SHIFT), | ||
409 | .voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK, | ||
410 | LDO1_VSEL_SHIFT), | ||
411 | .ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK, | ||
412 | LDO1_ILIM_SHIFT), | ||
413 | }, | ||
414 | { | ||
415 | .name = "LDO2", | ||
416 | .n_voltages = ARRAY_SIZE(ldo2_voltages), | ||
417 | .voltages = ldo2_voltages, | ||
418 | .n_ilimsels = ARRAY_SIZE(ldo_ilimsel), | ||
419 | .ilimsels = ldo_ilimsel, | ||
420 | .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, | ||
421 | BLOCK_LDO2_SHIFT), | ||
422 | .voltage = __MK_FIELD(REG_LDO_SET, LDO_VSEL_MASK, | ||
423 | LDO2_VSEL_SHIFT), | ||
424 | .ilimsel = __MK_FIELD(REG_LDO_SET, LDO_ILIM_MASK, | ||
425 | LDO2_ILIM_SHIFT), | ||
426 | }, | ||
427 | { | ||
428 | .name = "USB", | ||
429 | .flags = FIXED_VOLTAGE, | ||
430 | .fixed_voltage = 5000000, | ||
431 | .n_ilimsels = ARRAY_SIZE(usb_ilimsel), | ||
432 | .ilimsels = usb_ilimsel, | ||
433 | .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, | ||
434 | BLOCK_USB_SHIFT), | ||
435 | .ilimsel = __MK_FIELD(REG_USB, USB_ILIM_MASK, | ||
436 | USB_ILIM_SHIFT), | ||
437 | }, | ||
438 | { | ||
439 | .name = "LCD", | ||
440 | .flags = FIXED_VOLTAGE | FIXED_ILIMSEL, | ||
441 | .fixed_voltage = 5000000, | ||
442 | .fixed_ilimsel = 400000, | ||
443 | .enable = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK, | ||
444 | BLOCK_LCD_SHIFT), | ||
445 | }, | ||
446 | }; | ||
447 | |||
448 | static int list_voltage(struct regulator_dev *rdev, unsigned selector) | ||
449 | { | ||
450 | const struct supply_info *info; | ||
451 | struct tps6524x *hw; | ||
452 | |||
453 | hw = rdev_get_drvdata(rdev); | ||
454 | info = &supply_info[rdev_get_id(rdev)]; | ||
455 | |||
456 | if (info->flags & FIXED_VOLTAGE) | ||
457 | return selector ? -EINVAL : info->fixed_voltage; | ||
458 | |||
459 | return ((selector < info->n_voltages) ? | ||
460 | info->voltages[selector] : -EINVAL); | ||
461 | } | ||
462 | |||
463 | static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, | ||
464 | unsigned *selector) | ||
465 | { | ||
466 | const struct supply_info *info; | ||
467 | struct tps6524x *hw; | ||
468 | unsigned i; | ||
469 | |||
470 | hw = rdev_get_drvdata(rdev); | ||
471 | info = &supply_info[rdev_get_id(rdev)]; | ||
472 | |||
473 | if (info->flags & FIXED_VOLTAGE) | ||
474 | return -EINVAL; | ||
475 | |||
476 | for (i = 0; i < info->n_voltages; i++) | ||
477 | if (min_uV <= info->voltages[i] && | ||
478 | max_uV >= info->voltages[i]) | ||
479 | break; | ||
480 | |||
481 | if (i >= info->n_voltages) | ||
482 | i = info->n_voltages - 1; | ||
483 | |||
484 | *selector = info->voltages[i]; | ||
485 | |||
486 | return write_field(hw, &info->voltage, i); | ||
487 | } | ||
488 | |||
489 | static int get_voltage(struct regulator_dev *rdev) | ||
490 | { | ||
491 | const struct supply_info *info; | ||
492 | struct tps6524x *hw; | ||
493 | int ret; | ||
494 | |||
495 | hw = rdev_get_drvdata(rdev); | ||
496 | info = &supply_info[rdev_get_id(rdev)]; | ||
497 | |||
498 | if (info->flags & FIXED_VOLTAGE) | ||
499 | return info->fixed_voltage; | ||
500 | |||
501 | ret = read_field(hw, &info->voltage); | ||
502 | if (ret < 0) | ||
503 | return ret; | ||
504 | if (WARN_ON(ret >= info->n_voltages)) | ||
505 | return -EIO; | ||
506 | |||
507 | return info->voltages[ret]; | ||
508 | } | ||
509 | |||
510 | static int set_current_limit(struct regulator_dev *rdev, int min_uA, | ||
511 | int max_uA) | ||
512 | { | ||
513 | const struct supply_info *info; | ||
514 | struct tps6524x *hw; | ||
515 | int i; | ||
516 | |||
517 | hw = rdev_get_drvdata(rdev); | ||
518 | info = &supply_info[rdev_get_id(rdev)]; | ||
519 | |||
520 | if (info->flags & FIXED_ILIMSEL) | ||
521 | return -EINVAL; | ||
522 | |||
523 | for (i = 0; i < info->n_ilimsels; i++) | ||
524 | if (min_uA <= info->ilimsels[i] && | ||
525 | max_uA >= info->ilimsels[i]) | ||
526 | break; | ||
527 | |||
528 | if (i >= info->n_ilimsels) | ||
529 | return -EINVAL; | ||
530 | |||
531 | return write_field(hw, &info->ilimsel, i); | ||
532 | } | ||
533 | |||
534 | static int get_current_limit(struct regulator_dev *rdev) | ||
535 | { | ||
536 | const struct supply_info *info; | ||
537 | struct tps6524x *hw; | ||
538 | int ret; | ||
539 | |||
540 | hw = rdev_get_drvdata(rdev); | ||
541 | info = &supply_info[rdev_get_id(rdev)]; | ||
542 | |||
543 | if (info->flags & FIXED_ILIMSEL) | ||
544 | return info->fixed_ilimsel; | ||
545 | |||
546 | ret = read_field(hw, &info->ilimsel); | ||
547 | if (ret < 0) | ||
548 | return ret; | ||
549 | if (WARN_ON(ret >= info->n_ilimsels)) | ||
550 | return -EIO; | ||
551 | |||
552 | return info->ilimsels[ret]; | ||
553 | } | ||
554 | |||
555 | static int enable_supply(struct regulator_dev *rdev) | ||
556 | { | ||
557 | const struct supply_info *info; | ||
558 | struct tps6524x *hw; | ||
559 | |||
560 | hw = rdev_get_drvdata(rdev); | ||
561 | info = &supply_info[rdev_get_id(rdev)]; | ||
562 | |||
563 | return write_field(hw, &info->enable, 1); | ||
564 | } | ||
565 | |||
566 | static int disable_supply(struct regulator_dev *rdev) | ||
567 | { | ||
568 | const struct supply_info *info; | ||
569 | struct tps6524x *hw; | ||
570 | |||
571 | hw = rdev_get_drvdata(rdev); | ||
572 | info = &supply_info[rdev_get_id(rdev)]; | ||
573 | |||
574 | return write_field(hw, &info->enable, 0); | ||
575 | } | ||
576 | |||
577 | static int is_supply_enabled(struct regulator_dev *rdev) | ||
578 | { | ||
579 | const struct supply_info *info; | ||
580 | struct tps6524x *hw; | ||
581 | |||
582 | hw = rdev_get_drvdata(rdev); | ||
583 | info = &supply_info[rdev_get_id(rdev)]; | ||
584 | |||
585 | return read_field(hw, &info->enable); | ||
586 | } | ||
587 | |||
588 | static struct regulator_ops regulator_ops = { | ||
589 | .is_enabled = is_supply_enabled, | ||
590 | .enable = enable_supply, | ||
591 | .disable = disable_supply, | ||
592 | .get_voltage = get_voltage, | ||
593 | .set_voltage = set_voltage, | ||
594 | .list_voltage = list_voltage, | ||
595 | .set_current_limit = set_current_limit, | ||
596 | .get_current_limit = get_current_limit, | ||
597 | }; | ||
598 | |||
599 | static int __devexit pmic_remove(struct spi_device *spi) | ||
600 | { | ||
601 | struct tps6524x *hw = spi_get_drvdata(spi); | ||
602 | int i; | ||
603 | |||
604 | if (!hw) | ||
605 | return 0; | ||
606 | for (i = 0; i < N_REGULATORS; i++) { | ||
607 | if (hw->rdev[i]) | ||
608 | regulator_unregister(hw->rdev[i]); | ||
609 | hw->rdev[i] = NULL; | ||
610 | } | ||
611 | spi_set_drvdata(spi, NULL); | ||
612 | kfree(hw); | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static int __devinit pmic_probe(struct spi_device *spi) | ||
617 | { | ||
618 | struct tps6524x *hw; | ||
619 | struct device *dev = &spi->dev; | ||
620 | const struct supply_info *info = supply_info; | ||
621 | struct regulator_init_data *init_data; | ||
622 | int ret = 0, i; | ||
623 | |||
624 | init_data = dev->platform_data; | ||
625 | if (!init_data) { | ||
626 | dev_err(dev, "could not find regulator platform data\n"); | ||
627 | return -EINVAL; | ||
628 | } | ||
629 | |||
630 | hw = kzalloc(sizeof(struct tps6524x), GFP_KERNEL); | ||
631 | if (!hw) { | ||
632 | dev_err(dev, "cannot allocate regulator private data\n"); | ||
633 | return -ENOMEM; | ||
634 | } | ||
635 | spi_set_drvdata(spi, hw); | ||
636 | |||
637 | memset(hw, 0, sizeof(struct tps6524x)); | ||
638 | hw->dev = dev; | ||
639 | hw->spi = spi_dev_get(spi); | ||
640 | mutex_init(&hw->lock); | ||
641 | |||
642 | for (i = 0; i < N_REGULATORS; i++, info++, init_data++) { | ||
643 | hw->desc[i].name = info->name; | ||
644 | hw->desc[i].id = i; | ||
645 | hw->desc[i].n_voltages = info->n_voltages; | ||
646 | hw->desc[i].ops = ®ulator_ops; | ||
647 | hw->desc[i].type = REGULATOR_VOLTAGE; | ||
648 | hw->desc[i].owner = THIS_MODULE; | ||
649 | |||
650 | if (info->flags & FIXED_VOLTAGE) | ||
651 | hw->desc[i].n_voltages = 1; | ||
652 | |||
653 | hw->rdev[i] = regulator_register(&hw->desc[i], dev, | ||
654 | init_data, hw); | ||
655 | if (IS_ERR(hw->rdev[i])) { | ||
656 | ret = PTR_ERR(hw->rdev[i]); | ||
657 | hw->rdev[i] = NULL; | ||
658 | goto fail; | ||
659 | } | ||
660 | } | ||
661 | |||
662 | return 0; | ||
663 | |||
664 | fail: | ||
665 | pmic_remove(spi); | ||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | static struct spi_driver pmic_driver = { | ||
670 | .probe = pmic_probe, | ||
671 | .remove = __devexit_p(pmic_remove), | ||
672 | .driver = { | ||
673 | .name = "tps6524x", | ||
674 | .owner = THIS_MODULE, | ||
675 | }, | ||
676 | }; | ||
677 | |||
678 | static int __init pmic_driver_init(void) | ||
679 | { | ||
680 | return spi_register_driver(&pmic_driver); | ||
681 | } | ||
682 | module_init(pmic_driver_init); | ||
683 | |||
684 | static void __exit pmic_driver_exit(void) | ||
685 | { | ||
686 | spi_unregister_driver(&pmic_driver); | ||
687 | } | ||
688 | module_exit(pmic_driver_exit); | ||
689 | |||
690 | MODULE_DESCRIPTION("TPS6524X PMIC Driver"); | ||
691 | MODULE_AUTHOR("Cyril Chemparathy"); | ||
692 | MODULE_LICENSE("GPL"); | ||
693 | MODULE_ALIAS("spi:tps6524x"); | ||
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 6d20b0454a1d..bb04a75a4c98 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -85,7 +85,8 @@ static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, | |||
85 | 85 | ||
86 | static int __tps6586x_ldo_set_voltage(struct device *parent, | 86 | static int __tps6586x_ldo_set_voltage(struct device *parent, |
87 | struct tps6586x_regulator *ri, | 87 | struct tps6586x_regulator *ri, |
88 | int min_uV, int max_uV) | 88 | int min_uV, int max_uV, |
89 | unsigned *selector) | ||
89 | { | 90 | { |
90 | int val, uV; | 91 | int val, uV; |
91 | uint8_t mask; | 92 | uint8_t mask; |
@@ -100,6 +101,8 @@ static int __tps6586x_ldo_set_voltage(struct device *parent, | |||
100 | /* use the first in-range value */ | 101 | /* use the first in-range value */ |
101 | if (min_uV <= uV && uV <= max_uV) { | 102 | if (min_uV <= uV && uV <= max_uV) { |
102 | 103 | ||
104 | *selector = val; | ||
105 | |||
103 | val <<= ri->volt_shift; | 106 | val <<= ri->volt_shift; |
104 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; | 107 | mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; |
105 | 108 | ||
@@ -111,12 +114,13 @@ static int __tps6586x_ldo_set_voltage(struct device *parent, | |||
111 | } | 114 | } |
112 | 115 | ||
113 | static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, | 116 | static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, |
114 | int min_uV, int max_uV) | 117 | int min_uV, int max_uV, unsigned *selector) |
115 | { | 118 | { |
116 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | 119 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); |
117 | struct device *parent = to_tps6586x_dev(rdev); | 120 | struct device *parent = to_tps6586x_dev(rdev); |
118 | 121 | ||
119 | return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); | 122 | return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV, |
123 | selector); | ||
120 | } | 124 | } |
121 | 125 | ||
122 | static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) | 126 | static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) |
@@ -140,13 +144,14 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) | |||
140 | } | 144 | } |
141 | 145 | ||
142 | static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, | 146 | static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, |
143 | int min_uV, int max_uV) | 147 | int min_uV, int max_uV, unsigned *selector) |
144 | { | 148 | { |
145 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | 149 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); |
146 | struct device *parent = to_tps6586x_dev(rdev); | 150 | struct device *parent = to_tps6586x_dev(rdev); |
147 | int ret; | 151 | int ret; |
148 | 152 | ||
149 | ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); | 153 | ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV, |
154 | selector); | ||
150 | if (ret) | 155 | if (ret) |
151 | return ret; | 156 | return ret; |
152 | 157 | ||
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index a57262a4fa6c..bd332cf1cc3f 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
@@ -329,7 +329,8 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
329 | } | 329 | } |
330 | 330 | ||
331 | static int | 331 | static int |
332 | twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | 332 | twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, |
333 | unsigned *selector) | ||
333 | { | 334 | { |
334 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 335 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
335 | int vsel; | 336 | int vsel; |
@@ -345,9 +346,11 @@ twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
345 | /* REVISIT for VAUX2, first match may not be best/lowest */ | 346 | /* REVISIT for VAUX2, first match may not be best/lowest */ |
346 | 347 | ||
347 | /* use the first in-range value */ | 348 | /* use the first in-range value */ |
348 | if (min_uV <= uV && uV <= max_uV) | 349 | if (min_uV <= uV && uV <= max_uV) { |
350 | *selector = vsel; | ||
349 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, | 351 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, |
350 | VREG_VOLTAGE, vsel); | 352 | VREG_VOLTAGE, vsel); |
353 | } | ||
351 | } | 354 | } |
352 | 355 | ||
353 | return -EDOM; | 356 | return -EDOM; |
@@ -389,7 +392,8 @@ static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
389 | } | 392 | } |
390 | 393 | ||
391 | static int | 394 | static int |
392 | twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | 395 | twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, |
396 | unsigned *selector) | ||
393 | { | 397 | { |
394 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 398 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
395 | int vsel; | 399 | int vsel; |
@@ -402,6 +406,7 @@ twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) | |||
402 | * mV = 1000mv + 100mv * (vsel - 1) | 406 | * mV = 1000mv + 100mv * (vsel - 1) |
403 | */ | 407 | */ |
404 | vsel = (min_uV/1000 - 1000)/100 + 1; | 408 | vsel = (min_uV/1000 - 1000)/100 + 1; |
409 | *selector = vsel; | ||
405 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); | 410 | return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel); |
406 | 411 | ||
407 | } | 412 | } |
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index dbfaf5945e48..8b0d2c4bde91 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c | |||
@@ -302,7 +302,7 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state) | |||
302 | } | 302 | } |
303 | 303 | ||
304 | static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, | 304 | static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, |
305 | int min_uV, int max_uV) | 305 | int min_uV, int max_uV, unsigned *selector) |
306 | { | 306 | { |
307 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 307 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
308 | struct wm831x *wm831x = dcdc->wm831x; | 308 | struct wm831x *wm831x = dcdc->wm831x; |
@@ -314,6 +314,8 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, | |||
314 | if (vsel < 0) | 314 | if (vsel < 0) |
315 | return vsel; | 315 | return vsel; |
316 | 316 | ||
317 | *selector = vsel; | ||
318 | |||
317 | /* If this value is already set then do a GPIO update if we can */ | 319 | /* If this value is already set then do a GPIO update if we can */ |
318 | if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) | 320 | if (dcdc->dvs_gpio && dcdc->on_vsel == vsel) |
319 | return wm831x_buckv_set_dvs(rdev, 0); | 321 | return wm831x_buckv_set_dvs(rdev, 0); |
@@ -375,14 +377,14 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev, | |||
375 | return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel); | 377 | return wm831x_set_bits(wm831x, reg, WM831X_DC1_SLP_VSEL_MASK, vsel); |
376 | } | 378 | } |
377 | 379 | ||
378 | static int wm831x_buckv_get_voltage(struct regulator_dev *rdev) | 380 | static int wm831x_buckv_get_voltage_sel(struct regulator_dev *rdev) |
379 | { | 381 | { |
380 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 382 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
381 | 383 | ||
382 | if (dcdc->dvs_gpio && dcdc->dvs_gpio_state) | 384 | if (dcdc->dvs_gpio && dcdc->dvs_gpio_state) |
383 | return wm831x_buckv_list_voltage(rdev, dcdc->dvs_vsel); | 385 | return dcdc->dvs_vsel; |
384 | else | 386 | else |
385 | return wm831x_buckv_list_voltage(rdev, dcdc->on_vsel); | 387 | return dcdc->on_vsel; |
386 | } | 388 | } |
387 | 389 | ||
388 | /* Current limit options */ | 390 | /* Current limit options */ |
@@ -424,7 +426,7 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev) | |||
424 | 426 | ||
425 | static struct regulator_ops wm831x_buckv_ops = { | 427 | static struct regulator_ops wm831x_buckv_ops = { |
426 | .set_voltage = wm831x_buckv_set_voltage, | 428 | .set_voltage = wm831x_buckv_set_voltage, |
427 | .get_voltage = wm831x_buckv_get_voltage, | 429 | .get_voltage_sel = wm831x_buckv_get_voltage_sel, |
428 | .list_voltage = wm831x_buckv_list_voltage, | 430 | .list_voltage = wm831x_buckv_list_voltage, |
429 | .set_suspend_voltage = wm831x_buckv_set_suspend_voltage, | 431 | .set_suspend_voltage = wm831x_buckv_set_suspend_voltage, |
430 | .set_current_limit = wm831x_buckv_set_current_limit, | 432 | .set_current_limit = wm831x_buckv_set_current_limit, |
@@ -636,7 +638,7 @@ static int wm831x_buckp_list_voltage(struct regulator_dev *rdev, | |||
636 | } | 638 | } |
637 | 639 | ||
638 | static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, | 640 | static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, |
639 | int min_uV, int max_uV) | 641 | int min_uV, int max_uV, int *selector) |
640 | { | 642 | { |
641 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 643 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
642 | struct wm831x *wm831x = dcdc->wm831x; | 644 | struct wm831x *wm831x = dcdc->wm831x; |
@@ -650,16 +652,20 @@ static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg, | |||
650 | if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV) | 652 | if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV) |
651 | return -EINVAL; | 653 | return -EINVAL; |
652 | 654 | ||
655 | *selector = vsel; | ||
656 | |||
653 | return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel); | 657 | return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel); |
654 | } | 658 | } |
655 | 659 | ||
656 | static int wm831x_buckp_set_voltage(struct regulator_dev *rdev, | 660 | static int wm831x_buckp_set_voltage(struct regulator_dev *rdev, |
657 | int min_uV, int max_uV) | 661 | int min_uV, int max_uV, |
662 | unsigned *selector) | ||
658 | { | 663 | { |
659 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 664 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
660 | u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; | 665 | u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG; |
661 | 666 | ||
662 | return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV); | 667 | return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV, |
668 | selector); | ||
663 | } | 669 | } |
664 | 670 | ||
665 | static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, | 671 | static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, |
@@ -667,11 +673,12 @@ static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, | |||
667 | { | 673 | { |
668 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 674 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
669 | u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; | 675 | u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL; |
676 | unsigned selector; | ||
670 | 677 | ||
671 | return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV); | 678 | return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector); |
672 | } | 679 | } |
673 | 680 | ||
674 | static int wm831x_buckp_get_voltage(struct regulator_dev *rdev) | 681 | static int wm831x_buckp_get_voltage_sel(struct regulator_dev *rdev) |
675 | { | 682 | { |
676 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); | 683 | struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev); |
677 | struct wm831x *wm831x = dcdc->wm831x; | 684 | struct wm831x *wm831x = dcdc->wm831x; |
@@ -682,12 +689,12 @@ static int wm831x_buckp_get_voltage(struct regulator_dev *rdev) | |||
682 | if (val < 0) | 689 | if (val < 0) |
683 | return val; | 690 | return val; |
684 | 691 | ||
685 | return wm831x_buckp_list_voltage(rdev, val & WM831X_DC3_ON_VSEL_MASK); | 692 | return val & WM831X_DC3_ON_VSEL_MASK; |
686 | } | 693 | } |
687 | 694 | ||
688 | static struct regulator_ops wm831x_buckp_ops = { | 695 | static struct regulator_ops wm831x_buckp_ops = { |
689 | .set_voltage = wm831x_buckp_set_voltage, | 696 | .set_voltage = wm831x_buckp_set_voltage, |
690 | .get_voltage = wm831x_buckp_get_voltage, | 697 | .get_voltage_sel = wm831x_buckp_get_voltage_sel, |
691 | .list_voltage = wm831x_buckp_list_voltage, | 698 | .list_voltage = wm831x_buckp_list_voltage, |
692 | .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, | 699 | .set_suspend_voltage = wm831x_buckp_set_suspend_voltage, |
693 | 700 | ||
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 9edf8f692341..c94fc5b7cd5b 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
@@ -113,7 +113,8 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev, | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, | 115 | static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, |
116 | int min_uV, int max_uV) | 116 | int min_uV, int max_uV, |
117 | unsigned *selector) | ||
117 | { | 118 | { |
118 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 119 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
119 | struct wm831x *wm831x = ldo->wm831x; | 120 | struct wm831x *wm831x = ldo->wm831x; |
@@ -133,16 +134,20 @@ static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg, | |||
133 | if (ret < min_uV || ret > max_uV) | 134 | if (ret < min_uV || ret > max_uV) |
134 | return -EINVAL; | 135 | return -EINVAL; |
135 | 136 | ||
137 | *selector = vsel; | ||
138 | |||
136 | return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel); | 139 | return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel); |
137 | } | 140 | } |
138 | 141 | ||
139 | static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev, | 142 | static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev, |
140 | int min_uV, int max_uV) | 143 | int min_uV, int max_uV, |
144 | unsigned *selector) | ||
141 | { | 145 | { |
142 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 146 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
143 | int reg = ldo->base + WM831X_LDO_ON_CONTROL; | 147 | int reg = ldo->base + WM831X_LDO_ON_CONTROL; |
144 | 148 | ||
145 | return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV); | 149 | return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV, |
150 | selector); | ||
146 | } | 151 | } |
147 | 152 | ||
148 | static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, | 153 | static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, |
@@ -150,11 +155,12 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, | |||
150 | { | 155 | { |
151 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 156 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
152 | int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; | 157 | int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; |
158 | unsigned int selector; | ||
153 | 159 | ||
154 | return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV); | 160 | return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); |
155 | } | 161 | } |
156 | 162 | ||
157 | static int wm831x_gp_ldo_get_voltage(struct regulator_dev *rdev) | 163 | static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev) |
158 | { | 164 | { |
159 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 165 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
160 | struct wm831x *wm831x = ldo->wm831x; | 166 | struct wm831x *wm831x = ldo->wm831x; |
@@ -167,7 +173,7 @@ static int wm831x_gp_ldo_get_voltage(struct regulator_dev *rdev) | |||
167 | 173 | ||
168 | ret &= WM831X_LDO1_ON_VSEL_MASK; | 174 | ret &= WM831X_LDO1_ON_VSEL_MASK; |
169 | 175 | ||
170 | return wm831x_gp_ldo_list_voltage(rdev, ret); | 176 | return ret; |
171 | } | 177 | } |
172 | 178 | ||
173 | static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev) | 179 | static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev) |
@@ -287,7 +293,7 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev, | |||
287 | 293 | ||
288 | static struct regulator_ops wm831x_gp_ldo_ops = { | 294 | static struct regulator_ops wm831x_gp_ldo_ops = { |
289 | .list_voltage = wm831x_gp_ldo_list_voltage, | 295 | .list_voltage = wm831x_gp_ldo_list_voltage, |
290 | .get_voltage = wm831x_gp_ldo_get_voltage, | 296 | .get_voltage_sel = wm831x_gp_ldo_get_voltage_sel, |
291 | .set_voltage = wm831x_gp_ldo_set_voltage, | 297 | .set_voltage = wm831x_gp_ldo_set_voltage, |
292 | .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, | 298 | .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, |
293 | .get_mode = wm831x_gp_ldo_get_mode, | 299 | .get_mode = wm831x_gp_ldo_get_mode, |
@@ -413,7 +419,8 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev, | |||
413 | } | 419 | } |
414 | 420 | ||
415 | static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg, | 421 | static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg, |
416 | int min_uV, int max_uV) | 422 | int min_uV, int max_uV, |
423 | unsigned *selector) | ||
417 | { | 424 | { |
418 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 425 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
419 | struct wm831x *wm831x = ldo->wm831x; | 426 | struct wm831x *wm831x = ldo->wm831x; |
@@ -433,16 +440,19 @@ static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg, | |||
433 | if (ret < min_uV || ret > max_uV) | 440 | if (ret < min_uV || ret > max_uV) |
434 | return -EINVAL; | 441 | return -EINVAL; |
435 | 442 | ||
443 | *selector = vsel; | ||
444 | |||
436 | return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel); | 445 | return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel); |
437 | } | 446 | } |
438 | 447 | ||
439 | static int wm831x_aldo_set_voltage(struct regulator_dev *rdev, | 448 | static int wm831x_aldo_set_voltage(struct regulator_dev *rdev, |
440 | int min_uV, int max_uV) | 449 | int min_uV, int max_uV, unsigned *selector) |
441 | { | 450 | { |
442 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 451 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
443 | int reg = ldo->base + WM831X_LDO_ON_CONTROL; | 452 | int reg = ldo->base + WM831X_LDO_ON_CONTROL; |
444 | 453 | ||
445 | return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV); | 454 | return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV, |
455 | selector); | ||
446 | } | 456 | } |
447 | 457 | ||
448 | static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, | 458 | static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, |
@@ -450,11 +460,12 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, | |||
450 | { | 460 | { |
451 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 461 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
452 | int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; | 462 | int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; |
463 | unsigned int selector; | ||
453 | 464 | ||
454 | return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV); | 465 | return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector); |
455 | } | 466 | } |
456 | 467 | ||
457 | static int wm831x_aldo_get_voltage(struct regulator_dev *rdev) | 468 | static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev) |
458 | { | 469 | { |
459 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 470 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
460 | struct wm831x *wm831x = ldo->wm831x; | 471 | struct wm831x *wm831x = ldo->wm831x; |
@@ -467,7 +478,7 @@ static int wm831x_aldo_get_voltage(struct regulator_dev *rdev) | |||
467 | 478 | ||
468 | ret &= WM831X_LDO7_ON_VSEL_MASK; | 479 | ret &= WM831X_LDO7_ON_VSEL_MASK; |
469 | 480 | ||
470 | return wm831x_aldo_list_voltage(rdev, ret); | 481 | return ret; |
471 | } | 482 | } |
472 | 483 | ||
473 | static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) | 484 | static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev) |
@@ -548,7 +559,7 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) | |||
548 | 559 | ||
549 | static struct regulator_ops wm831x_aldo_ops = { | 560 | static struct regulator_ops wm831x_aldo_ops = { |
550 | .list_voltage = wm831x_aldo_list_voltage, | 561 | .list_voltage = wm831x_aldo_list_voltage, |
551 | .get_voltage = wm831x_aldo_get_voltage, | 562 | .get_voltage_sel = wm831x_aldo_get_voltage_sel, |
552 | .set_voltage = wm831x_aldo_set_voltage, | 563 | .set_voltage = wm831x_aldo_set_voltage, |
553 | .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, | 564 | .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, |
554 | .get_mode = wm831x_aldo_get_mode, | 565 | .get_mode = wm831x_aldo_get_mode, |
@@ -666,7 +677,8 @@ static int wm831x_alive_ldo_list_voltage(struct regulator_dev *rdev, | |||
666 | 677 | ||
667 | static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, | 678 | static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, |
668 | int reg, | 679 | int reg, |
669 | int min_uV, int max_uV) | 680 | int min_uV, int max_uV, |
681 | unsigned *selector) | ||
670 | { | 682 | { |
671 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 683 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
672 | struct wm831x *wm831x = ldo->wm831x; | 684 | struct wm831x *wm831x = ldo->wm831x; |
@@ -680,16 +692,20 @@ static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev, | |||
680 | if (ret < min_uV || ret > max_uV) | 692 | if (ret < min_uV || ret > max_uV) |
681 | return -EINVAL; | 693 | return -EINVAL; |
682 | 694 | ||
695 | *selector = vsel; | ||
696 | |||
683 | return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel); | 697 | return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel); |
684 | } | 698 | } |
685 | 699 | ||
686 | static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev, | 700 | static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev, |
687 | int min_uV, int max_uV) | 701 | int min_uV, int max_uV, |
702 | unsigned *selector) | ||
688 | { | 703 | { |
689 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 704 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
690 | int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; | 705 | int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL; |
691 | 706 | ||
692 | return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV); | 707 | return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV, |
708 | selector); | ||
693 | } | 709 | } |
694 | 710 | ||
695 | static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, | 711 | static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, |
@@ -697,11 +713,12 @@ static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev, | |||
697 | { | 713 | { |
698 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 714 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
699 | int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL; | 715 | int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL; |
716 | unsigned selector; | ||
700 | 717 | ||
701 | return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV); | 718 | return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector); |
702 | } | 719 | } |
703 | 720 | ||
704 | static int wm831x_alive_ldo_get_voltage(struct regulator_dev *rdev) | 721 | static int wm831x_alive_ldo_get_voltage_sel(struct regulator_dev *rdev) |
705 | { | 722 | { |
706 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); | 723 | struct wm831x_ldo *ldo = rdev_get_drvdata(rdev); |
707 | struct wm831x *wm831x = ldo->wm831x; | 724 | struct wm831x *wm831x = ldo->wm831x; |
@@ -714,7 +731,7 @@ static int wm831x_alive_ldo_get_voltage(struct regulator_dev *rdev) | |||
714 | 731 | ||
715 | ret &= WM831X_LDO11_ON_VSEL_MASK; | 732 | ret &= WM831X_LDO11_ON_VSEL_MASK; |
716 | 733 | ||
717 | return wm831x_alive_ldo_list_voltage(rdev, ret); | 734 | return ret; |
718 | } | 735 | } |
719 | 736 | ||
720 | static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) | 737 | static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) |
@@ -736,7 +753,7 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev) | |||
736 | 753 | ||
737 | static struct regulator_ops wm831x_alive_ldo_ops = { | 754 | static struct regulator_ops wm831x_alive_ldo_ops = { |
738 | .list_voltage = wm831x_alive_ldo_list_voltage, | 755 | .list_voltage = wm831x_alive_ldo_list_voltage, |
739 | .get_voltage = wm831x_alive_ldo_get_voltage, | 756 | .get_voltage_sel = wm831x_alive_ldo_get_voltage_sel, |
740 | .set_voltage = wm831x_alive_ldo_set_voltage, | 757 | .set_voltage = wm831x_alive_ldo_set_voltage, |
741 | .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, | 758 | .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage, |
742 | .get_status = wm831x_alive_ldo_get_status, | 759 | .get_status = wm831x_alive_ldo_get_status, |
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index fe4b8a8a9dfd..1bcb22c44095 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c | |||
@@ -360,7 +360,7 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode, | |||
360 | EXPORT_SYMBOL_GPL(wm8350_isink_set_flash); | 360 | EXPORT_SYMBOL_GPL(wm8350_isink_set_flash); |
361 | 361 | ||
362 | static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, | 362 | static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, |
363 | int max_uV) | 363 | int max_uV, unsigned *selector) |
364 | { | 364 | { |
365 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); | 365 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); |
366 | int volt_reg, dcdc = rdev_get_id(rdev), mV, | 366 | int volt_reg, dcdc = rdev_get_id(rdev), mV, |
@@ -397,17 +397,18 @@ static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, | |||
397 | return -EINVAL; | 397 | return -EINVAL; |
398 | } | 398 | } |
399 | 399 | ||
400 | *selector = mV; | ||
401 | |||
400 | /* all DCDCs have same mV bits */ | 402 | /* all DCDCs have same mV bits */ |
401 | val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; | 403 | val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK; |
402 | wm8350_reg_write(wm8350, volt_reg, val | mV); | 404 | wm8350_reg_write(wm8350, volt_reg, val | mV); |
403 | return 0; | 405 | return 0; |
404 | } | 406 | } |
405 | 407 | ||
406 | static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev) | 408 | static int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev) |
407 | { | 409 | { |
408 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); | 410 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); |
409 | int volt_reg, dcdc = rdev_get_id(rdev); | 411 | int volt_reg, dcdc = rdev_get_id(rdev); |
410 | u16 val; | ||
411 | 412 | ||
412 | switch (dcdc) { | 413 | switch (dcdc) { |
413 | case WM8350_DCDC_1: | 414 | case WM8350_DCDC_1: |
@@ -429,8 +430,7 @@ static int wm8350_dcdc_get_voltage(struct regulator_dev *rdev) | |||
429 | } | 430 | } |
430 | 431 | ||
431 | /* all DCDCs have same mV bits */ | 432 | /* all DCDCs have same mV bits */ |
432 | val = wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK; | 433 | return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK; |
433 | return wm8350_dcdc_val_to_mvolts(val) * 1000; | ||
434 | } | 434 | } |
435 | 435 | ||
436 | static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev, | 436 | static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev, |
@@ -754,7 +754,7 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev) | |||
754 | } | 754 | } |
755 | 755 | ||
756 | static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, | 756 | static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, |
757 | int max_uV) | 757 | int max_uV, unsigned *selector) |
758 | { | 758 | { |
759 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); | 759 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); |
760 | int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000, | 760 | int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000, |
@@ -797,17 +797,18 @@ static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV, | |||
797 | return -EINVAL; | 797 | return -EINVAL; |
798 | } | 798 | } |
799 | 799 | ||
800 | *selector = mV; | ||
801 | |||
800 | /* all LDOs have same mV bits */ | 802 | /* all LDOs have same mV bits */ |
801 | val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; | 803 | val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK; |
802 | wm8350_reg_write(wm8350, volt_reg, val | mV); | 804 | wm8350_reg_write(wm8350, volt_reg, val | mV); |
803 | return 0; | 805 | return 0; |
804 | } | 806 | } |
805 | 807 | ||
806 | static int wm8350_ldo_get_voltage(struct regulator_dev *rdev) | 808 | static int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev) |
807 | { | 809 | { |
808 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); | 810 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); |
809 | int volt_reg, ldo = rdev_get_id(rdev); | 811 | int volt_reg, ldo = rdev_get_id(rdev); |
810 | u16 val; | ||
811 | 812 | ||
812 | switch (ldo) { | 813 | switch (ldo) { |
813 | case WM8350_LDO_1: | 814 | case WM8350_LDO_1: |
@@ -827,8 +828,7 @@ static int wm8350_ldo_get_voltage(struct regulator_dev *rdev) | |||
827 | } | 828 | } |
828 | 829 | ||
829 | /* all LDOs have same mV bits */ | 830 | /* all LDOs have same mV bits */ |
830 | val = wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK; | 831 | return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK; |
831 | return wm8350_ldo_val_to_mvolts(val) * 1000; | ||
832 | } | 832 | } |
833 | 833 | ||
834 | static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, | 834 | static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, |
@@ -1225,7 +1225,7 @@ static int wm8350_ldo_is_enabled(struct regulator_dev *rdev) | |||
1225 | 1225 | ||
1226 | static struct regulator_ops wm8350_dcdc_ops = { | 1226 | static struct regulator_ops wm8350_dcdc_ops = { |
1227 | .set_voltage = wm8350_dcdc_set_voltage, | 1227 | .set_voltage = wm8350_dcdc_set_voltage, |
1228 | .get_voltage = wm8350_dcdc_get_voltage, | 1228 | .get_voltage_sel = wm8350_dcdc_get_voltage_sel, |
1229 | .list_voltage = wm8350_dcdc_list_voltage, | 1229 | .list_voltage = wm8350_dcdc_list_voltage, |
1230 | .enable = wm8350_dcdc_enable, | 1230 | .enable = wm8350_dcdc_enable, |
1231 | .disable = wm8350_dcdc_disable, | 1231 | .disable = wm8350_dcdc_disable, |
@@ -1249,7 +1249,7 @@ static struct regulator_ops wm8350_dcdc2_5_ops = { | |||
1249 | 1249 | ||
1250 | static struct regulator_ops wm8350_ldo_ops = { | 1250 | static struct regulator_ops wm8350_ldo_ops = { |
1251 | .set_voltage = wm8350_ldo_set_voltage, | 1251 | .set_voltage = wm8350_ldo_set_voltage, |
1252 | .get_voltage = wm8350_ldo_get_voltage, | 1252 | .get_voltage_sel = wm8350_ldo_get_voltage_sel, |
1253 | .list_voltage = wm8350_ldo_list_voltage, | 1253 | .list_voltage = wm8350_ldo_list_voltage, |
1254 | .enable = wm8350_ldo_enable, | 1254 | .enable = wm8350_ldo_enable, |
1255 | .disable = wm8350_ldo_disable, | 1255 | .disable = wm8350_ldo_disable, |
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 924c7eb29ee9..b42d01cef35a 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c | |||
@@ -67,7 +67,7 @@ static int wm8400_ldo_get_voltage(struct regulator_dev *dev) | |||
67 | } | 67 | } |
68 | 68 | ||
69 | static int wm8400_ldo_set_voltage(struct regulator_dev *dev, | 69 | static int wm8400_ldo_set_voltage(struct regulator_dev *dev, |
70 | int min_uV, int max_uV) | 70 | int min_uV, int max_uV, unsigned *selector) |
71 | { | 71 | { |
72 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); | 72 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); |
73 | u16 val; | 73 | u16 val; |
@@ -93,6 +93,8 @@ static int wm8400_ldo_set_voltage(struct regulator_dev *dev, | |||
93 | val += 0xf; | 93 | val += 0xf; |
94 | } | 94 | } |
95 | 95 | ||
96 | *selector = val; | ||
97 | |||
96 | return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), | 98 | return wm8400_set_bits(wm8400, WM8400_LDO1_CONTROL + rdev_get_id(dev), |
97 | WM8400_LDO1_VSEL_MASK, val); | 99 | WM8400_LDO1_VSEL_MASK, val); |
98 | } | 100 | } |
@@ -156,7 +158,7 @@ static int wm8400_dcdc_get_voltage(struct regulator_dev *dev) | |||
156 | } | 158 | } |
157 | 159 | ||
158 | static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, | 160 | static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, |
159 | int min_uV, int max_uV) | 161 | int min_uV, int max_uV, unsigned *selector) |
160 | { | 162 | { |
161 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); | 163 | struct wm8400 *wm8400 = rdev_get_drvdata(dev); |
162 | u16 val; | 164 | u16 val; |
@@ -171,6 +173,8 @@ static int wm8400_dcdc_set_voltage(struct regulator_dev *dev, | |||
171 | return -EINVAL; | 173 | return -EINVAL; |
172 | BUG_ON(850000 + (25000 * val) < min_uV); | 174 | BUG_ON(850000 + (25000 * val) < min_uV); |
173 | 175 | ||
176 | *selector = val; | ||
177 | |||
174 | return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, | 178 | return wm8400_set_bits(wm8400, WM8400_DCDC1_CONTROL_1 + offset, |
175 | WM8400_DC1_VSEL_MASK, val); | 179 | WM8400_DC1_VSEL_MASK, val); |
176 | } | 180 | } |
diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 03713bc66e4a..35b2958d5106 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c | |||
@@ -86,7 +86,7 @@ static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev, | |||
86 | return (selector * 100000) + 2400000; | 86 | return (selector * 100000) + 2400000; |
87 | } | 87 | } |
88 | 88 | ||
89 | static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev) | 89 | static int wm8994_ldo1_get_voltage_sel(struct regulator_dev *rdev) |
90 | { | 90 | { |
91 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); | 91 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); |
92 | int val; | 92 | int val; |
@@ -95,13 +95,11 @@ static int wm8994_ldo1_get_voltage(struct regulator_dev *rdev) | |||
95 | if (val < 0) | 95 | if (val < 0) |
96 | return val; | 96 | return val; |
97 | 97 | ||
98 | val = (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT; | 98 | return (val & WM8994_LDO1_VSEL_MASK) >> WM8994_LDO1_VSEL_SHIFT; |
99 | |||
100 | return wm8994_ldo1_list_voltage(rdev, val); | ||
101 | } | 99 | } |
102 | 100 | ||
103 | static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev, | 101 | static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev, |
104 | int min_uV, int max_uV) | 102 | int min_uV, int max_uV, unsigned *s) |
105 | { | 103 | { |
106 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); | 104 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); |
107 | int selector, v; | 105 | int selector, v; |
@@ -111,6 +109,7 @@ static int wm8994_ldo1_set_voltage(struct regulator_dev *rdev, | |||
111 | if (v < 0 || v > max_uV) | 109 | if (v < 0 || v > max_uV) |
112 | return -EINVAL; | 110 | return -EINVAL; |
113 | 111 | ||
112 | *s = selector; | ||
114 | selector <<= WM8994_LDO1_VSEL_SHIFT; | 113 | selector <<= WM8994_LDO1_VSEL_SHIFT; |
115 | 114 | ||
116 | return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1, | 115 | return wm8994_set_bits(ldo->wm8994, WM8994_LDO_1, |
@@ -124,20 +123,29 @@ static struct regulator_ops wm8994_ldo1_ops = { | |||
124 | .enable_time = wm8994_ldo_enable_time, | 123 | .enable_time = wm8994_ldo_enable_time, |
125 | 124 | ||
126 | .list_voltage = wm8994_ldo1_list_voltage, | 125 | .list_voltage = wm8994_ldo1_list_voltage, |
127 | .get_voltage = wm8994_ldo1_get_voltage, | 126 | .get_voltage_sel = wm8994_ldo1_get_voltage_sel, |
128 | .set_voltage = wm8994_ldo1_set_voltage, | 127 | .set_voltage = wm8994_ldo1_set_voltage, |
129 | }; | 128 | }; |
130 | 129 | ||
131 | static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev, | 130 | static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev, |
132 | unsigned int selector) | 131 | unsigned int selector) |
133 | { | 132 | { |
133 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); | ||
134 | |||
134 | if (selector > WM8994_LDO2_MAX_SELECTOR) | 135 | if (selector > WM8994_LDO2_MAX_SELECTOR) |
135 | return -EINVAL; | 136 | return -EINVAL; |
136 | 137 | ||
137 | return (selector * 100000) + 900000; | 138 | switch (ldo->wm8994->type) { |
139 | case WM8994: | ||
140 | return (selector * 100000) + 900000; | ||
141 | case WM8958: | ||
142 | return (selector * 100000) + 1000000; | ||
143 | default: | ||
144 | return -EINVAL; | ||
145 | } | ||
138 | } | 146 | } |
139 | 147 | ||
140 | static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev) | 148 | static int wm8994_ldo2_get_voltage_sel(struct regulator_dev *rdev) |
141 | { | 149 | { |
142 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); | 150 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); |
143 | int val; | 151 | int val; |
@@ -146,22 +154,31 @@ static int wm8994_ldo2_get_voltage(struct regulator_dev *rdev) | |||
146 | if (val < 0) | 154 | if (val < 0) |
147 | return val; | 155 | return val; |
148 | 156 | ||
149 | val = (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT; | 157 | return (val & WM8994_LDO2_VSEL_MASK) >> WM8994_LDO2_VSEL_SHIFT; |
150 | |||
151 | return wm8994_ldo2_list_voltage(rdev, val); | ||
152 | } | 158 | } |
153 | 159 | ||
154 | static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev, | 160 | static int wm8994_ldo2_set_voltage(struct regulator_dev *rdev, |
155 | int min_uV, int max_uV) | 161 | int min_uV, int max_uV, unsigned *s) |
156 | { | 162 | { |
157 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); | 163 | struct wm8994_ldo *ldo = rdev_get_drvdata(rdev); |
158 | int selector, v; | 164 | int selector, v; |
159 | 165 | ||
160 | selector = (min_uV - 900000) / 100000; | 166 | switch (ldo->wm8994->type) { |
167 | case WM8994: | ||
168 | selector = (min_uV - 900000) / 100000; | ||
169 | break; | ||
170 | case WM8958: | ||
171 | selector = (min_uV - 1000000) / 100000; | ||
172 | break; | ||
173 | default: | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
161 | v = wm8994_ldo2_list_voltage(rdev, selector); | 177 | v = wm8994_ldo2_list_voltage(rdev, selector); |
162 | if (v < 0 || v > max_uV) | 178 | if (v < 0 || v > max_uV) |
163 | return -EINVAL; | 179 | return -EINVAL; |
164 | 180 | ||
181 | *s = selector; | ||
165 | selector <<= WM8994_LDO2_VSEL_SHIFT; | 182 | selector <<= WM8994_LDO2_VSEL_SHIFT; |
166 | 183 | ||
167 | return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2, | 184 | return wm8994_set_bits(ldo->wm8994, WM8994_LDO_2, |
@@ -175,7 +192,7 @@ static struct regulator_ops wm8994_ldo2_ops = { | |||
175 | .enable_time = wm8994_ldo_enable_time, | 192 | .enable_time = wm8994_ldo_enable_time, |
176 | 193 | ||
177 | .list_voltage = wm8994_ldo2_list_voltage, | 194 | .list_voltage = wm8994_ldo2_list_voltage, |
178 | .get_voltage = wm8994_ldo2_get_voltage, | 195 | .get_voltage_sel = wm8994_ldo2_get_voltage_sel, |
179 | .set_voltage = wm8994_ldo2_set_voltage, | 196 | .set_voltage = wm8994_ldo2_set_voltage, |
180 | }; | 197 | }; |
181 | 198 | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 7e6ce626b7f1..c7ff8df347e7 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | #include <linux/log2.h> | 38 | #include <linux/log2.h> |
39 | #include <linux/pm.h> | ||
39 | 40 | ||
40 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 41 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
41 | #include <asm-generic/rtc.h> | 42 | #include <asm-generic/rtc.h> |
@@ -851,7 +852,7 @@ static void __exit cmos_do_remove(struct device *dev) | |||
851 | 852 | ||
852 | #ifdef CONFIG_PM | 853 | #ifdef CONFIG_PM |
853 | 854 | ||
854 | static int cmos_suspend(struct device *dev, pm_message_t mesg) | 855 | static int cmos_suspend(struct device *dev) |
855 | { | 856 | { |
856 | struct cmos_rtc *cmos = dev_get_drvdata(dev); | 857 | struct cmos_rtc *cmos = dev_get_drvdata(dev); |
857 | unsigned char tmp; | 858 | unsigned char tmp; |
@@ -899,7 +900,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg) | |||
899 | */ | 900 | */ |
900 | static inline int cmos_poweroff(struct device *dev) | 901 | static inline int cmos_poweroff(struct device *dev) |
901 | { | 902 | { |
902 | return cmos_suspend(dev, PMSG_HIBERNATE); | 903 | return cmos_suspend(dev); |
903 | } | 904 | } |
904 | 905 | ||
905 | static int cmos_resume(struct device *dev) | 906 | static int cmos_resume(struct device *dev) |
@@ -946,9 +947,9 @@ static int cmos_resume(struct device *dev) | |||
946 | return 0; | 947 | return 0; |
947 | } | 948 | } |
948 | 949 | ||
950 | static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume); | ||
951 | |||
949 | #else | 952 | #else |
950 | #define cmos_suspend NULL | ||
951 | #define cmos_resume NULL | ||
952 | 953 | ||
953 | static inline int cmos_poweroff(struct device *dev) | 954 | static inline int cmos_poweroff(struct device *dev) |
954 | { | 955 | { |
@@ -1078,7 +1079,7 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp) | |||
1078 | 1079 | ||
1079 | static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) | 1080 | static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg) |
1080 | { | 1081 | { |
1081 | return cmos_suspend(&pnp->dev, mesg); | 1082 | return cmos_suspend(&pnp->dev); |
1082 | } | 1083 | } |
1083 | 1084 | ||
1084 | static int cmos_pnp_resume(struct pnp_dev *pnp) | 1085 | static int cmos_pnp_resume(struct pnp_dev *pnp) |
@@ -1158,8 +1159,9 @@ static struct platform_driver cmos_platform_driver = { | |||
1158 | .shutdown = cmos_platform_shutdown, | 1159 | .shutdown = cmos_platform_shutdown, |
1159 | .driver = { | 1160 | .driver = { |
1160 | .name = (char *) driver_name, | 1161 | .name = (char *) driver_name, |
1161 | .suspend = cmos_suspend, | 1162 | #ifdef CONFIG_PM |
1162 | .resume = cmos_resume, | 1163 | .pm = &cmos_pm_ops, |
1164 | #endif | ||
1163 | } | 1165 | } |
1164 | }; | 1166 | }; |
1165 | 1167 | ||
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 657403ebd54a..0ec3f588a255 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c | |||
@@ -139,12 +139,13 @@ static int __devinit max6902_probe(struct spi_device *spi) | |||
139 | if (IS_ERR(rtc)) | 139 | if (IS_ERR(rtc)) |
140 | return PTR_ERR(rtc); | 140 | return PTR_ERR(rtc); |
141 | 141 | ||
142 | dev_set_drvdata(&spi->dev, rtc); | ||
142 | return 0; | 143 | return 0; |
143 | } | 144 | } |
144 | 145 | ||
145 | static int __devexit max6902_remove(struct spi_device *spi) | 146 | static int __devexit max6902_remove(struct spi_device *spi) |
146 | { | 147 | { |
147 | struct rtc_device *rtc = platform_get_drvdata(spi); | 148 | struct rtc_device *rtc = dev_get_drvdata(&spi->dev); |
148 | 149 | ||
149 | rtc_device_unregister(rtc); | 150 | rtc_device_unregister(rtc); |
150 | return 0; | 151 | return 0; |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 73377b0d65da..e72b523c79a5 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -429,13 +429,14 @@ fail1: | |||
429 | fail0: | 429 | fail0: |
430 | iounmap(rtc_base); | 430 | iounmap(rtc_base); |
431 | fail: | 431 | fail: |
432 | release_resource(mem); | 432 | release_mem_region(mem->start, resource_size(mem)); |
433 | return -EIO; | 433 | return -EIO; |
434 | } | 434 | } |
435 | 435 | ||
436 | static int __exit omap_rtc_remove(struct platform_device *pdev) | 436 | static int __exit omap_rtc_remove(struct platform_device *pdev) |
437 | { | 437 | { |
438 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 438 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
439 | struct resource *mem = dev_get_drvdata(&rtc->dev); | ||
439 | 440 | ||
440 | device_init_wakeup(&pdev->dev, 0); | 441 | device_init_wakeup(&pdev->dev, 0); |
441 | 442 | ||
@@ -447,8 +448,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
447 | if (omap_rtc_timer != omap_rtc_alarm) | 448 | if (omap_rtc_timer != omap_rtc_alarm) |
448 | free_irq(omap_rtc_alarm, rtc); | 449 | free_irq(omap_rtc_alarm, rtc); |
449 | 450 | ||
450 | release_resource(dev_get_drvdata(&rtc->dev)); | ||
451 | rtc_device_unregister(rtc); | 451 | rtc_device_unregister(rtc); |
452 | iounmap(rtc_base); | ||
453 | release_mem_region(mem->start, resource_size(mem)); | ||
452 | return 0; | 454 | return 0; |
453 | } | 455 | } |
454 | 456 | ||
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 09e7a053c844..30b2a820e670 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -841,7 +841,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) | |||
841 | } | 841 | } |
842 | 842 | ||
843 | /** | 843 | /** |
844 | * Emit buffer of a lan comand. | 844 | * Emit buffer of a lan command. |
845 | */ | 845 | */ |
846 | static void | 846 | static void |
847 | lcs_lancmd_timeout(unsigned long data) | 847 | lcs_lancmd_timeout(unsigned long data) |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 46342fee394d..303dde09d294 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
@@ -317,7 +317,7 @@ static void zfcp_act_eval_err(struct zfcp_adapter *adapter, u32 table) | |||
317 | 317 | ||
318 | /** | 318 | /** |
319 | * zfcp_cfdc_port_denied - Process "access denied" for port | 319 | * zfcp_cfdc_port_denied - Process "access denied" for port |
320 | * @port: The port where the acces has been denied | 320 | * @port: The port where the access has been denied |
321 | * @qual: The FSF status qualifier for the access denied FSF status | 321 | * @qual: The FSF status qualifier for the access denied FSF status |
322 | */ | 322 | */ |
323 | void zfcp_cfdc_port_denied(struct zfcp_port *port, | 323 | void zfcp_cfdc_port_denied(struct zfcp_port *port, |
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index dc5ac6e528c4..a391090a17c5 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c | |||
@@ -416,7 +416,7 @@ static u8 orc_load_firmware(struct orc_host * host) | |||
416 | /* Go back and check they match */ | 416 | /* Go back and check they match */ |
417 | 417 | ||
418 | outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL); /* Reset program count 0 */ | 418 | outb(PRGMRST | DOWNLOAD, host->base + ORC_RISCCTL); /* Reset program count 0 */ |
419 | bios_addr -= 0x1000; /* Reset the BIOS adddress */ | 419 | bios_addr -= 0x1000; /* Reset the BIOS address */ |
420 | for (i = 0, data32_ptr = (u8 *) & data32; /* Check the code */ | 420 | for (i = 0, data32_ptr = (u8 *) & data32; /* Check the code */ |
421 | i < 0x1000; /* Firmware code size = 4K */ | 421 | i < 0x1000; /* Firmware code size = 4K */ |
422 | i++, bios_addr++) { | 422 | i++, bios_addr++) { |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index afc9aeba5edb..060ac4bd5a14 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -91,7 +91,7 @@ void aac_fib_map_free(struct aac_dev *dev) | |||
91 | * aac_fib_setup - setup the fibs | 91 | * aac_fib_setup - setup the fibs |
92 | * @dev: Adapter to set up | 92 | * @dev: Adapter to set up |
93 | * | 93 | * |
94 | * Allocate the PCI space for the fibs, map it and then intialise the | 94 | * Allocate the PCI space for the fibs, map it and then initialise the |
95 | * fib area, the unmapped fib data and also the free list | 95 | * fib area, the unmapped fib data and also the free list |
96 | */ | 96 | */ |
97 | 97 | ||
diff --git a/drivers/scsi/aic7xxx_old/aic7xxx.seq b/drivers/scsi/aic7xxx_old/aic7xxx.seq index 5997e7c3a191..1565be9ebd49 100644 --- a/drivers/scsi/aic7xxx_old/aic7xxx.seq +++ b/drivers/scsi/aic7xxx_old/aic7xxx.seq | |||
@@ -1178,7 +1178,7 @@ notFound: | |||
1178 | /* | 1178 | /* |
1179 | * Retrieve an SCB by SCBID first searching the disconnected list falling | 1179 | * Retrieve an SCB by SCBID first searching the disconnected list falling |
1180 | * back to DMA'ing the SCB down from the host. This routine assumes that | 1180 | * back to DMA'ing the SCB down from the host. This routine assumes that |
1181 | * ARG_1 is the SCBID of interrest and that SINDEX is the position in the | 1181 | * ARG_1 is the SCBID of interest and that SINDEX is the position in the |
1182 | * disconnected list to start the search from. If SINDEX is SCB_LIST_NULL, | 1182 | * disconnected list to start the search from. If SINDEX is SCB_LIST_NULL, |
1183 | * we go directly to the host for the SCB. | 1183 | * we go directly to the host for the SCB. |
1184 | */ | 1184 | */ |
diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h index 28aaf349c111..40273a747d29 100644 --- a/drivers/scsi/aic94xx/aic94xx_reg_def.h +++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h | |||
@@ -1689,7 +1689,7 @@ | |||
1689 | #define PHY_START_CAL 0x01 | 1689 | #define PHY_START_CAL 0x01 |
1690 | 1690 | ||
1691 | /* | 1691 | /* |
1692 | * HST_PCIX2 Registers, Addresss Range: (0x00-0xFC) | 1692 | * HST_PCIX2 Registers, Address Range: (0x00-0xFC) |
1693 | */ | 1693 | */ |
1694 | #define PCIX_REG_BASE_ADR 0xB8040000 | 1694 | #define PCIX_REG_BASE_ADR 0xB8040000 |
1695 | 1695 | ||
@@ -1802,7 +1802,7 @@ | |||
1802 | #define PCIC_TP_CTRL 0xFC | 1802 | #define PCIC_TP_CTRL 0xFC |
1803 | 1803 | ||
1804 | /* | 1804 | /* |
1805 | * EXSI Registers, Addresss Range: (0x00-0xFC) | 1805 | * EXSI Registers, Address Range: (0x00-0xFC) |
1806 | */ | 1806 | */ |
1807 | #define EXSI_REG_BASE_ADR REG_BASE_ADDR_EXSI | 1807 | #define EXSI_REG_BASE_ADR REG_BASE_ADDR_EXSI |
1808 | 1808 | ||
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index c43698b1cb64..29593275201a 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c | |||
@@ -867,7 +867,7 @@ void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id, | |||
867 | * resources they have with this SCB, and then call this one at the | 867 | * resources they have with this SCB, and then call this one at the |
868 | * end of their timeout function. To do this, one should initialize | 868 | * end of their timeout function. To do this, one should initialize |
869 | * the ascb->timer.{function, data, expires} prior to calling the post | 869 | * the ascb->timer.{function, data, expires} prior to calling the post |
870 | * funcion. The timer is started by the post function. | 870 | * function. The timer is started by the post function. |
871 | */ | 871 | */ |
872 | void asd_ascb_timedout(unsigned long data) | 872 | void asd_ascb_timedout(unsigned long data) |
873 | { | 873 | { |
diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 74374618010c..390168f62a13 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c | |||
@@ -797,7 +797,7 @@ static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) | |||
797 | int j; | 797 | int j; |
798 | /* Start from Page 1 of Mode 0 and 1. */ | 798 | /* Start from Page 1 of Mode 0 and 1. */ |
799 | moffs = LSEQ_PAGE_SIZE + i*LSEQ_MODE_SCRATCH_SIZE; | 799 | moffs = LSEQ_PAGE_SIZE + i*LSEQ_MODE_SCRATCH_SIZE; |
800 | /* All the fields of page 1 can be intialized to 0. */ | 800 | /* All the fields of page 1 can be initialized to 0. */ |
801 | for (j = 0; j < LSEQ_PAGE_SIZE; j += 4) | 801 | for (j = 0; j < LSEQ_PAGE_SIZE; j += 4) |
802 | asd_write_reg_dword(asd_ha, LmSCRATCH(lseq)+moffs+j,0); | 802 | asd_write_reg_dword(asd_ha, LmSCRATCH(lseq)+moffs+j,0); |
803 | } | 803 | } |
@@ -938,7 +938,7 @@ static void asd_init_cseq_cio(struct asd_ha_struct *asd_ha) | |||
938 | asd_write_reg_dword(asd_ha, SCBPRO, 0); | 938 | asd_write_reg_dword(asd_ha, SCBPRO, 0); |
939 | asd_write_reg_dword(asd_ha, CSEQCON, 0); | 939 | asd_write_reg_dword(asd_ha, CSEQCON, 0); |
940 | 940 | ||
941 | /* Intialize CSEQ Mode 11 Interrupt Vectors. | 941 | /* Initialize CSEQ Mode 11 Interrupt Vectors. |
942 | * The addresses are 16 bit wide and in dword units. | 942 | * The addresses are 16 bit wide and in dword units. |
943 | * The values of their macros are in byte units. | 943 | * The values of their macros are in byte units. |
944 | * Thus we have to divide by 4. */ | 944 | * Thus we have to divide by 4. */ |
@@ -961,7 +961,7 @@ static void asd_init_cseq_cio(struct asd_ha_struct *asd_ha) | |||
961 | asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); | 961 | asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); |
962 | 962 | ||
963 | for (i = 0; i < 8; i++) { | 963 | for (i = 0; i < 8; i++) { |
964 | /* Intialize Mode n Link m Interrupt Enable. */ | 964 | /* Initialize Mode n Link m Interrupt Enable. */ |
965 | asd_write_reg_dword(asd_ha, CMnINTEN(i), EN_CMnRSPMBXF); | 965 | asd_write_reg_dword(asd_ha, CMnINTEN(i), EN_CMnRSPMBXF); |
966 | /* Initialize Mode n Request Mailbox. */ | 966 | /* Initialize Mode n Request Mailbox. */ |
967 | asd_write_reg_dword(asd_ha, CMnREQMBX(i), 0); | 967 | asd_write_reg_dword(asd_ha, CMnREQMBX(i), 0); |
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 9c410b21db6d..c0353cdca929 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c | |||
@@ -1838,7 +1838,7 @@ bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | |||
1838 | 1838 | ||
1839 | case BFA_IOIM_SM_ABORT: | 1839 | case BFA_IOIM_SM_ABORT: |
1840 | /* | 1840 | /* |
1841 | * IO is alraedy being cleaned up implicitly | 1841 | * IO is already being cleaned up implicitly |
1842 | */ | 1842 | */ |
1843 | ioim->io_cbfn = __bfa_cb_ioim_abort; | 1843 | ioim->io_cbfn = __bfa_cb_ioim_abort; |
1844 | break; | 1844 | break; |
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 4e2eb92ba028..43fa986bb586 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c | |||
@@ -5646,7 +5646,7 @@ bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) | |||
5646 | switch (status) { | 5646 | switch (status) { |
5647 | case BFA_STATUS_OK: | 5647 | case BFA_STATUS_OK: |
5648 | /* | 5648 | /* |
5649 | * Initialiaze the V-Port fields | 5649 | * Initialize the V-Port fields |
5650 | */ | 5650 | */ |
5651 | __vport_fcid(vport) = vport->lps->lp_pid; | 5651 | __vport_fcid(vport) = vport->lps->lp_pid; |
5652 | vport->vport_stats.fdisc_accepts++; | 5652 | vport->vport_stats.fdisc_accepts++; |
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 8f1b5c8bf903..b0f8523e665f 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c | |||
@@ -3796,7 +3796,7 @@ static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, | |||
3796 | * adapter_add_device - Adds the device instance to the adaptor instance. | 3796 | * adapter_add_device - Adds the device instance to the adaptor instance. |
3797 | * | 3797 | * |
3798 | * @acb: The adapter device to be updated | 3798 | * @acb: The adapter device to be updated |
3799 | * @dcb: A newly created and intialised device instance to add. | 3799 | * @dcb: A newly created and initialised device instance to add. |
3800 | **/ | 3800 | **/ |
3801 | static void adapter_add_device(struct AdapterCtlBlk *acb, | 3801 | static void adapter_add_device(struct AdapterCtlBlk *acb, |
3802 | struct DeviceCtlBlk *dcb) | 3802 | struct DeviceCtlBlk *dcb) |
@@ -4498,7 +4498,7 @@ static void __devinit adapter_init_chip(struct AdapterCtlBlk *acb) | |||
4498 | * init_adapter - Grab the resource for the card, setup the adapter | 4498 | * init_adapter - Grab the resource for the card, setup the adapter |
4499 | * information, set the card into a known state, create the various | 4499 | * information, set the card into a known state, create the various |
4500 | * tables etc etc. This basically gets all adapter information all up | 4500 | * tables etc etc. This basically gets all adapter information all up |
4501 | * to date, intialised and gets the chip in sync with it. | 4501 | * to date, initialised and gets the chip in sync with it. |
4502 | * | 4502 | * |
4503 | * @host: This hosts adapter structure | 4503 | * @host: This hosts adapter structure |
4504 | * @io_port: The base I/O port | 4504 | * @io_port: The base I/O port |
@@ -4789,7 +4789,7 @@ static void banner_display(void) | |||
4789 | * that it finds in the system. The pci_dev strcuture indicates which | 4789 | * that it finds in the system. The pci_dev strcuture indicates which |
4790 | * instance we are being called from. | 4790 | * instance we are being called from. |
4791 | * | 4791 | * |
4792 | * @dev: The PCI device to intialize. | 4792 | * @dev: The PCI device to initialize. |
4793 | * @id: Looks like a pointer to the entry in our pci device table | 4793 | * @id: Looks like a pointer to the entry in our pci device table |
4794 | * that was actually matched by the PCI subsystem. | 4794 | * that was actually matched by the PCI subsystem. |
4795 | * | 4795 | * |
@@ -4860,7 +4860,7 @@ fail: | |||
4860 | * dc395x_remove_one - Called to remove a single instance of the | 4860 | * dc395x_remove_one - Called to remove a single instance of the |
4861 | * adapter. | 4861 | * adapter. |
4862 | * | 4862 | * |
4863 | * @dev: The PCI device to intialize. | 4863 | * @dev: The PCI device to initialize. |
4864 | **/ | 4864 | **/ |
4865 | static void __devexit dc395x_remove_one(struct pci_dev *dev) | 4865 | static void __devexit dc395x_remove_one(struct pci_dev *dev) |
4866 | { | 4866 | { |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index cdc06cda76e5..5962d1a5a674 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -1250,7 +1250,7 @@ static void fc_lun_reset_send(unsigned long data) | |||
1250 | /** | 1250 | /** |
1251 | * fc_lun_reset() - Send a LUN RESET command to a device | 1251 | * fc_lun_reset() - Send a LUN RESET command to a device |
1252 | * and wait for the reply | 1252 | * and wait for the reply |
1253 | * @lport: The local port to sent the comand on | 1253 | * @lport: The local port to sent the command on |
1254 | * @fsp: The FCP packet that identifies the LUN to be reset | 1254 | * @fsp: The FCP packet that identifies the LUN to be reset |
1255 | * @id: The SCSI command ID | 1255 | * @id: The SCSI command ID |
1256 | * @lun: The LUN ID to be reset | 1256 | * @lun: The LUN ID to be reset |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index c06491b5862f..3512abb8a587 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1335,7 +1335,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ | |||
1335 | } | 1335 | } |
1336 | 1336 | ||
1337 | /** | 1337 | /** |
1338 | * lpfc_param_init - Intializes a cfg attribute | 1338 | * lpfc_param_init - Initializes a cfg attribute |
1339 | * | 1339 | * |
1340 | * Description: | 1340 | * Description: |
1341 | * Macro that given an attr e.g. hba_queue_depth expands | 1341 | * Macro that given an attr e.g. hba_queue_depth expands |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f9f160ab2ee9..bb015960dbc9 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -2852,7 +2852,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) | |||
2852 | if (unlikely(!fcf_record)) { | 2852 | if (unlikely(!fcf_record)) { |
2853 | lpfc_printf_log(phba, KERN_ERR, | 2853 | lpfc_printf_log(phba, KERN_ERR, |
2854 | LOG_MBOX | LOG_SLI, | 2854 | LOG_MBOX | LOG_SLI, |
2855 | "2554 Could not allocate memmory for " | 2855 | "2554 Could not allocate memory for " |
2856 | "fcf record\n"); | 2856 | "fcf record\n"); |
2857 | rc = -ENODEV; | 2857 | rc = -ENODEV; |
2858 | goto out; | 2858 | goto out; |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 462242dcdd0a..6d0b36aa3389 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -8071,7 +8071,7 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) | |||
8071 | * the HBA. | 8071 | * the HBA. |
8072 | */ | 8072 | */ |
8073 | 8073 | ||
8074 | /* HBA interrupt will be diabled after this call */ | 8074 | /* HBA interrupt will be disabled after this call */ |
8075 | lpfc_sli_hba_down(phba); | 8075 | lpfc_sli_hba_down(phba); |
8076 | /* Stop kthread signal shall trigger work_done one more time */ | 8076 | /* Stop kthread signal shall trigger work_done one more time */ |
8077 | kthread_stop(phba->worker_thread); | 8077 | kthread_stop(phba->worker_thread); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 634b2fea9c4d..a359d2b873ce 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -10172,7 +10172,7 @@ lpfc_sli4_intr_handler(int irq, void *dev_id) | |||
10172 | * lpfc_sli4_queue_free - free a queue structure and associated memory | 10172 | * lpfc_sli4_queue_free - free a queue structure and associated memory |
10173 | * @queue: The queue structure to free. | 10173 | * @queue: The queue structure to free. |
10174 | * | 10174 | * |
10175 | * This function frees a queue structure and the DMAable memeory used for | 10175 | * This function frees a queue structure and the DMAable memory used for |
10176 | * the host resident queue. This function must be called after destroying the | 10176 | * the host resident queue. This function must be called after destroying the |
10177 | * queue on the HBA. | 10177 | * queue on the HBA. |
10178 | **/ | 10178 | **/ |
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index f5644745e24e..853411911b2e 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h | |||
@@ -13,7 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * Comand coalescing - This feature allows the driver to be able to combine | 16 | * Command coalescing - This feature allows the driver to be able to combine |
17 | * two or more commands and issue as one command in order to boost I/O | 17 | * two or more commands and issue as one command in order to boost I/O |
18 | * performance. Useful if the nature of the I/O is sequential. It is not very | 18 | * performance. Useful if the nature of the I/O is sequential. It is not very |
19 | * useful for random natured I/Os. | 19 | * useful for random natured I/Os. |
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index a7008c0c24f9..25506c777381 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c | |||
@@ -224,7 +224,7 @@ mraid_mm_unlocked_ioctl(struct file *filep, unsigned int cmd, | |||
224 | { | 224 | { |
225 | int err; | 225 | int err; |
226 | 226 | ||
227 | /* inconsistant: mraid_mm_compat_ioctl doesn't take the BKL */ | 227 | /* inconsistent: mraid_mm_compat_ioctl doesn't take the BKL */ |
228 | mutex_lock(&mraid_mm_mutex); | 228 | mutex_lock(&mraid_mm_mutex); |
229 | err = mraid_mm_ioctl(filep, cmd, arg); | 229 | err = mraid_mm_ioctl(filep, cmd, arg); |
230 | mutex_unlock(&mraid_mm_mutex); | 230 | mutex_unlock(&mraid_mm_mutex); |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index f8c86b28f03f..b95285f3383f 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
@@ -603,7 +603,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) | |||
603 | #endif | 603 | #endif |
604 | 604 | ||
605 | intx: | 605 | intx: |
606 | /* intialize the INT-X interrupt */ | 606 | /* initialize the INT-X interrupt */ |
607 | rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, | 607 | rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, |
608 | SHOST_TO_SAS_HA(pm8001_ha->shost)); | 608 | SHOST_TO_SAS_HA(pm8001_ha->shost)); |
609 | return rc; | 609 | return rc; |
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index d53e6503c6d5..a2ed201885ae 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c | |||
@@ -477,7 +477,7 @@ EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); | |||
477 | 477 | ||
478 | 478 | ||
479 | /** | 479 | /** |
480 | * scsi_netlink_init - Called by SCSI subsystem to intialize | 480 | * scsi_netlink_init - Called by SCSI subsystem to initialize |
481 | * the SCSI transport netlink interface | 481 | * the SCSI transport netlink interface |
482 | * | 482 | * |
483 | **/ | 483 | **/ |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 4c68d36f9ac2..490ce213204e 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -864,13 +864,15 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
864 | 864 | ||
865 | error = device_add(&sdev->sdev_gendev); | 865 | error = device_add(&sdev->sdev_gendev); |
866 | if (error) { | 866 | if (error) { |
867 | printk(KERN_INFO "error 1\n"); | 867 | sdev_printk(KERN_INFO, sdev, |
868 | "failed to add device: %d\n", error); | ||
868 | return error; | 869 | return error; |
869 | } | 870 | } |
870 | device_enable_async_suspend(&sdev->sdev_dev); | 871 | device_enable_async_suspend(&sdev->sdev_dev); |
871 | error = device_add(&sdev->sdev_dev); | 872 | error = device_add(&sdev->sdev_dev); |
872 | if (error) { | 873 | if (error) { |
873 | printk(KERN_INFO "error 2\n"); | 874 | sdev_printk(KERN_INFO, sdev, |
875 | "failed to add class device: %d\n", error); | ||
874 | device_del(&sdev->sdev_gendev); | 876 | device_del(&sdev->sdev_gendev); |
875 | return error; | 877 | return error; |
876 | } | 878 | } |
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 6b97ded9d45d..b4543f575f46 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c | |||
@@ -1866,7 +1866,7 @@ static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev) | |||
1866 | * | 1866 | * |
1867 | * This routine is similar to sym_set_workarounds(), except | 1867 | * This routine is similar to sym_set_workarounds(), except |
1868 | * that, at this point, we already know that the device was | 1868 | * that, at this point, we already know that the device was |
1869 | * successfully intialized at least once before, and so most | 1869 | * successfully initialized at least once before, and so most |
1870 | * of the steps taken there are un-needed here. | 1870 | * of the steps taken there are un-needed here. |
1871 | */ | 1871 | */ |
1872 | static void sym2_reset_workarounds(struct pci_dev *pdev) | 1872 | static void sym2_reset_workarounds(struct pci_dev *pdev) |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index c291b3add1d2..92c91c83edde 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) | 4 | * SuperH on-chip serial module support. (SCI with no FIFO / with FIFO) |
5 | * | 5 | * |
6 | * Copyright (C) 2002 - 2008 Paul Mundt | 6 | * Copyright (C) 2002 - 2011 Paul Mundt |
7 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). | 7 | * Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007). |
8 | * | 8 | * |
9 | * based off of the old drivers/char/sh-sci.c by: | 9 | * based off of the old drivers/char/sh-sci.c by: |
@@ -81,14 +81,22 @@ struct sci_port { | |||
81 | struct timer_list break_timer; | 81 | struct timer_list break_timer; |
82 | int break_flag; | 82 | int break_flag; |
83 | 83 | ||
84 | /* SCSCR initialization */ | ||
85 | unsigned int scscr; | ||
86 | |||
87 | /* SCBRR calculation algo */ | ||
88 | unsigned int scbrr_algo_id; | ||
89 | |||
84 | /* Interface clock */ | 90 | /* Interface clock */ |
85 | struct clk *iclk; | 91 | struct clk *iclk; |
86 | /* Function clock */ | 92 | /* Function clock */ |
87 | struct clk *fclk; | 93 | struct clk *fclk; |
88 | 94 | ||
89 | struct list_head node; | 95 | struct list_head node; |
96 | |||
90 | struct dma_chan *chan_tx; | 97 | struct dma_chan *chan_tx; |
91 | struct dma_chan *chan_rx; | 98 | struct dma_chan *chan_rx; |
99 | |||
92 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 100 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
93 | struct device *dma_dev; | 101 | struct device *dma_dev; |
94 | unsigned int slave_tx; | 102 | unsigned int slave_tx; |
@@ -415,9 +423,9 @@ static void sci_transmit_chars(struct uart_port *port) | |||
415 | if (!(status & SCxSR_TDxE(port))) { | 423 | if (!(status & SCxSR_TDxE(port))) { |
416 | ctrl = sci_in(port, SCSCR); | 424 | ctrl = sci_in(port, SCSCR); |
417 | if (uart_circ_empty(xmit)) | 425 | if (uart_circ_empty(xmit)) |
418 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 426 | ctrl &= ~SCSCR_TIE; |
419 | else | 427 | else |
420 | ctrl |= SCI_CTRL_FLAGS_TIE; | 428 | ctrl |= SCSCR_TIE; |
421 | sci_out(port, SCSCR, ctrl); | 429 | sci_out(port, SCSCR, ctrl); |
422 | return; | 430 | return; |
423 | } | 431 | } |
@@ -459,7 +467,7 @@ static void sci_transmit_chars(struct uart_port *port) | |||
459 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); | 467 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); |
460 | } | 468 | } |
461 | 469 | ||
462 | ctrl |= SCI_CTRL_FLAGS_TIE; | 470 | ctrl |= SCSCR_TIE; |
463 | sci_out(port, SCSCR, ctrl); | 471 | sci_out(port, SCSCR, ctrl); |
464 | } | 472 | } |
465 | } | 473 | } |
@@ -708,7 +716,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
708 | disable_irq_nosync(irq); | 716 | disable_irq_nosync(irq); |
709 | scr |= 0x4000; | 717 | scr |= 0x4000; |
710 | } else { | 718 | } else { |
711 | scr &= ~SCI_CTRL_FLAGS_RIE; | 719 | scr &= ~SCSCR_RIE; |
712 | } | 720 | } |
713 | sci_out(port, SCSCR, scr); | 721 | sci_out(port, SCSCR, scr); |
714 | /* Clear current interrupt */ | 722 | /* Clear current interrupt */ |
@@ -777,6 +785,18 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) | |||
777 | return IRQ_HANDLED; | 785 | return IRQ_HANDLED; |
778 | } | 786 | } |
779 | 787 | ||
788 | static inline unsigned long port_rx_irq_mask(struct uart_port *port) | ||
789 | { | ||
790 | /* | ||
791 | * Not all ports (such as SCIFA) will support REIE. Rather than | ||
792 | * special-casing the port type, we check the port initialization | ||
793 | * IRQ enable mask to see whether the IRQ is desired at all. If | ||
794 | * it's unset, it's logically inferred that there's no point in | ||
795 | * testing for it. | ||
796 | */ | ||
797 | return SCSCR_RIE | (to_sci_port(port)->scscr & SCSCR_REIE); | ||
798 | } | ||
799 | |||
780 | static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | 800 | static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) |
781 | { | 801 | { |
782 | unsigned short ssr_status, scr_status, err_enabled; | 802 | unsigned short ssr_status, scr_status, err_enabled; |
@@ -786,22 +806,25 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
786 | 806 | ||
787 | ssr_status = sci_in(port, SCxSR); | 807 | ssr_status = sci_in(port, SCxSR); |
788 | scr_status = sci_in(port, SCSCR); | 808 | scr_status = sci_in(port, SCSCR); |
789 | err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE); | 809 | err_enabled = scr_status & port_rx_irq_mask(port); |
790 | 810 | ||
791 | /* Tx Interrupt */ | 811 | /* Tx Interrupt */ |
792 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE) && | 812 | if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCSCR_TIE) && |
793 | !s->chan_tx) | 813 | !s->chan_tx) |
794 | ret = sci_tx_interrupt(irq, ptr); | 814 | ret = sci_tx_interrupt(irq, ptr); |
815 | |||
795 | /* | 816 | /* |
796 | * Rx Interrupt: if we're using DMA, the DMA controller clears RDF / | 817 | * Rx Interrupt: if we're using DMA, the DMA controller clears RDF / |
797 | * DR flags | 818 | * DR flags |
798 | */ | 819 | */ |
799 | if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) && | 820 | if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) && |
800 | (scr_status & SCI_CTRL_FLAGS_RIE)) | 821 | (scr_status & SCSCR_RIE)) |
801 | ret = sci_rx_interrupt(irq, ptr); | 822 | ret = sci_rx_interrupt(irq, ptr); |
823 | |||
802 | /* Error Interrupt */ | 824 | /* Error Interrupt */ |
803 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) | 825 | if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled) |
804 | ret = sci_er_interrupt(irq, ptr); | 826 | ret = sci_er_interrupt(irq, ptr); |
827 | |||
805 | /* Break Interrupt */ | 828 | /* Break Interrupt */ |
806 | if ((ssr_status & SCxSR_BRK(port)) && err_enabled) | 829 | if ((ssr_status & SCxSR_BRK(port)) && err_enabled) |
807 | ret = sci_br_interrupt(irq, ptr); | 830 | ret = sci_br_interrupt(irq, ptr); |
@@ -951,7 +974,7 @@ static void sci_dma_tx_complete(void *arg) | |||
951 | schedule_work(&s->work_tx); | 974 | schedule_work(&s->work_tx); |
952 | } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 975 | } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
953 | u16 ctrl = sci_in(port, SCSCR); | 976 | u16 ctrl = sci_in(port, SCSCR); |
954 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | 977 | sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); |
955 | } | 978 | } |
956 | 979 | ||
957 | spin_unlock_irqrestore(&port->lock, flags); | 980 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -1214,14 +1237,16 @@ static void sci_start_tx(struct uart_port *port) | |||
1214 | if (new != scr) | 1237 | if (new != scr) |
1215 | sci_out(port, SCSCR, new); | 1238 | sci_out(port, SCSCR, new); |
1216 | } | 1239 | } |
1240 | |||
1217 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && | 1241 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && |
1218 | s->cookie_tx < 0) | 1242 | s->cookie_tx < 0) |
1219 | schedule_work(&s->work_tx); | 1243 | schedule_work(&s->work_tx); |
1220 | #endif | 1244 | #endif |
1245 | |||
1221 | if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { | 1246 | if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1222 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1247 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1223 | ctrl = sci_in(port, SCSCR); | 1248 | ctrl = sci_in(port, SCSCR); |
1224 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); | 1249 | sci_out(port, SCSCR, ctrl | SCSCR_TIE); |
1225 | } | 1250 | } |
1226 | } | 1251 | } |
1227 | 1252 | ||
@@ -1231,20 +1256,24 @@ static void sci_stop_tx(struct uart_port *port) | |||
1231 | 1256 | ||
1232 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1257 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1233 | ctrl = sci_in(port, SCSCR); | 1258 | ctrl = sci_in(port, SCSCR); |
1259 | |||
1234 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 1260 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1235 | ctrl &= ~0x8000; | 1261 | ctrl &= ~0x8000; |
1236 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1262 | |
1263 | ctrl &= ~SCSCR_TIE; | ||
1264 | |||
1237 | sci_out(port, SCSCR, ctrl); | 1265 | sci_out(port, SCSCR, ctrl); |
1238 | } | 1266 | } |
1239 | 1267 | ||
1240 | static void sci_start_rx(struct uart_port *port) | 1268 | static void sci_start_rx(struct uart_port *port) |
1241 | { | 1269 | { |
1242 | unsigned short ctrl = SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE; | 1270 | unsigned short ctrl; |
1271 | |||
1272 | ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port); | ||
1243 | 1273 | ||
1244 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | ||
1245 | ctrl |= sci_in(port, SCSCR); | ||
1246 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 1274 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1247 | ctrl &= ~0x4000; | 1275 | ctrl &= ~0x4000; |
1276 | |||
1248 | sci_out(port, SCSCR, ctrl); | 1277 | sci_out(port, SCSCR, ctrl); |
1249 | } | 1278 | } |
1250 | 1279 | ||
@@ -1252,11 +1281,13 @@ static void sci_stop_rx(struct uart_port *port) | |||
1252 | { | 1281 | { |
1253 | unsigned short ctrl; | 1282 | unsigned short ctrl; |
1254 | 1283 | ||
1255 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | ||
1256 | ctrl = sci_in(port, SCSCR); | 1284 | ctrl = sci_in(port, SCSCR); |
1285 | |||
1257 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) | 1286 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1258 | ctrl &= ~0x4000; | 1287 | ctrl &= ~0x4000; |
1259 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1288 | |
1289 | ctrl &= ~port_rx_irq_mask(port); | ||
1290 | |||
1260 | sci_out(port, SCSCR, ctrl); | 1291 | sci_out(port, SCSCR, ctrl); |
1261 | } | 1292 | } |
1262 | 1293 | ||
@@ -1296,7 +1327,7 @@ static void rx_timer_fn(unsigned long arg) | |||
1296 | scr &= ~0x4000; | 1327 | scr &= ~0x4000; |
1297 | enable_irq(s->irqs[1]); | 1328 | enable_irq(s->irqs[1]); |
1298 | } | 1329 | } |
1299 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); | 1330 | sci_out(port, SCSCR, scr | SCSCR_RIE); |
1300 | dev_dbg(port->dev, "DMA Rx timed out\n"); | 1331 | dev_dbg(port->dev, "DMA Rx timed out\n"); |
1301 | schedule_work(&s->work_rx); | 1332 | schedule_work(&s->work_rx); |
1302 | } | 1333 | } |
@@ -1442,12 +1473,31 @@ static void sci_shutdown(struct uart_port *port) | |||
1442 | s->disable(port); | 1473 | s->disable(port); |
1443 | } | 1474 | } |
1444 | 1475 | ||
1476 | static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, | ||
1477 | unsigned long freq) | ||
1478 | { | ||
1479 | switch (algo_id) { | ||
1480 | case SCBRR_ALGO_1: | ||
1481 | return ((freq + 16 * bps) / (16 * bps) - 1); | ||
1482 | case SCBRR_ALGO_2: | ||
1483 | return ((freq + 16 * bps) / (32 * bps) - 1); | ||
1484 | case SCBRR_ALGO_3: | ||
1485 | return (((freq * 2) + 16 * bps) / (16 * bps) - 1); | ||
1486 | case SCBRR_ALGO_4: | ||
1487 | return (((freq * 2) + 16 * bps) / (32 * bps) - 1); | ||
1488 | case SCBRR_ALGO_5: | ||
1489 | return (((freq * 1000 / 32) / bps) - 1); | ||
1490 | } | ||
1491 | |||
1492 | /* Warn, but use a safe default */ | ||
1493 | WARN_ON(1); | ||
1494 | return ((freq + 16 * bps) / (32 * bps) - 1); | ||
1495 | } | ||
1496 | |||
1445 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 1497 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
1446 | struct ktermios *old) | 1498 | struct ktermios *old) |
1447 | { | 1499 | { |
1448 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
1449 | struct sci_port *s = to_sci_port(port); | 1500 | struct sci_port *s = to_sci_port(port); |
1450 | #endif | ||
1451 | unsigned int status, baud, smr_val, max_baud; | 1501 | unsigned int status, baud, smr_val, max_baud; |
1452 | int t = -1; | 1502 | int t = -1; |
1453 | u16 scfcr = 0; | 1503 | u16 scfcr = 0; |
@@ -1464,7 +1514,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1464 | 1514 | ||
1465 | baud = uart_get_baud_rate(port, termios, old, 0, max_baud); | 1515 | baud = uart_get_baud_rate(port, termios, old, 0, max_baud); |
1466 | if (likely(baud && port->uartclk)) | 1516 | if (likely(baud && port->uartclk)) |
1467 | t = SCBRR_VALUE(baud, port->uartclk); | 1517 | t = sci_scbrr_calc(s->scbrr_algo_id, baud, port->uartclk); |
1468 | 1518 | ||
1469 | do { | 1519 | do { |
1470 | status = sci_in(port, SCxSR); | 1520 | status = sci_in(port, SCxSR); |
@@ -1490,7 +1540,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1490 | sci_out(port, SCSMR, smr_val); | 1540 | sci_out(port, SCSMR, smr_val); |
1491 | 1541 | ||
1492 | dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, | 1542 | dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, |
1493 | SCSCR_INIT(port)); | 1543 | s->scscr); |
1494 | 1544 | ||
1495 | if (t > 0) { | 1545 | if (t > 0) { |
1496 | if (t >= 256) { | 1546 | if (t >= 256) { |
@@ -1506,7 +1556,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1506 | sci_init_pins(port, termios->c_cflag); | 1556 | sci_init_pins(port, termios->c_cflag); |
1507 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); | 1557 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); |
1508 | 1558 | ||
1509 | sci_out(port, SCSCR, SCSCR_INIT(port)); | 1559 | sci_out(port, SCSCR, s->scscr); |
1510 | 1560 | ||
1511 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1561 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1512 | /* | 1562 | /* |
@@ -1679,9 +1729,11 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1679 | port->mapbase = p->mapbase; | 1729 | port->mapbase = p->mapbase; |
1680 | port->membase = p->membase; | 1730 | port->membase = p->membase; |
1681 | 1731 | ||
1682 | port->irq = p->irqs[SCIx_TXI_IRQ]; | 1732 | port->irq = p->irqs[SCIx_TXI_IRQ]; |
1683 | port->flags = p->flags; | 1733 | port->flags = p->flags; |
1684 | sci_port->type = port->type = p->type; | 1734 | sci_port->type = port->type = p->type; |
1735 | sci_port->scscr = p->scscr; | ||
1736 | sci_port->scbrr_algo_id = p->scbrr_algo_id; | ||
1685 | 1737 | ||
1686 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1738 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1687 | sci_port->dma_dev = p->dma_dev; | 1739 | sci_port->dma_dev = p->dma_dev; |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 4bc614e4221c..b223d6cbf33a 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -15,27 +15,17 @@ | |||
15 | defined(CONFIG_CPU_SUBTYPE_SH7709) | 15 | defined(CONFIG_CPU_SUBTYPE_SH7709) |
16 | # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ | 16 | # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ |
17 | # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ | 17 | # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ |
18 | # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ | ||
19 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) | 18 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) |
20 | # define SCIF0 0xA4400000 | 19 | # define SCIF0 0xA4400000 |
21 | # define SCIF2 0xA4410000 | 20 | # define SCIF2 0xA4410000 |
22 | # define SCSMR_Ir 0xA44A0000 | ||
23 | # define IRDA_SCIF SCIF0 | ||
24 | # define SCPCR 0xA4000116 | 21 | # define SCPCR 0xA4000116 |
25 | # define SCPDR 0xA4000136 | 22 | # define SCPDR 0xA4000136 |
26 | |||
27 | /* Set the clock source, | ||
28 | * SCIF2 (0xA4410000) -> External clock, SCK pin used as clock input | ||
29 | * SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output | ||
30 | */ | ||
31 | # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 | ||
32 | #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 23 | #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
33 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 24 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
34 | defined(CONFIG_ARCH_SH73A0) || \ | 25 | defined(CONFIG_ARCH_SH73A0) || \ |
35 | defined(CONFIG_ARCH_SH7367) || \ | 26 | defined(CONFIG_ARCH_SH7367) || \ |
36 | defined(CONFIG_ARCH_SH7377) || \ | 27 | defined(CONFIG_ARCH_SH7377) || \ |
37 | defined(CONFIG_ARCH_SH7372) | 28 | defined(CONFIG_ARCH_SH7372) |
38 | # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ | ||
39 | # define PORT_PTCR 0xA405011EUL | 29 | # define PORT_PTCR 0xA405011EUL |
40 | # define PORT_PVCR 0xA4050122UL | 30 | # define PORT_PVCR 0xA4050122UL |
41 | # define SCIF_ORER 0x0200 /* overrun error bit */ | 31 | # define SCIF_ORER 0x0200 /* overrun error bit */ |
@@ -43,7 +33,6 @@ | |||
43 | # define SCSPTR1 0xFFE0001C /* 8 bit SCIF */ | 33 | # define SCSPTR1 0xFFE0001C /* 8 bit SCIF */ |
44 | # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ | 34 | # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ |
45 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 35 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
46 | # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
47 | #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ | 36 | #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ |
48 | defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ | 37 | defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ |
49 | defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ | 38 | defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ |
@@ -53,39 +42,31 @@ | |||
53 | # define SCSPTR1 0xffe0001c /* 8 bit SCI */ | 42 | # define SCSPTR1 0xffe0001c /* 8 bit SCI */ |
54 | # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ | 43 | # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ |
55 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 44 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
56 | # define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \ | ||
57 | 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ | ||
58 | 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ ) | ||
59 | #elif defined(CONFIG_CPU_SUBTYPE_SH7760) | 45 | #elif defined(CONFIG_CPU_SUBTYPE_SH7760) |
60 | # define SCSPTR0 0xfe600024 /* 16 bit SCIF */ | 46 | # define SCSPTR0 0xfe600024 /* 16 bit SCIF */ |
61 | # define SCSPTR1 0xfe610024 /* 16 bit SCIF */ | 47 | # define SCSPTR1 0xfe610024 /* 16 bit SCIF */ |
62 | # define SCSPTR2 0xfe620024 /* 16 bit SCIF */ | 48 | # define SCSPTR2 0xfe620024 /* 16 bit SCIF */ |
63 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 49 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
64 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
65 | #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) | 50 | #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) |
66 | # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ | 51 | # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ |
67 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 52 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
68 | # define PACR 0xa4050100 | 53 | # define PACR 0xa4050100 |
69 | # define PBCR 0xa4050102 | 54 | # define PBCR 0xa4050102 |
70 | # define SCSCR_INIT(port) 0x3B | ||
71 | #elif defined(CONFIG_CPU_SUBTYPE_SH7343) | 55 | #elif defined(CONFIG_CPU_SUBTYPE_SH7343) |
72 | # define SCSPTR0 0xffe00010 /* 16 bit SCIF */ | 56 | # define SCSPTR0 0xffe00010 /* 16 bit SCIF */ |
73 | # define SCSPTR1 0xffe10010 /* 16 bit SCIF */ | 57 | # define SCSPTR1 0xffe10010 /* 16 bit SCIF */ |
74 | # define SCSPTR2 0xffe20010 /* 16 bit SCIF */ | 58 | # define SCSPTR2 0xffe20010 /* 16 bit SCIF */ |
75 | # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ | 59 | # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ |
76 | # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ | ||
77 | #elif defined(CONFIG_CPU_SUBTYPE_SH7722) | 60 | #elif defined(CONFIG_CPU_SUBTYPE_SH7722) |
78 | # define PADR 0xA4050120 | 61 | # define PADR 0xA4050120 |
79 | # define PSDR 0xA405013e | 62 | # define PSDR 0xA405013e |
80 | # define PWDR 0xA4050166 | 63 | # define PWDR 0xA4050166 |
81 | # define PSCR 0xA405011E | 64 | # define PSCR 0xA405011E |
82 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 65 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
83 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
84 | #elif defined(CONFIG_CPU_SUBTYPE_SH7366) | 66 | #elif defined(CONFIG_CPU_SUBTYPE_SH7366) |
85 | # define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ | 67 | # define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ |
86 | # define SCSPTR0 SCPDR0 | 68 | # define SCSPTR0 SCPDR0 |
87 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 69 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
88 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
89 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 70 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) |
90 | # define SCSPTR0 0xa4050160 | 71 | # define SCSPTR0 0xa4050160 |
91 | # define SCSPTR1 0xa405013e | 72 | # define SCSPTR1 0xa405013e |
@@ -94,62 +75,38 @@ | |||
94 | # define SCSPTR4 0xa4050128 | 75 | # define SCSPTR4 0xa4050128 |
95 | # define SCSPTR5 0xa4050128 | 76 | # define SCSPTR5 0xa4050128 |
96 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 77 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
97 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
98 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | 78 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) |
99 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 79 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
100 | # define SCSCR_INIT(port) ((port)->type == PORT_SCIFA ? \ | ||
101 | 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ | ||
102 | 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ ) | ||
103 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) | 80 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
104 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ | 81 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
105 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 82 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
106 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
107 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) | 83 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) |
108 | # define SCIF_BASE_ADDR 0x01030000 | ||
109 | # define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR | ||
110 | # define SCIF_PTR2_OFFS 0x0000020 | 84 | # define SCIF_PTR2_OFFS 0x0000020 |
111 | # define SCIF_LSR2_OFFS 0x0000024 | ||
112 | # define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ | 85 | # define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ |
113 | # define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */ | ||
114 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */ | ||
115 | #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) | 86 | #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) |
116 | # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ | ||
117 | # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) | 87 | # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) |
118 | #elif defined(CONFIG_H8S2678) | 88 | #elif defined(CONFIG_H8S2678) |
119 | # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ | ||
120 | # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) | 89 | # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) |
121 | #elif defined(CONFIG_CPU_SUBTYPE_SH7757) | 90 | #elif defined(CONFIG_CPU_SUBTYPE_SH7757) |
122 | # define SCSPTR0 0xfe4b0020 | 91 | # define SCSPTR0 0xfe4b0020 |
123 | # define SCSPTR1 0xfe4b0020 | 92 | # define SCSPTR1 0xfe4b0020 |
124 | # define SCSPTR2 0xfe4b0020 | 93 | # define SCSPTR2 0xfe4b0020 |
125 | # define SCIF_ORER 0x0001 | 94 | # define SCIF_ORER 0x0001 |
126 | # define SCSCR_INIT(port) 0x38 | ||
127 | # define SCIF_ONLY | 95 | # define SCIF_ONLY |
128 | #elif defined(CONFIG_CPU_SUBTYPE_SH7763) | 96 | #elif defined(CONFIG_CPU_SUBTYPE_SH7763) |
129 | # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ | 97 | # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ |
130 | # define SCSPTR1 0xffe08024 /* 16 bit SCIF */ | 98 | # define SCSPTR1 0xffe08024 /* 16 bit SCIF */ |
131 | # define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */ | 99 | # define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */ |
132 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 100 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
133 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
134 | #elif defined(CONFIG_CPU_SUBTYPE_SH7770) | 101 | #elif defined(CONFIG_CPU_SUBTYPE_SH7770) |
135 | # define SCSPTR0 0xff923020 /* 16 bit SCIF */ | 102 | # define SCSPTR0 0xff923020 /* 16 bit SCIF */ |
136 | # define SCSPTR1 0xff924020 /* 16 bit SCIF */ | 103 | # define SCSPTR1 0xff924020 /* 16 bit SCIF */ |
137 | # define SCSPTR2 0xff925020 /* 16 bit SCIF */ | 104 | # define SCSPTR2 0xff925020 /* 16 bit SCIF */ |
138 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 105 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
139 | # define SCSCR_INIT(port) 0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */ | ||
140 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) | 106 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) |
141 | # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ | 107 | # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ |
142 | # define SCSPTR1 0xffe10024 /* 16 bit SCIF */ | 108 | # define SCSPTR1 0xffe10024 /* 16 bit SCIF */ |
143 | # define SCIF_ORER 0x0001 /* Overrun error bit */ | 109 | # define SCIF_ORER 0x0001 /* Overrun error bit */ |
144 | |||
145 | #if defined(CONFIG_SH_SH2007) | ||
146 | /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */ | ||
147 | # define SCSCR_INIT(port) 0x38 | ||
148 | #else | ||
149 | /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */ | ||
150 | # define SCSCR_INIT(port) 0x3a | ||
151 | #endif | ||
152 | |||
153 | #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ | 110 | #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ |
154 | defined(CONFIG_CPU_SUBTYPE_SH7786) | 111 | defined(CONFIG_CPU_SUBTYPE_SH7786) |
155 | # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ | 112 | # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ |
@@ -159,7 +116,6 @@ | |||
159 | # define SCSPTR4 0xffee0024 /* 16 bit SCIF */ | 116 | # define SCSPTR4 0xffee0024 /* 16 bit SCIF */ |
160 | # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ | 117 | # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ |
161 | # define SCIF_ORER 0x0001 /* Overrun error bit */ | 118 | # define SCIF_ORER 0x0001 /* Overrun error bit */ |
162 | # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
163 | #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ | 119 | #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ |
164 | defined(CONFIG_CPU_SUBTYPE_SH7203) || \ | 120 | defined(CONFIG_CPU_SUBTYPE_SH7203) || \ |
165 | defined(CONFIG_CPU_SUBTYPE_SH7206) || \ | 121 | defined(CONFIG_CPU_SUBTYPE_SH7206) || \ |
@@ -174,52 +130,21 @@ | |||
174 | # define SCSPTR6 0xfffeB020 /* 16 bit SCIF */ | 130 | # define SCSPTR6 0xfffeB020 /* 16 bit SCIF */ |
175 | # define SCSPTR7 0xfffeB820 /* 16 bit SCIF */ | 131 | # define SCSPTR7 0xfffeB820 /* 16 bit SCIF */ |
176 | # endif | 132 | # endif |
177 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
178 | #elif defined(CONFIG_CPU_SUBTYPE_SH7619) | 133 | #elif defined(CONFIG_CPU_SUBTYPE_SH7619) |
179 | # define SCSPTR0 0xf8400020 /* 16 bit SCIF */ | 134 | # define SCSPTR0 0xf8400020 /* 16 bit SCIF */ |
180 | # define SCSPTR1 0xf8410020 /* 16 bit SCIF */ | 135 | # define SCSPTR1 0xf8410020 /* 16 bit SCIF */ |
181 | # define SCSPTR2 0xf8420020 /* 16 bit SCIF */ | 136 | # define SCSPTR2 0xf8420020 /* 16 bit SCIF */ |
182 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 137 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
183 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
184 | #elif defined(CONFIG_CPU_SUBTYPE_SHX3) | 138 | #elif defined(CONFIG_CPU_SUBTYPE_SHX3) |
185 | # define SCSPTR0 0xffc30020 /* 16 bit SCIF */ | 139 | # define SCSPTR0 0xffc30020 /* 16 bit SCIF */ |
186 | # define SCSPTR1 0xffc40020 /* 16 bit SCIF */ | 140 | # define SCSPTR1 0xffc40020 /* 16 bit SCIF */ |
187 | # define SCSPTR2 0xffc50020 /* 16 bit SCIF */ | 141 | # define SCSPTR2 0xffc50020 /* 16 bit SCIF */ |
188 | # define SCSPTR3 0xffc60020 /* 16 bit SCIF */ | 142 | # define SCSPTR3 0xffc60020 /* 16 bit SCIF */ |
189 | # define SCIF_ORER 0x0001 /* Overrun error bit */ | 143 | # define SCIF_ORER 0x0001 /* Overrun error bit */ |
190 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
191 | #else | 144 | #else |
192 | # error CPU subtype not defined | 145 | # error CPU subtype not defined |
193 | #endif | 146 | #endif |
194 | 147 | ||
195 | /* SCSCR */ | ||
196 | #define SCI_CTRL_FLAGS_TIE 0x80 /* all */ | ||
197 | #define SCI_CTRL_FLAGS_RIE 0x40 /* all */ | ||
198 | #define SCI_CTRL_FLAGS_TE 0x20 /* all */ | ||
199 | #define SCI_CTRL_FLAGS_RE 0x10 /* all */ | ||
200 | #if defined(CONFIG_CPU_SUBTYPE_SH7750) || \ | ||
201 | defined(CONFIG_CPU_SUBTYPE_SH7091) || \ | ||
202 | defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ | ||
203 | defined(CONFIG_CPU_SUBTYPE_SH7722) || \ | ||
204 | defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ | ||
205 | defined(CONFIG_CPU_SUBTYPE_SH7751) || \ | ||
206 | defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ | ||
207 | defined(CONFIG_CPU_SUBTYPE_SH7763) || \ | ||
208 | defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | ||
209 | defined(CONFIG_CPU_SUBTYPE_SH7785) || \ | ||
210 | defined(CONFIG_CPU_SUBTYPE_SH7786) || \ | ||
211 | defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
212 | #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ | ||
213 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
214 | #define SCI_CTRL_FLAGS_REIE ((port)->type == PORT_SCIFA ? 0 : 8) | ||
215 | #else | ||
216 | #define SCI_CTRL_FLAGS_REIE 0 | ||
217 | #endif | ||
218 | /* SCI_CTRL_FLAGS_MPIE 0x08 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ | ||
219 | /* SCI_CTRL_FLAGS_TEIE 0x04 * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ | ||
220 | /* SCI_CTRL_FLAGS_CKE1 0x02 * all */ | ||
221 | /* SCI_CTRL_FLAGS_CKE0 0x01 * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */ | ||
222 | |||
223 | /* SCxSR SCI */ | 148 | /* SCxSR SCI */ |
224 | #define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ | 149 | #define SCI_TDRE 0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
225 | #define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ | 150 | #define SCI_RDRF 0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ |
@@ -300,23 +225,11 @@ | |||
300 | /* SCFCR */ | 225 | /* SCFCR */ |
301 | #define SCFCR_RFRST 0x0002 | 226 | #define SCFCR_RFRST 0x0002 |
302 | #define SCFCR_TFRST 0x0004 | 227 | #define SCFCR_TFRST 0x0004 |
303 | #define SCFCR_TCRST 0x4000 | ||
304 | #define SCFCR_MCE 0x0008 | 228 | #define SCFCR_MCE 0x0008 |
305 | 229 | ||
306 | #define SCI_MAJOR 204 | 230 | #define SCI_MAJOR 204 |
307 | #define SCI_MINOR_START 8 | 231 | #define SCI_MINOR_START 8 |
308 | 232 | ||
309 | /* Generic serial flags */ | ||
310 | #define SCI_RX_THROTTLE 0x0000001 | ||
311 | |||
312 | #define SCI_MAGIC 0xbabeface | ||
313 | |||
314 | /* | ||
315 | * Events are used to schedule things to happen at timer-interrupt | ||
316 | * time, instead of at rs interrupt time. | ||
317 | */ | ||
318 | #define SCI_EVENT_WRITE_WAKEUP 0 | ||
319 | |||
320 | #define SCI_IN(size, offset) \ | 233 | #define SCI_IN(size, offset) \ |
321 | if ((size) == 8) { \ | 234 | if ((size) == 8) { \ |
322 | return ioread8(port->membase + (offset)); \ | 235 | return ioread8(port->membase + (offset)); \ |
@@ -445,8 +358,6 @@ | |||
445 | SCIF_FNS(SCSMR, 0x00, 16) | 358 | SCIF_FNS(SCSMR, 0x00, 16) |
446 | SCIF_FNS(SCBRR, 0x04, 8) | 359 | SCIF_FNS(SCBRR, 0x04, 8) |
447 | SCIF_FNS(SCSCR, 0x08, 16) | 360 | SCIF_FNS(SCSCR, 0x08, 16) |
448 | SCIF_FNS(SCTDSR, 0x0c, 8) | ||
449 | SCIF_FNS(SCFER, 0x10, 16) | ||
450 | SCIF_FNS(SCxSR, 0x14, 16) | 361 | SCIF_FNS(SCxSR, 0x14, 16) |
451 | SCIF_FNS(SCFCR, 0x18, 16) | 362 | SCIF_FNS(SCFCR, 0x18, 16) |
452 | SCIF_FNS(SCFDR, 0x1c, 16) | 363 | SCIF_FNS(SCFDR, 0x1c, 16) |
@@ -476,8 +387,6 @@ SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8) | |||
476 | SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16) | 387 | SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16) |
477 | SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8) | 388 | SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8) |
478 | SCIx_FNS(SCSPTR, 0, 0, 0, 0) | 389 | SCIx_FNS(SCSPTR, 0, 0, 0, 0) |
479 | SCIF_FNS(SCTDSR, 0x0c, 8) | ||
480 | SCIF_FNS(SCFER, 0x10, 16) | ||
481 | SCIF_FNS(SCFCR, 0x18, 16) | 390 | SCIF_FNS(SCFCR, 0x18, 16) |
482 | SCIF_FNS(SCFDR, 0x1c, 16) | 391 | SCIF_FNS(SCFDR, 0x1c, 16) |
483 | SCIF_FNS(SCLSR, 0x24, 16) | 392 | SCIF_FNS(SCLSR, 0x24, 16) |
@@ -503,7 +412,6 @@ SCIF_FNS(SCLSR, 0, 0, 0x28, 16) | |||
503 | #elif defined(CONFIG_CPU_SUBTYPE_SH7763) | 412 | #elif defined(CONFIG_CPU_SUBTYPE_SH7763) |
504 | SCIF_FNS(SCFDR, 0, 0, 0x1C, 16) | 413 | SCIF_FNS(SCFDR, 0, 0, 0x1C, 16) |
505 | SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16) | 414 | SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16) |
506 | SCIF_FNS(SCLSR2, 0, 0, 0x24, 16) | ||
507 | SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) | 415 | SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) |
508 | SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) | 416 | SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) |
509 | SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) | 417 | SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) |
@@ -597,64 +505,3 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
597 | return 1; | 505 | return 1; |
598 | } | 506 | } |
599 | #endif | 507 | #endif |
600 | |||
601 | /* | ||
602 | * Values for the BitRate Register (SCBRR) | ||
603 | * | ||
604 | * The values are actually divisors for a frequency which can | ||
605 | * be internal to the SH3 (14.7456MHz) or derived from an external | ||
606 | * clock source. This driver assumes the internal clock is used; | ||
607 | * to support using an external clock source, config options or | ||
608 | * possibly command-line options would need to be added. | ||
609 | * | ||
610 | * Also, to support speeds below 2400 (why?) the lower 2 bits of | ||
611 | * the SCSMR register would also need to be set to non-zero values. | ||
612 | * | ||
613 | * -- Greg Banks 27Feb2000 | ||
614 | * | ||
615 | * Answer: The SCBRR register is only eight bits, and the value in | ||
616 | * it gets larger with lower baud rates. At around 2400 (depending on | ||
617 | * the peripherial module clock) you run out of bits. However the | ||
618 | * lower two bits of SCSMR allow the module clock to be divided down, | ||
619 | * scaling the value which is needed in SCBRR. | ||
620 | * | ||
621 | * -- Stuart Menefy - 23 May 2000 | ||
622 | * | ||
623 | * I meant, why would anyone bother with bitrates below 2400. | ||
624 | * | ||
625 | * -- Greg Banks - 7Jul2000 | ||
626 | * | ||
627 | * You "speedist"! How will I use my 110bps ASR-33 teletype with paper | ||
628 | * tape reader as a console! | ||
629 | * | ||
630 | * -- Mitch Davis - 15 Jul 2000 | ||
631 | */ | ||
632 | |||
633 | #if (defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | ||
634 | defined(CONFIG_CPU_SUBTYPE_SH7785) || \ | ||
635 | defined(CONFIG_CPU_SUBTYPE_SH7786)) && \ | ||
636 | !defined(CONFIG_SH_SH2007) | ||
637 | #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) | ||
638 | #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ | ||
639 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | ||
640 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | ||
641 | defined(CONFIG_ARCH_SH73A0) || \ | ||
642 | defined(CONFIG_ARCH_SH7367) || \ | ||
643 | defined(CONFIG_ARCH_SH7377) || \ | ||
644 | defined(CONFIG_ARCH_SH7372) | ||
645 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) | ||
646 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | ||
647 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
648 | static inline int scbrr_calc(struct uart_port *port, int bps, int clk) | ||
649 | { | ||
650 | if (port->type == PORT_SCIF) | ||
651 | return (clk+16*bps)/(32*bps)-1; | ||
652 | else | ||
653 | return ((clk*2)+16*bps)/(16*bps)-1; | ||
654 | } | ||
655 | #define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk) | ||
656 | #elif defined(__H8300H__) || defined(__H8300S__) | ||
657 | #define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1) | ||
658 | #else /* Generic SH */ | ||
659 | #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) | ||
660 | #endif | ||
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index a067046c9da2..1a478bf88c9d 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
@@ -341,9 +341,9 @@ static void atmel_spi_next_message(struct spi_master *master) | |||
341 | /* | 341 | /* |
342 | * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma: | 342 | * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma: |
343 | * - The buffer is either valid for CPU access, else NULL | 343 | * - The buffer is either valid for CPU access, else NULL |
344 | * - If the buffer is valid, so is its DMA addresss | 344 | * - If the buffer is valid, so is its DMA address |
345 | * | 345 | * |
346 | * This driver manages the dma addresss unless message->is_dma_mapped. | 346 | * This driver manages the dma address unless message->is_dma_mapped. |
347 | */ | 347 | */ |
348 | static int | 348 | static int |
349 | atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) | 349 | atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) |
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 4e6245e67995..603428213d21 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | 39 | ||
40 | /* | 40 | /* |
41 | * This supports acccess to SPI devices using normal userspace I/O calls. | 41 | * This supports access to SPI devices using normal userspace I/O calls. |
42 | * Note that while traditional UNIX/POSIX I/O semantics are half duplex, | 42 | * Note that while traditional UNIX/POSIX I/O semantics are half duplex, |
43 | * and often mask message boundaries, full SPI support requires full duplex | 43 | * and often mask message boundaries, full SPI support requires full duplex |
44 | * transfers. There are several kinds of internal message boundaries to | 44 | * transfers. There are several kinds of internal message boundaries to |
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e2d586903432..5c8fcfc42c3e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -123,6 +123,8 @@ source "drivers/staging/sep/Kconfig" | |||
123 | 123 | ||
124 | source "drivers/staging/iio/Kconfig" | 124 | source "drivers/staging/iio/Kconfig" |
125 | 125 | ||
126 | source "drivers/staging/cs5535_gpio/Kconfig" | ||
127 | |||
126 | source "drivers/staging/zram/Kconfig" | 128 | source "drivers/staging/zram/Kconfig" |
127 | 129 | ||
128 | source "drivers/staging/wlags49_h2/Kconfig" | 130 | source "drivers/staging/wlags49_h2/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c7d222413c07..d53886317826 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_VME_BUS) += vme/ | |||
44 | obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ | 44 | obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ |
45 | obj-$(CONFIG_DX_SEP) += sep/ | 45 | obj-$(CONFIG_DX_SEP) += sep/ |
46 | obj-$(CONFIG_IIO) += iio/ | 46 | obj-$(CONFIG_IIO) += iio/ |
47 | obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio/ | ||
47 | obj-$(CONFIG_ZRAM) += zram/ | 48 | obj-$(CONFIG_ZRAM) += zram/ |
48 | obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ | 49 | obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ |
49 | obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ | 50 | obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ |
diff --git a/drivers/staging/cs5535_gpio/Kconfig b/drivers/staging/cs5535_gpio/Kconfig new file mode 100644 index 000000000000..a1b3a8d2b866 --- /dev/null +++ b/drivers/staging/cs5535_gpio/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | config CS5535_GPIO | ||
2 | tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)" | ||
3 | depends on X86_32 | ||
4 | help | ||
5 | Note: this driver is DEPRECATED. Please use the cs5535-gpio module | ||
6 | in the GPIO section instead (CONFIG_GPIO_CS5535). | ||
7 | |||
8 | Give userspace access to the GPIO pins on the AMD CS5535 and | ||
9 | CS5536 Geode companion devices. | ||
10 | |||
11 | If compiled as a module, it will be called cs5535_gpio. | ||
diff --git a/drivers/staging/cs5535_gpio/Makefile b/drivers/staging/cs5535_gpio/Makefile new file mode 100644 index 000000000000..d67c4b85f191 --- /dev/null +++ b/drivers/staging/cs5535_gpio/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_CS5535_GPIO) += cs5535_gpio.o | |||
diff --git a/drivers/staging/cs5535_gpio/TODO b/drivers/staging/cs5535_gpio/TODO new file mode 100644 index 000000000000..98d1cd1e2363 --- /dev/null +++ b/drivers/staging/cs5535_gpio/TODO | |||
@@ -0,0 +1,6 @@ | |||
1 | This is an obsolete driver for some the CS5535 and CS5536 southbridge GPIOs. | ||
2 | It has been replaced by a driver that makes use of the Linux GPIO subsystem. | ||
3 | Please switch to that driver, and let dilinger@queued.net know if there's | ||
4 | anything missing from the new driver. | ||
5 | |||
6 | This driver is scheduled for removal in 2.6.40. | ||
diff --git a/drivers/char/cs5535_gpio.c b/drivers/staging/cs5535_gpio/cs5535_gpio.c index 0cf1e5fad9ab..0cf1e5fad9ab 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/staging/cs5535_gpio/cs5535_gpio.c | |||
diff --git a/drivers/staging/msm/msm_fb_bl.c b/drivers/staging/msm/msm_fb_bl.c index 033fc9486e01..2a8077511fc0 100644 --- a/drivers/staging/msm/msm_fb_bl.c +++ b/drivers/staging/msm/msm_fb_bl.c | |||
@@ -42,7 +42,7 @@ static int msm_fb_bl_update_status(struct backlight_device *pbd) | |||
42 | return 0; | 42 | return 0; |
43 | } | 43 | } |
44 | 44 | ||
45 | static struct backlight_ops msm_fb_bl_ops = { | 45 | static const struct backlight_ops msm_fb_bl_ops = { |
46 | .get_brightness = msm_fb_bl_get_brightness, | 46 | .get_brightness = msm_fb_bl_get_brightness, |
47 | .update_status = msm_fb_bl_update_status, | 47 | .update_status = msm_fb_bl_update_status, |
48 | }; | 48 | }; |
diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO index ac2d3d023715..35f9cda7be11 100644 --- a/drivers/staging/olpc_dcon/TODO +++ b/drivers/staging/olpc_dcon/TODO | |||
@@ -1,6 +1,5 @@ | |||
1 | TODO: | 1 | TODO: |
2 | - checkpatch.pl cleanups | 2 | - checkpatch.pl cleanups |
3 | - port geode gpio calls to newer cs5535 API | ||
4 | - see if vx855 gpio API can be made similar enough to cs5535 so we can | 3 | - see if vx855 gpio API can be made similar enough to cs5535 so we can |
5 | share more code | 4 | share more code |
6 | - allow simultaneous XO-1 and XO-1.5 support | 5 | - allow simultaneous XO-1 and XO-1.5 support |
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 4ca45ec7fd84..9f26dc9408bb 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/reboot.h> | 29 | #include <linux/reboot.h> |
30 | #include <linux/gpio.h> | ||
31 | #include <asm/tsc.h> | 30 | #include <asm/tsc.h> |
32 | #include <asm/olpc.h> | 31 | #include <asm/olpc.h> |
33 | 32 | ||
@@ -49,7 +48,7 @@ struct dcon_platform_data { | |||
49 | int (*init)(void); | 48 | int (*init)(void); |
50 | void (*bus_stabilize_wiggle)(void); | 49 | void (*bus_stabilize_wiggle)(void); |
51 | void (*set_dconload)(int); | 50 | void (*set_dconload)(int); |
52 | int (*read_status)(void); | 51 | u8 (*read_status)(void); |
53 | }; | 52 | }; |
54 | 53 | ||
55 | static struct dcon_platform_data *pdata; | 54 | static struct dcon_platform_data *pdata; |
@@ -615,7 +614,7 @@ static struct device_attribute dcon_device_files[] = { | |||
615 | __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store), | 614 | __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store), |
616 | }; | 615 | }; |
617 | 616 | ||
618 | static struct backlight_ops dcon_bl_ops = { | 617 | static const struct backlight_ops dcon_bl_ops = { |
619 | .get_brightness = dconbl_get, | 618 | .get_brightness = dconbl_get, |
620 | .update_status = dconbl_set | 619 | .update_status = dconbl_set |
621 | }; | 620 | }; |
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h index 6453ca4ba0ee..e566d213da2a 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ b/drivers/staging/olpc_dcon/olpc_dcon.h | |||
@@ -29,26 +29,6 @@ | |||
29 | #define DCON_REG_SCAN_INT 9 | 29 | #define DCON_REG_SCAN_INT 9 |
30 | #define DCON_REG_BRIGHT 10 | 30 | #define DCON_REG_BRIGHT 10 |
31 | 31 | ||
32 | /* GPIO registers (CS5536) */ | ||
33 | |||
34 | #define MSR_LBAR_GPIO 0x5140000C | ||
35 | |||
36 | #define GPIOx_OUT_VAL 0x00 | ||
37 | #define GPIOx_OUT_EN 0x04 | ||
38 | #define GPIOx_IN_EN 0x20 | ||
39 | #define GPIOx_INV_EN 0x24 | ||
40 | #define GPIOx_IN_FLTR_EN 0x28 | ||
41 | #define GPIOx_EVNTCNT_EN 0x2C | ||
42 | #define GPIOx_READ_BACK 0x30 | ||
43 | #define GPIOx_EVNT_EN 0x38 | ||
44 | #define GPIOx_NEGEDGE_EN 0x44 | ||
45 | #define GPIOx_NEGEDGE_STS 0x4C | ||
46 | #define GPIO_FLT7_AMNT 0xD8 | ||
47 | #define GPIO_MAP_X 0xE0 | ||
48 | #define GPIO_MAP_Y 0xE4 | ||
49 | #define GPIO_FE7_SEL 0xF7 | ||
50 | |||
51 | |||
52 | /* Status values */ | 32 | /* Status values */ |
53 | 33 | ||
54 | #define DCONSTAT_SCANINT 0 | 34 | #define DCONSTAT_SCANINT 0 |
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c index 779fb7d7b30c..043198dc6ff7 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c | |||
@@ -10,54 +10,70 @@ | |||
10 | * modify it under the terms of version 2 of the GNU General Public | 10 | * modify it under the terms of version 2 of the GNU General Public |
11 | * License as published by the Free Software Foundation. | 11 | * License as published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | #include <linux/cs5535.h> | |
14 | #include <linux/gpio.h> | ||
14 | #include <asm/olpc.h> | 15 | #include <asm/olpc.h> |
15 | 16 | ||
16 | #include "olpc_dcon.h" | 17 | #include "olpc_dcon.h" |
17 | 18 | ||
18 | /* Base address of the GPIO registers */ | ||
19 | static unsigned long gpio_base; | ||
20 | |||
21 | /* | ||
22 | * List of GPIOs that we care about: | ||
23 | * (in) GPIO12 -- DCONBLANK | ||
24 | * (in) GPIO[56] -- DCONSTAT[01] | ||
25 | * (out) GPIO11 -- DCONLOAD | ||
26 | */ | ||
27 | |||
28 | #define IN_GPIOS ((1<<5) | (1<<6) | (1<<7) | (1<<12)) | ||
29 | #define OUT_GPIOS (1<<11) | ||
30 | |||
31 | static int dcon_init_xo_1(void) | 19 | static int dcon_init_xo_1(void) |
32 | { | 20 | { |
33 | unsigned long lo, hi; | ||
34 | unsigned char lob; | 21 | unsigned char lob; |
35 | 22 | ||
36 | rdmsr(MSR_LBAR_GPIO, lo, hi); | 23 | if (gpio_request(OLPC_GPIO_DCON_STAT0, "OLPC-DCON")) { |
37 | 24 | printk(KERN_ERR "olpc-dcon: failed to request STAT0 GPIO\n"); | |
38 | /* Check the mask and whether GPIO is enabled (sanity check) */ | 25 | return -EIO; |
39 | if (hi != 0x0000f001) { | 26 | } |
40 | printk(KERN_ERR "GPIO not enabled -- cannot use DCON\n"); | 27 | if (gpio_request(OLPC_GPIO_DCON_STAT1, "OLPC-DCON")) { |
41 | return -ENODEV; | 28 | printk(KERN_ERR "olpc-dcon: failed to request STAT1 GPIO\n"); |
29 | goto err_gp_stat1; | ||
30 | } | ||
31 | if (gpio_request(OLPC_GPIO_DCON_IRQ, "OLPC-DCON")) { | ||
32 | printk(KERN_ERR "olpc-dcon: failed to request IRQ GPIO\n"); | ||
33 | goto err_gp_irq; | ||
34 | } | ||
35 | if (gpio_request(OLPC_GPIO_DCON_LOAD, "OLPC-DCON")) { | ||
36 | printk(KERN_ERR "olpc-dcon: failed to request LOAD GPIO\n"); | ||
37 | goto err_gp_load; | ||
38 | } | ||
39 | if (gpio_request(OLPC_GPIO_DCON_BLANK, "OLPC-DCON")) { | ||
40 | printk(KERN_ERR "olpc-dcon: failed to request BLANK GPIO\n"); | ||
41 | goto err_gp_blank; | ||
42 | } | 42 | } |
43 | |||
44 | /* Mask off the IO base address */ | ||
45 | gpio_base = lo & 0x0000ff00; | ||
46 | 43 | ||
47 | /* Turn off the event enable for GPIO7 just to be safe */ | 44 | /* Turn off the event enable for GPIO7 just to be safe */ |
48 | outl(1 << (16+7), gpio_base + GPIOx_EVNT_EN); | 45 | cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); |
46 | |||
47 | /* | ||
48 | * Determine the current state by reading the GPIO bit; earlier | ||
49 | * stages of the boot process have established the state. | ||
50 | * | ||
51 | * Note that we read GPIO_OUPUT_VAL rather than GPIO_READ_BACK here; | ||
52 | * this is because OFW will disable input for the pin and set a value.. | ||
53 | * READ_BACK will only contain a valid value if input is enabled and | ||
54 | * then a value is set. So, future readings of the pin can use | ||
55 | * READ_BACK, but the first one cannot. Awesome, huh? | ||
56 | */ | ||
57 | dcon_source = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL) | ||
58 | ? DCON_SOURCE_CPU | ||
59 | : DCON_SOURCE_DCON; | ||
60 | dcon_pending = dcon_source; | ||
49 | 61 | ||
50 | /* Set the directions for the GPIO pins */ | 62 | /* Set the directions for the GPIO pins */ |
51 | outl(OUT_GPIOS | (IN_GPIOS << 16), gpio_base + GPIOx_OUT_EN); | 63 | gpio_direction_input(OLPC_GPIO_DCON_STAT0); |
52 | outl(IN_GPIOS | (OUT_GPIOS << 16), gpio_base + GPIOx_IN_EN); | 64 | gpio_direction_input(OLPC_GPIO_DCON_STAT1); |
65 | gpio_direction_input(OLPC_GPIO_DCON_IRQ); | ||
66 | gpio_direction_input(OLPC_GPIO_DCON_BLANK); | ||
67 | gpio_direction_output(OLPC_GPIO_DCON_LOAD, | ||
68 | dcon_source == DCON_SOURCE_CPU); | ||
53 | 69 | ||
54 | /* Set up the interrupt mappings */ | 70 | /* Set up the interrupt mappings */ |
55 | 71 | ||
56 | /* Set the IRQ to pair 2 */ | 72 | /* Set the IRQ to pair 2 */ |
57 | geode_gpio_event_irq(OLPC_GPIO_DCON_IRQ, 2); | 73 | cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0); |
58 | 74 | ||
59 | /* Enable group 2 to trigger the DCON interrupt */ | 75 | /* Enable group 2 to trigger the DCON interrupt */ |
60 | geode_gpio_set_irq(2, DCON_IRQ); | 76 | cs5535_gpio_set_irq(2, DCON_IRQ); |
61 | 77 | ||
62 | /* Select edge level for interrupt (in PIC) */ | 78 | /* Select edge level for interrupt (in PIC) */ |
63 | lob = inb(0x4d0); | 79 | lob = inb(0x4d0); |
@@ -65,52 +81,61 @@ static int dcon_init_xo_1(void) | |||
65 | outb(lob, 0x4d0); | 81 | outb(lob, 0x4d0); |
66 | 82 | ||
67 | /* Register the interupt handler */ | 83 | /* Register the interupt handler */ |
68 | if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", &dcon_driver)) | 84 | if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", &dcon_driver)) { |
69 | return -EIO; | 85 | printk(KERN_ERR "olpc-dcon: failed to request DCON's irq\n"); |
86 | goto err_req_irq; | ||
87 | } | ||
70 | 88 | ||
71 | /* Clear INV_EN for GPIO7 (DCONIRQ) */ | 89 | /* Clear INV_EN for GPIO7 (DCONIRQ) */ |
72 | outl((1<<(16+7)), gpio_base + GPIOx_INV_EN); | 90 | cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT); |
73 | 91 | ||
74 | /* Enable filter for GPIO12 (DCONBLANK) */ | 92 | /* Enable filter for GPIO12 (DCONBLANK) */ |
75 | outl(1<<(12), gpio_base + GPIOx_IN_FLTR_EN); | 93 | cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER); |
76 | 94 | ||
77 | /* Disable filter for GPIO7 */ | 95 | /* Disable filter for GPIO7 */ |
78 | outl(1<<(16+7), gpio_base + GPIOx_IN_FLTR_EN); | 96 | cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER); |
79 | 97 | ||
80 | /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ | 98 | /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ |
81 | 99 | cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT); | |
82 | outl(1<<(16+7), gpio_base + GPIOx_EVNTCNT_EN); | 100 | cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT); |
83 | outl(1<<(16+12), gpio_base + GPIOx_EVNTCNT_EN); | ||
84 | 101 | ||
85 | /* Add GPIO12 to the Filter Event Pair #7 */ | 102 | /* Add GPIO12 to the Filter Event Pair #7 */ |
86 | outb(12, gpio_base + GPIO_FE7_SEL); | 103 | cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL); |
87 | 104 | ||
88 | /* Turn off negative Edge Enable for GPIO12 */ | 105 | /* Turn off negative Edge Enable for GPIO12 */ |
89 | outl(1<<(16+12), gpio_base + GPIOx_NEGEDGE_EN); | 106 | cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN); |
90 | 107 | ||
91 | /* Enable negative Edge Enable for GPIO7 */ | 108 | /* Enable negative Edge Enable for GPIO7 */ |
92 | outl(1<<7, gpio_base + GPIOx_NEGEDGE_EN); | 109 | cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN); |
93 | 110 | ||
94 | /* Zero the filter amount for Filter Event Pair #7 */ | 111 | /* Zero the filter amount for Filter Event Pair #7 */ |
95 | outw(0, gpio_base + GPIO_FLT7_AMNT); | 112 | cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT); |
96 | 113 | ||
97 | /* Clear the negative edge status for GPIO7 and GPIO12 */ | 114 | /* Clear the negative edge status for GPIO7 and GPIO12 */ |
98 | outl((1<<7) | (1<<12), gpio_base+0x4c); | 115 | cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); |
116 | cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS); | ||
99 | 117 | ||
100 | /* FIXME: Clear the posiitive status as well, just to be sure */ | 118 | /* FIXME: Clear the posiitive status as well, just to be sure */ |
101 | outl((1<<7) | (1<<12), gpio_base+0x48); | 119 | cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS); |
120 | cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS); | ||
102 | 121 | ||
103 | /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ | 122 | /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ |
104 | outl((1<<(7))|(1<<12), gpio_base + GPIOx_EVNT_EN); | 123 | cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); |
105 | 124 | cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE); | |
106 | /* Determine the current state by reading the GPIO bit */ | ||
107 | /* Earlier stages of the boot process have established the state */ | ||
108 | dcon_source = inl(gpio_base + GPIOx_OUT_VAL) & (1<<11) | ||
109 | ? DCON_SOURCE_CPU | ||
110 | : DCON_SOURCE_DCON; | ||
111 | dcon_pending = dcon_source; | ||
112 | 125 | ||
113 | return 0; | 126 | return 0; |
127 | |||
128 | err_req_irq: | ||
129 | gpio_free(OLPC_GPIO_DCON_BLANK); | ||
130 | err_gp_blank: | ||
131 | gpio_free(OLPC_GPIO_DCON_LOAD); | ||
132 | err_gp_load: | ||
133 | gpio_free(OLPC_GPIO_DCON_IRQ); | ||
134 | err_gp_irq: | ||
135 | gpio_free(OLPC_GPIO_DCON_STAT1); | ||
136 | err_gp_stat1: | ||
137 | gpio_free(OLPC_GPIO_DCON_STAT0); | ||
138 | return -EIO; | ||
114 | } | 139 | } |
115 | 140 | ||
116 | static void dcon_wiggle_xo_1(void) | 141 | static void dcon_wiggle_xo_1(void) |
@@ -128,37 +153,44 @@ static void dcon_wiggle_xo_1(void) | |||
128 | * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and | 153 | * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and |
129 | * GPIO15. | 154 | * GPIO15. |
130 | */ | 155 | */ |
131 | geode_gpio_set(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL); | 156 | cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); |
132 | geode_gpio_set(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE); | 157 | cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL); |
133 | geode_gpio_clear(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); | 158 | cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE); |
134 | geode_gpio_clear(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2); | 159 | cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE); |
135 | geode_gpio_clear(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); | 160 | cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); |
161 | cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); | ||
162 | cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2); | ||
163 | cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2); | ||
164 | cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); | ||
165 | cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); | ||
136 | 166 | ||
137 | for (x = 0; x < 16; x++) { | 167 | for (x = 0; x < 16; x++) { |
138 | udelay(5); | 168 | udelay(5); |
139 | geode_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); | 169 | cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); |
140 | udelay(5); | 170 | udelay(5); |
141 | geode_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); | 171 | cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); |
142 | } | 172 | } |
143 | udelay(5); | 173 | udelay(5); |
144 | geode_gpio_set(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); | 174 | cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); |
145 | geode_gpio_set(OLPC_GPIO_SMB_CLK|OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); | 175 | cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); |
176 | cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); | ||
177 | cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); | ||
146 | } | 178 | } |
147 | 179 | ||
148 | static void dcon_set_dconload_1(int val) | 180 | static void dcon_set_dconload_1(int val) |
149 | { | 181 | { |
150 | if (val) | 182 | gpio_set_value(OLPC_GPIO_DCON_LOAD, val); |
151 | outl(1<<11, gpio_base + GPIOx_OUT_VAL); | ||
152 | else | ||
153 | outl(1<<(11 + 16), gpio_base + GPIOx_OUT_VAL); | ||
154 | } | 183 | } |
155 | 184 | ||
156 | static int dcon_read_status_xo_1(void) | 185 | static u8 dcon_read_status_xo_1(void) |
157 | { | 186 | { |
158 | int status = inl(gpio_base + GPIOx_READ_BACK) >> 5; | 187 | u8 status; |
159 | 188 | ||
189 | status = gpio_get_value(OLPC_GPIO_DCON_STAT0); | ||
190 | status |= gpio_get_value(OLPC_GPIO_DCON_STAT1) << 1; | ||
191 | |||
160 | /* Clear the negative edge status for GPIO7 */ | 192 | /* Clear the negative edge status for GPIO7 */ |
161 | outl(1 << 7, gpio_base + GPIOx_NEGEDGE_STS); | 193 | cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); |
162 | 194 | ||
163 | return status; | 195 | return status; |
164 | } | 196 | } |
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c index cca6a235ef96..4f56098bb366 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c | |||
@@ -195,9 +195,9 @@ static void dcon_set_dconload_xo_1_5(int val) | |||
195 | } | 195 | } |
196 | } | 196 | } |
197 | 197 | ||
198 | static int dcon_read_status_xo_1_5(void) | 198 | static u8 dcon_read_status_xo_1_5(void) |
199 | { | 199 | { |
200 | int status; | 200 | u8 status; |
201 | 201 | ||
202 | if (!dcon_was_irq()) | 202 | if (!dcon_was_irq()) |
203 | return -1; | 203 | return -1; |
diff --git a/drivers/staging/pohmelfs/net.c b/drivers/staging/pohmelfs/net.c index 9279897ff161..b2e918622088 100644 --- a/drivers/staging/pohmelfs/net.c +++ b/drivers/staging/pohmelfs/net.c | |||
@@ -413,7 +413,7 @@ static int pohmelfs_readdir_response(struct netfs_state *st) | |||
413 | if (dentry) { | 413 | if (dentry) { |
414 | alias = d_materialise_unique(dentry, &npi->vfs_inode); | 414 | alias = d_materialise_unique(dentry, &npi->vfs_inode); |
415 | if (alias) | 415 | if (alias) |
416 | dput(dentry); | 416 | dput(alias); |
417 | } | 417 | } |
418 | 418 | ||
419 | dput(dentry); | 419 | dput(dentry); |
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c index ac2bf11e1119..701e8d52a9fa 100644 --- a/drivers/staging/samsung-laptop/samsung-laptop.c +++ b/drivers/staging/samsung-laptop/samsung-laptop.c | |||
@@ -269,7 +269,7 @@ static int update_status(struct backlight_device *bd) | |||
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
272 | static struct backlight_ops backlight_ops = { | 272 | static const struct backlight_ops backlight_ops = { |
273 | .get_brightness = get_brightness, | 273 | .get_brightness = get_brightness, |
274 | .update_status = update_status, | 274 | .update_status = update_status, |
275 | }; | 275 | }; |
diff --git a/drivers/staging/smbfs/dir.c b/drivers/staging/smbfs/dir.c index dd612f50749f..87a3a9bd5842 100644 --- a/drivers/staging/smbfs/dir.c +++ b/drivers/staging/smbfs/dir.c | |||
@@ -403,12 +403,6 @@ smb_delete_dentry(const struct dentry *dentry) | |||
403 | void | 403 | void |
404 | smb_new_dentry(struct dentry *dentry) | 404 | smb_new_dentry(struct dentry *dentry) |
405 | { | 405 | { |
406 | struct smb_sb_info *server = server_from_dentry(dentry); | ||
407 | |||
408 | if (server->mnt->flags & SMB_MOUNT_CASE) | ||
409 | d_set_d_op(dentry, &smbfs_dentry_operations_case); | ||
410 | else | ||
411 | d_set_d_op(dentry, &smbfs_dentry_operations); | ||
412 | dentry->d_time = jiffies; | 406 | dentry->d_time = jiffies; |
413 | } | 407 | } |
414 | 408 | ||
@@ -440,7 +434,6 @@ smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
440 | struct smb_fattr finfo; | 434 | struct smb_fattr finfo; |
441 | struct inode *inode; | 435 | struct inode *inode; |
442 | int error; | 436 | int error; |
443 | struct smb_sb_info *server; | ||
444 | 437 | ||
445 | error = -ENAMETOOLONG; | 438 | error = -ENAMETOOLONG; |
446 | if (dentry->d_name.len > SMB_MAXNAMELEN) | 439 | if (dentry->d_name.len > SMB_MAXNAMELEN) |
@@ -468,12 +461,6 @@ smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
468 | inode = smb_iget(dir->i_sb, &finfo); | 461 | inode = smb_iget(dir->i_sb, &finfo); |
469 | if (inode) { | 462 | if (inode) { |
470 | add_entry: | 463 | add_entry: |
471 | server = server_from_dentry(dentry); | ||
472 | if (server->mnt->flags & SMB_MOUNT_CASE) | ||
473 | d_set_d_op(dentry, &smbfs_dentry_operations_case); | ||
474 | else | ||
475 | d_set_d_op(dentry, &smbfs_dentry_operations); | ||
476 | |||
477 | d_add(dentry, inode); | 464 | d_add(dentry, inode); |
478 | smb_renew_times(dentry); | 465 | smb_renew_times(dentry); |
479 | error = 0; | 466 | error = 0; |
diff --git a/drivers/staging/smbfs/inode.c b/drivers/staging/smbfs/inode.c index 244319dc9702..0778589d9e9e 100644 --- a/drivers/staging/smbfs/inode.c +++ b/drivers/staging/smbfs/inode.c | |||
@@ -614,6 +614,10 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
614 | printk(KERN_ERR "smbfs: failed to start smbiod\n"); | 614 | printk(KERN_ERR "smbfs: failed to start smbiod\n"); |
615 | goto out_no_smbiod; | 615 | goto out_no_smbiod; |
616 | } | 616 | } |
617 | if (server->mnt->flags & SMB_MOUNT_CASE) | ||
618 | sb->s_d_op = &smbfs_dentry_operations_case; | ||
619 | else | ||
620 | sb->s_d_op = &smbfs_dentry_operations; | ||
617 | 621 | ||
618 | /* | 622 | /* |
619 | * Keep the super block locked while we get the root inode. | 623 | * Keep the super block locked while we get the root inode. |
diff --git a/drivers/staging/smbfs/proto.h b/drivers/staging/smbfs/proto.h index 05939a6f43e6..3883cb16a3f6 100644 --- a/drivers/staging/smbfs/proto.h +++ b/drivers/staging/smbfs/proto.h | |||
@@ -38,6 +38,8 @@ extern void smb_install_null_ops(struct smb_ops *ops); | |||
38 | extern const struct file_operations smb_dir_operations; | 38 | extern const struct file_operations smb_dir_operations; |
39 | extern const struct inode_operations smb_dir_inode_operations; | 39 | extern const struct inode_operations smb_dir_inode_operations; |
40 | extern const struct inode_operations smb_dir_inode_operations_unix; | 40 | extern const struct inode_operations smb_dir_inode_operations_unix; |
41 | extern const struct dentry_operations smbfs_dentry_operations_case; | ||
42 | extern const struct dentry_operations smbfs_dentry_operations; | ||
41 | extern void smb_new_dentry(struct dentry *dentry); | 43 | extern void smb_new_dentry(struct dentry *dentry); |
42 | extern void smb_renew_times(struct dentry *dentry); | 44 | extern void smb_renew_times(struct dentry *dentry); |
43 | /* cache.c */ | 45 | /* cache.c */ |
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 0d236f4bb8c2..b00101972f20 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c | |||
@@ -284,12 +284,11 @@ static int samplerate = 100; | |||
284 | 284 | ||
285 | module_param(ixjdebug, int, 0); | 285 | module_param(ixjdebug, int, 0); |
286 | 286 | ||
287 | static struct pci_device_id ixj_pci_tbl[] __devinitdata = { | 287 | static DEFINE_PCI_DEVICE_TABLE(ixj_pci_tbl) = { |
288 | { PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ, | 288 | { PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ, |
289 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 289 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
290 | { } | 290 | { } |
291 | }; | 291 | }; |
292 | |||
293 | MODULE_DEVICE_TABLE(pci, ixj_pci_tbl); | 292 | MODULE_DEVICE_TABLE(pci, ixj_pci_tbl); |
294 | 293 | ||
295 | /************************************************************************ | 294 | /************************************************************************ |
@@ -6581,7 +6580,8 @@ static long do_ixj_ioctl(struct file *file_p, unsigned int cmd, unsigned long ar | |||
6581 | case IXJCTL_SET_FILTER: | 6580 | case IXJCTL_SET_FILTER: |
6582 | if (copy_from_user(&jf, argp, sizeof(jf))) | 6581 | if (copy_from_user(&jf, argp, sizeof(jf))) |
6583 | retval = -EFAULT; | 6582 | retval = -EFAULT; |
6584 | retval = ixj_init_filter(j, &jf); | 6583 | else |
6584 | retval = ixj_init_filter(j, &jf); | ||
6585 | break; | 6585 | break; |
6586 | case IXJCTL_SET_FILTER_RAW: | 6586 | case IXJCTL_SET_FILTER_RAW: |
6587 | if (copy_from_user(&jfr, argp, sizeof(jfr))) | 6587 | if (copy_from_user(&jfr, argp, sizeof(jfr))) |
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 1210534822d6..5408186afc35 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c | |||
@@ -1320,7 +1320,7 @@ static struct imx_udc_struct controller = { | |||
1320 | }; | 1320 | }; |
1321 | 1321 | ||
1322 | /******************************************************************************* | 1322 | /******************************************************************************* |
1323 | * USB gadged driver functions | 1323 | * USB gadget driver functions |
1324 | ******************************************************************************* | 1324 | ******************************************************************************* |
1325 | */ | 1325 | */ |
1326 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver, | 1326 | int usb_gadget_probe_driver(struct usb_gadget_driver *driver, |
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 777972454e3e..1eca8b47ce3c 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c | |||
@@ -3086,7 +3086,7 @@ static void langwell_udc_remove(struct pci_dev *pdev) | |||
3086 | 3086 | ||
3087 | kfree(dev->ep); | 3087 | kfree(dev->ep); |
3088 | 3088 | ||
3089 | /* diable IRQ handler */ | 3089 | /* disable IRQ handler */ |
3090 | if (dev->got_irq) | 3090 | if (dev->got_irq) |
3091 | free_irq(pdev->irq, dev); | 3091 | free_irq(pdev->irq, dev); |
3092 | 3092 | ||
@@ -3406,7 +3406,7 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3406 | /* disable interrupt and set controller to stop state */ | 3406 | /* disable interrupt and set controller to stop state */ |
3407 | langwell_udc_stop(dev); | 3407 | langwell_udc_stop(dev); |
3408 | 3408 | ||
3409 | /* diable IRQ handler */ | 3409 | /* disable IRQ handler */ |
3410 | if (dev->got_irq) | 3410 | if (dev->got_irq) |
3411 | free_irq(pdev->irq, dev); | 3411 | free_irq(pdev->irq, dev); |
3412 | dev->got_irq = 0; | 3412 | dev->got_irq = 0; |
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 20092a27a1e8..12fd184226f2 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c | |||
@@ -98,13 +98,13 @@ void fhci_usb_enable_interrupt(struct fhci_usb *usb) | |||
98 | usb->intr_nesting_cnt--; | 98 | usb->intr_nesting_cnt--; |
99 | } | 99 | } |
100 | 100 | ||
101 | /* diable the usb interrupt */ | 101 | /* disable the usb interrupt */ |
102 | void fhci_usb_disable_interrupt(struct fhci_usb *usb) | 102 | void fhci_usb_disable_interrupt(struct fhci_usb *usb) |
103 | { | 103 | { |
104 | struct fhci_hcd *fhci = usb->fhci; | 104 | struct fhci_hcd *fhci = usb->fhci; |
105 | 105 | ||
106 | if (usb->intr_nesting_cnt == 0) { | 106 | if (usb->intr_nesting_cnt == 0) { |
107 | /* diable the timer interrupt */ | 107 | /* disable the timer interrupt */ |
108 | disable_irq_nosync(fhci->timer->irq); | 108 | disable_irq_nosync(fhci->timer->irq); |
109 | 109 | ||
110 | /* disable the usb interrupt */ | 110 | /* disable the usb interrupt */ |
diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index 7be548ca2183..38fe058fbe61 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c | |||
@@ -271,8 +271,8 @@ void fhci_init_ep_registers(struct fhci_usb *usb, struct endpoint *ep, | |||
271 | 271 | ||
272 | /* | 272 | /* |
273 | * Collect the submitted frames and inform the application about them | 273 | * Collect the submitted frames and inform the application about them |
274 | * It is also prepearing the TDs for new frames. If the Tx interrupts | 274 | * It is also preparing the TDs for new frames. If the Tx interrupts |
275 | * are diabled, the application should call that routine to get | 275 | * are disabled, the application should call that routine to get |
276 | * confirmation about the submitted frames. Otherwise, the routine is | 276 | * confirmation about the submitted frames. Otherwise, the routine is |
277 | * called frome the interrupt service routine during the Tx interrupt. | 277 | * called frome the interrupt service routine during the Tx interrupt. |
278 | * In that case the application is informed by calling the application | 278 | * In that case the application is informed by calling the application |
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index e49b75a78000..f90d003f2302 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c | |||
@@ -1658,7 +1658,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd) | |||
1658 | 1658 | ||
1659 | spin_lock_irqsave(&imx21->lock, flags); | 1659 | spin_lock_irqsave(&imx21->lock, flags); |
1660 | 1660 | ||
1661 | /* Reset the Host controler modules */ | 1661 | /* Reset the Host controller modules */ |
1662 | writel(USBOTG_RST_RSTCTRL | USBOTG_RST_RSTRH | | 1662 | writel(USBOTG_RST_RSTCTRL | USBOTG_RST_RSTRH | |
1663 | USBOTG_RST_RSTHSIE | USBOTG_RST_RSTHC, | 1663 | USBOTG_RST_RSTHSIE | USBOTG_RST_RSTHC, |
1664 | imx21->regs + USBOTG_RST_CTRL); | 1664 | imx21->regs + USBOTG_RST_CTRL); |
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 32149be4ad8e..e0cb12b573f9 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c | |||
@@ -3094,7 +3094,7 @@ static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
3094 | 3094 | ||
3095 | /* Some boards (mostly VIA?) report bogus overcurrent indications, | 3095 | /* Some boards (mostly VIA?) report bogus overcurrent indications, |
3096 | * causing massive log spam unless we completely ignore them. It | 3096 | * causing massive log spam unless we completely ignore them. It |
3097 | * may be relevant that VIA VT8235 controlers, where PORT_POWER is | 3097 | * may be relevant that VIA VT8235 controllers, where PORT_POWER is |
3098 | * always set, seem to clear PORT_OCC and PORT_CSC when writing to | 3098 | * always set, seem to clear PORT_OCC and PORT_CSC when writing to |
3099 | * PORT_POWER; that's surprising, but maybe within-spec. | 3099 | * PORT_POWER; that's surprising, but maybe within-spec. |
3100 | */ | 3100 | */ |
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 44f8b9225054..a6afd15f6a46 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
@@ -717,7 +717,7 @@ static int adu_probe(struct usb_interface *interface, | |||
717 | goto exit; | 717 | goto exit; |
718 | } | 718 | } |
719 | 719 | ||
720 | /* allocate memory for our device state and intialize it */ | 720 | /* allocate memory for our device state and initialize it */ |
721 | dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL); | 721 | dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL); |
722 | if (dev == NULL) { | 722 | if (dev == NULL) { |
723 | dev_err(&interface->dev, "Out of memory\n"); | 723 | dev_err(&interface->dev, "Out of memory\n"); |
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index c9078e4e1f4d..e573e4704015 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c | |||
@@ -769,7 +769,7 @@ static int iowarrior_probe(struct usb_interface *interface, | |||
769 | int i; | 769 | int i; |
770 | int retval = -ENOMEM; | 770 | int retval = -ENOMEM; |
771 | 771 | ||
772 | /* allocate memory for our device state and intialize it */ | 772 | /* allocate memory for our device state and initialize it */ |
773 | dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); | 773 | dev = kzalloc(sizeof(struct iowarrior), GFP_KERNEL); |
774 | if (dev == NULL) { | 774 | if (dev == NULL) { |
775 | dev_err(&interface->dev, "Out of memory\n"); | 775 | dev_err(&interface->dev, "Out of memory\n"); |
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index edffef642337..eefb8275bb7e 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c | |||
@@ -642,7 +642,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * | |||
642 | int i; | 642 | int i; |
643 | int retval = -ENOMEM; | 643 | int retval = -ENOMEM; |
644 | 644 | ||
645 | /* allocate memory for our device state and intialize it */ | 645 | /* allocate memory for our device state and initialize it */ |
646 | 646 | ||
647 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 647 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
648 | if (dev == NULL) { | 648 | if (dev == NULL) { |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 9b162dfaa4fb..ed58c6c8f15c 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -1684,7 +1684,7 @@ static inline void __init musb_g_init_endpoints(struct musb *musb) | |||
1684 | struct musb_hw_ep *hw_ep; | 1684 | struct musb_hw_ep *hw_ep; |
1685 | unsigned count = 0; | 1685 | unsigned count = 0; |
1686 | 1686 | ||
1687 | /* intialize endpoint list just once */ | 1687 | /* initialize endpoint list just once */ |
1688 | INIT_LIST_HEAD(&(musb->g.ep_list)); | 1688 | INIT_LIST_HEAD(&(musb->g.ep_list)); |
1689 | 1689 | ||
1690 | for (epnum = 0, hw_ep = musb->endpoints; | 1690 | for (epnum = 0, hw_ep = musb->endpoints; |
@@ -1765,7 +1765,7 @@ void musb_gadget_cleanup(struct musb *musb) | |||
1765 | * | 1765 | * |
1766 | * -EINVAL something went wrong (not driver) | 1766 | * -EINVAL something went wrong (not driver) |
1767 | * -EBUSY another gadget is already using the controller | 1767 | * -EBUSY another gadget is already using the controller |
1768 | * -ENOMEM no memeory to perform the operation | 1768 | * -ENOMEM no memory to perform the operation |
1769 | * | 1769 | * |
1770 | * @param driver the gadget driver | 1770 | * @param driver the gadget driver |
1771 | * @param bind the driver's bind function | 1771 | * @param bind the driver's bind function |
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index c7b1d8108de9..8cb9d80207fa 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c | |||
@@ -49,7 +49,7 @@ | |||
49 | * | 49 | * |
50 | * USB Stack port number 4 (1 based) | 50 | * USB Stack port number 4 (1 based) |
51 | * WUSB code port index 3 (0 based) | 51 | * WUSB code port index 3 (0 based) |
52 | * USB Addresss 5 (2 based -- 0 is for default, 1 for root hub) | 52 | * USB Address 5 (2 based -- 0 is for default, 1 for root hub) |
53 | * | 53 | * |
54 | * Now, because we don't use the concept as default address exactly | 54 | * Now, because we don't use the concept as default address exactly |
55 | * like the (wired) USB code does, we need to kind of skip it. So we | 55 | * like the (wired) USB code does, we need to kind of skip it. So we |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 55dc6fb6e909..d916ac04abab 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -11,6 +11,13 @@ config HAVE_FB_ATMEL | |||
11 | config HAVE_FB_IMX | 11 | config HAVE_FB_IMX |
12 | bool | 12 | bool |
13 | 13 | ||
14 | config SH_MIPI_DSI | ||
15 | tristate | ||
16 | depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | ||
17 | |||
18 | config SH_LCD_MIPI_DSI | ||
19 | bool | ||
20 | |||
14 | source "drivers/char/agp/Kconfig" | 21 | source "drivers/char/agp/Kconfig" |
15 | 22 | ||
16 | source "drivers/gpu/vga/Kconfig" | 23 | source "drivers/gpu/vga/Kconfig" |
@@ -414,7 +421,7 @@ config FB_SA1100 | |||
414 | Y here. | 421 | Y here. |
415 | 422 | ||
416 | config FB_IMX | 423 | config FB_IMX |
417 | tristate "Motorola i.MX LCD support" | 424 | tristate "Freescale i.MX LCD support" |
418 | depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2) | 425 | depends on FB && (HAVE_FB_IMX || ARCH_MX1 || ARCH_MX2) |
419 | select FB_CFB_FILLRECT | 426 | select FB_CFB_FILLRECT |
420 | select FB_CFB_COPYAREA | 427 | select FB_CFB_COPYAREA |
@@ -1273,7 +1280,7 @@ config FB_MATROX | |||
1273 | module will be called matroxfb. | 1280 | module will be called matroxfb. |
1274 | 1281 | ||
1275 | You can pass several parameters to the driver at boot time or at | 1282 | You can pass several parameters to the driver at boot time or at |
1276 | module load time. The parameters look like "video=matrox:XXX", and | 1283 | module load time. The parameters look like "video=matroxfb:XXX", and |
1277 | are described in <file:Documentation/fb/matroxfb.txt>. | 1284 | are described in <file:Documentation/fb/matroxfb.txt>. |
1278 | 1285 | ||
1279 | config FB_MATROX_MILLENIUM | 1286 | config FB_MATROX_MILLENIUM |
@@ -1990,13 +1997,6 @@ config FB_W100 | |||
1990 | 1997 | ||
1991 | If unsure, say N. | 1998 | If unsure, say N. |
1992 | 1999 | ||
1993 | config SH_MIPI_DSI | ||
1994 | tristate | ||
1995 | depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | ||
1996 | |||
1997 | config SH_LCD_MIPI_DSI | ||
1998 | bool | ||
1999 | |||
2000 | config FB_SH_MOBILE_LCDC | 2000 | config FB_SH_MOBILE_LCDC |
2001 | tristate "SuperH Mobile LCDC framebuffer support" | 2001 | tristate "SuperH Mobile LCDC framebuffer support" |
2002 | depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | 2002 | depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 8dce25126330..bac163450216 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -111,7 +111,7 @@ static int atmel_bl_get_brightness(struct backlight_device *bl) | |||
111 | return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | 111 | return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct backlight_ops atmel_lcdc_bl_ops = { | 114 | static const struct backlight_ops atmel_lcdc_bl_ops = { |
115 | .update_status = atmel_bl_update_status, | 115 | .update_status = atmel_bl_update_status, |
116 | .get_brightness = atmel_bl_get_brightness, | 116 | .get_brightness = atmel_bl_get_brightness, |
117 | }; | 117 | }; |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 34a0851bcbfa..dd9de2e80580 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -1786,7 +1786,7 @@ static int aty128_bl_get_brightness(struct backlight_device *bd) | |||
1786 | return bd->props.brightness; | 1786 | return bd->props.brightness; |
1787 | } | 1787 | } |
1788 | 1788 | ||
1789 | static struct backlight_ops aty128_bl_data = { | 1789 | static const struct backlight_ops aty128_bl_data = { |
1790 | .get_brightness = aty128_bl_get_brightness, | 1790 | .get_brightness = aty128_bl_get_brightness, |
1791 | .update_status = aty128_bl_update_status, | 1791 | .update_status = aty128_bl_update_status, |
1792 | }; | 1792 | }; |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 5a3ce3ad1ec8..767ab4fb1a05 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
@@ -2221,7 +2221,7 @@ static int aty_bl_get_brightness(struct backlight_device *bd) | |||
2221 | return bd->props.brightness; | 2221 | return bd->props.brightness; |
2222 | } | 2222 | } |
2223 | 2223 | ||
2224 | static struct backlight_ops aty_bl_data = { | 2224 | static const struct backlight_ops aty_bl_data = { |
2225 | .get_brightness = aty_bl_get_brightness, | 2225 | .get_brightness = aty_bl_get_brightness, |
2226 | .update_status = aty_bl_update_status, | 2226 | .update_status = aty_bl_update_status, |
2227 | }; | 2227 | }; |
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index 256966e9667d..9b811ddbce83 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c | |||
@@ -128,7 +128,7 @@ static int radeon_bl_get_brightness(struct backlight_device *bd) | |||
128 | return bd->props.brightness; | 128 | return bd->props.brightness; |
129 | } | 129 | } |
130 | 130 | ||
131 | static struct backlight_ops radeon_bl_data = { | 131 | static const struct backlight_ops radeon_bl_data = { |
132 | .get_brightness = radeon_bl_get_brightness, | 132 | .get_brightness = radeon_bl_get_brightness, |
133 | .update_status = radeon_bl_update_status, | 133 | .update_status = radeon_bl_update_status, |
134 | }; | 134 | }; |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 38ffc3fbcbe4..c789c46e38af 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -155,7 +155,7 @@ out: | |||
155 | return -EINVAL; | 155 | return -EINVAL; |
156 | } | 156 | } |
157 | 157 | ||
158 | static struct backlight_ops pm860x_backlight_ops = { | 158 | static const struct backlight_ops pm860x_backlight_ops = { |
159 | .options = BL_CORE_SUSPENDRESUME, | 159 | .options = BL_CORE_SUSPENDRESUME, |
160 | .update_status = pm860x_backlight_update_status, | 160 | .update_status = pm860x_backlight_update_status, |
161 | .get_brightness = pm860x_backlight_get_brightness, | 161 | .get_brightness = pm860x_backlight_get_brightness, |
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index c67801e57aaf..98ad3e5f7c85 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c | |||
@@ -25,7 +25,7 @@ | |||
25 | struct l4f00242t03_priv { | 25 | struct l4f00242t03_priv { |
26 | struct spi_device *spi; | 26 | struct spi_device *spi; |
27 | struct lcd_device *ld; | 27 | struct lcd_device *ld; |
28 | int lcd_on:1; | 28 | int lcd_state; |
29 | struct regulator *io_reg; | 29 | struct regulator *io_reg; |
30 | struct regulator *core_reg; | 30 | struct regulator *core_reg; |
31 | }; | 31 | }; |
@@ -62,11 +62,36 @@ static void l4f00242t03_lcd_init(struct spi_device *spi) | |||
62 | regulator_enable(priv->core_reg); | 62 | regulator_enable(priv->core_reg); |
63 | } | 63 | } |
64 | 64 | ||
65 | l4f00242t03_reset(pdata->reset_gpio); | ||
66 | |||
65 | gpio_set_value(pdata->data_enable_gpio, 1); | 67 | gpio_set_value(pdata->data_enable_gpio, 1); |
66 | msleep(60); | 68 | msleep(60); |
67 | spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16)); | 69 | spi_write(spi, (const u8 *)cmd, ARRAY_SIZE(cmd) * sizeof(u16)); |
68 | } | 70 | } |
69 | 71 | ||
72 | static void l4f00242t03_lcd_powerdown(struct spi_device *spi) | ||
73 | { | ||
74 | struct l4f00242t03_pdata *pdata = spi->dev.platform_data; | ||
75 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | ||
76 | |||
77 | dev_dbg(&spi->dev, "Powering down LCD\n"); | ||
78 | |||
79 | gpio_set_value(pdata->data_enable_gpio, 0); | ||
80 | |||
81 | if (priv->io_reg) | ||
82 | regulator_disable(priv->io_reg); | ||
83 | |||
84 | if (priv->core_reg) | ||
85 | regulator_disable(priv->core_reg); | ||
86 | } | ||
87 | |||
88 | static int l4f00242t03_lcd_power_get(struct lcd_device *ld) | ||
89 | { | ||
90 | struct l4f00242t03_priv *priv = lcd_get_data(ld); | ||
91 | |||
92 | return priv->lcd_state; | ||
93 | } | ||
94 | |||
70 | static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) | 95 | static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) |
71 | { | 96 | { |
72 | struct l4f00242t03_priv *priv = lcd_get_data(ld); | 97 | struct l4f00242t03_priv *priv = lcd_get_data(ld); |
@@ -79,35 +104,54 @@ static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) | |||
79 | const u16 disoff = 0x28; | 104 | const u16 disoff = 0x28; |
80 | 105 | ||
81 | if (power <= FB_BLANK_NORMAL) { | 106 | if (power <= FB_BLANK_NORMAL) { |
82 | if (priv->lcd_on) | 107 | if (priv->lcd_state <= FB_BLANK_NORMAL) { |
83 | return 0; | 108 | /* Do nothing, the LCD is running */ |
84 | 109 | } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { | |
85 | dev_dbg(&spi->dev, "turning on LCD\n"); | 110 | dev_dbg(&spi->dev, "Resuming LCD\n"); |
86 | 111 | ||
87 | spi_write(spi, (const u8 *)&slpout, sizeof(u16)); | 112 | spi_write(spi, (const u8 *)&slpout, sizeof(u16)); |
88 | msleep(60); | 113 | msleep(60); |
89 | spi_write(spi, (const u8 *)&dison, sizeof(u16)); | 114 | spi_write(spi, (const u8 *)&dison, sizeof(u16)); |
90 | 115 | } else { | |
91 | priv->lcd_on = 1; | 116 | /* priv->lcd_state == FB_BLANK_POWERDOWN */ |
117 | l4f00242t03_lcd_init(spi); | ||
118 | priv->lcd_state = FB_BLANK_VSYNC_SUSPEND; | ||
119 | l4f00242t03_lcd_power_set(priv->ld, power); | ||
120 | } | ||
121 | } else if (power < FB_BLANK_POWERDOWN) { | ||
122 | if (priv->lcd_state <= FB_BLANK_NORMAL) { | ||
123 | /* Send the display in standby */ | ||
124 | dev_dbg(&spi->dev, "Standby the LCD\n"); | ||
125 | |||
126 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); | ||
127 | msleep(60); | ||
128 | spi_write(spi, (const u8 *)&slpin, sizeof(u16)); | ||
129 | } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { | ||
130 | /* Do nothing, the LCD is already in standby */ | ||
131 | } else { | ||
132 | /* priv->lcd_state == FB_BLANK_POWERDOWN */ | ||
133 | l4f00242t03_lcd_init(spi); | ||
134 | priv->lcd_state = FB_BLANK_UNBLANK; | ||
135 | l4f00242t03_lcd_power_set(ld, power); | ||
136 | } | ||
92 | } else { | 137 | } else { |
93 | if (!priv->lcd_on) | 138 | /* power == FB_BLANK_POWERDOWN */ |
94 | return 0; | 139 | if (priv->lcd_state != FB_BLANK_POWERDOWN) { |
95 | 140 | /* Clear the screen before shutting down */ | |
96 | dev_dbg(&spi->dev, "turning off LCD\n"); | 141 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); |
97 | 142 | msleep(60); | |
98 | spi_write(spi, (const u8 *)&disoff, sizeof(u16)); | 143 | l4f00242t03_lcd_powerdown(spi); |
99 | msleep(60); | 144 | } |
100 | spi_write(spi, (const u8 *)&slpin, sizeof(u16)); | ||
101 | |||
102 | priv->lcd_on = 0; | ||
103 | } | 145 | } |
104 | 146 | ||
147 | priv->lcd_state = power; | ||
148 | |||
105 | return 0; | 149 | return 0; |
106 | } | 150 | } |
107 | 151 | ||
108 | static struct lcd_ops l4f_ops = { | 152 | static struct lcd_ops l4f_ops = { |
109 | .set_power = l4f00242t03_lcd_power_set, | 153 | .set_power = l4f00242t03_lcd_power_set, |
110 | .get_power = NULL, | 154 | .get_power = l4f00242t03_lcd_power_get, |
111 | }; | 155 | }; |
112 | 156 | ||
113 | static int __devinit l4f00242t03_probe(struct spi_device *spi) | 157 | static int __devinit l4f00242t03_probe(struct spi_device *spi) |
@@ -185,9 +229,9 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
185 | } | 229 | } |
186 | 230 | ||
187 | /* Init the LCD */ | 231 | /* Init the LCD */ |
188 | l4f00242t03_reset(pdata->reset_gpio); | ||
189 | l4f00242t03_lcd_init(spi); | 232 | l4f00242t03_lcd_init(spi); |
190 | l4f00242t03_lcd_power_set(priv->ld, 1); | 233 | priv->lcd_state = FB_BLANK_VSYNC_SUSPEND; |
234 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_UNBLANK); | ||
191 | 235 | ||
192 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); | 236 | dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); |
193 | 237 | ||
@@ -214,9 +258,11 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi) | |||
214 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | 258 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); |
215 | struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; | 259 | struct l4f00242t03_pdata *pdata = priv->spi->dev.platform_data; |
216 | 260 | ||
217 | l4f00242t03_lcd_power_set(priv->ld, 0); | 261 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); |
218 | lcd_device_unregister(priv->ld); | 262 | lcd_device_unregister(priv->ld); |
219 | 263 | ||
264 | dev_set_drvdata(&spi->dev, NULL); | ||
265 | |||
220 | gpio_free(pdata->data_enable_gpio); | 266 | gpio_free(pdata->data_enable_gpio); |
221 | gpio_free(pdata->reset_gpio); | 267 | gpio_free(pdata->reset_gpio); |
222 | 268 | ||
@@ -230,6 +276,15 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi) | |||
230 | return 0; | 276 | return 0; |
231 | } | 277 | } |
232 | 278 | ||
279 | static void l4f00242t03_shutdown(struct spi_device *spi) | ||
280 | { | ||
281 | struct l4f00242t03_priv *priv = dev_get_drvdata(&spi->dev); | ||
282 | |||
283 | if (priv) | ||
284 | l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); | ||
285 | |||
286 | } | ||
287 | |||
233 | static struct spi_driver l4f00242t03_driver = { | 288 | static struct spi_driver l4f00242t03_driver = { |
234 | .driver = { | 289 | .driver = { |
235 | .name = "l4f00242t03", | 290 | .name = "l4f00242t03", |
@@ -237,6 +292,7 @@ static struct spi_driver l4f00242t03_driver = { | |||
237 | }, | 292 | }, |
238 | .probe = l4f00242t03_probe, | 293 | .probe = l4f00242t03_probe, |
239 | .remove = __devexit_p(l4f00242t03_remove), | 294 | .remove = __devexit_p(l4f00242t03_remove), |
295 | .shutdown = l4f00242t03_shutdown, | ||
240 | }; | 296 | }; |
241 | 297 | ||
242 | static __init int l4f00242t03_init(void) | 298 | static __init int l4f00242t03_init(void) |
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index b2b2c7ba1f63..209acc105cbc 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c | |||
@@ -92,7 +92,7 @@ static int max8925_backlight_get_brightness(struct backlight_device *bl) | |||
92 | return ret; | 92 | return ret; |
93 | } | 93 | } |
94 | 94 | ||
95 | static struct backlight_ops max8925_backlight_ops = { | 95 | static const struct backlight_ops max8925_backlight_ops = { |
96 | .options = BL_CORE_SUSPENDRESUME, | 96 | .options = BL_CORE_SUSPENDRESUME, |
97 | .update_status = max8925_backlight_update_status, | 97 | .update_status = max8925_backlight_update_status, |
98 | .get_brightness = max8925_backlight_get_brightness, | 98 | .get_brightness = max8925_backlight_get_brightness, |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 915448ec75bf..c97491b8b39b 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -375,7 +375,8 @@ static const char *vgacon_startup(void) | |||
375 | u16 saved1, saved2; | 375 | u16 saved1, saved2; |
376 | volatile u16 *p; | 376 | volatile u16 *p; |
377 | 377 | ||
378 | if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) { | 378 | if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB || |
379 | screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) { | ||
379 | no_vga: | 380 | no_vga: |
380 | #ifdef CONFIG_DUMMY_CONSOLE | 381 | #ifdef CONFIG_DUMMY_CONSOLE |
381 | conswitchp = &dummy_con; | 382 | conswitchp = &dummy_con; |
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 1ab2c2588675..69bd4a581d4a 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -974,6 +974,6 @@ static void __exit imxfb_cleanup(void) | |||
974 | module_init(imxfb_init); | 974 | module_init(imxfb_init); |
975 | module_exit(imxfb_cleanup); | 975 | module_exit(imxfb_cleanup); |
976 | 976 | ||
977 | MODULE_DESCRIPTION("Motorola i.MX framebuffer driver"); | 977 | MODULE_DESCRIPTION("Freescale i.MX framebuffer driver"); |
978 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | 978 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); |
979 | MODULE_LICENSE("GPL"); | 979 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 052dd9f0b760..a082debe824b 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -1247,46 +1247,46 @@ static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; | |||
1247 | }; | 1247 | }; |
1248 | 1248 | ||
1249 | /* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */ | 1249 | /* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */ |
1250 | static unsigned int mem; /* "matrox:mem:xxxxxM" */ | 1250 | static unsigned int mem; /* "matroxfb:mem:xxxxxM" */ |
1251 | static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */ | 1251 | static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */ |
1252 | static int inv24; /* "matrox:inv24" */ | 1252 | static int inv24; /* "matroxfb:inv24" */ |
1253 | static int cross4MB = -1; /* "matrox:cross4MB" */ | 1253 | static int cross4MB = -1; /* "matroxfb:cross4MB" */ |
1254 | static int disabled; /* "matrox:disabled" */ | 1254 | static int disabled; /* "matroxfb:disabled" */ |
1255 | static int noaccel; /* "matrox:noaccel" */ | 1255 | static int noaccel; /* "matroxfb:noaccel" */ |
1256 | static int nopan; /* "matrox:nopan" */ | 1256 | static int nopan; /* "matroxfb:nopan" */ |
1257 | static int no_pci_retry; /* "matrox:nopciretry" */ | 1257 | static int no_pci_retry; /* "matroxfb:nopciretry" */ |
1258 | static int novga; /* "matrox:novga" */ | 1258 | static int novga; /* "matroxfb:novga" */ |
1259 | static int nobios; /* "matrox:nobios" */ | 1259 | static int nobios; /* "matroxfb:nobios" */ |
1260 | static int noinit = 1; /* "matrox:init" */ | 1260 | static int noinit = 1; /* "matroxfb:init" */ |
1261 | static int inverse; /* "matrox:inverse" */ | 1261 | static int inverse; /* "matroxfb:inverse" */ |
1262 | static int sgram; /* "matrox:sgram" */ | 1262 | static int sgram; /* "matroxfb:sgram" */ |
1263 | #ifdef CONFIG_MTRR | 1263 | #ifdef CONFIG_MTRR |
1264 | static int mtrr = 1; /* "matrox:nomtrr" */ | 1264 | static int mtrr = 1; /* "matroxfb:nomtrr" */ |
1265 | #endif | 1265 | #endif |
1266 | static int grayscale; /* "matrox:grayscale" */ | 1266 | static int grayscale; /* "matroxfb:grayscale" */ |
1267 | static int dev = -1; /* "matrox:dev:xxxxx" */ | 1267 | static int dev = -1; /* "matroxfb:dev:xxxxx" */ |
1268 | static unsigned int vesa = ~0; /* "matrox:vesa:xxxxx" */ | 1268 | static unsigned int vesa = ~0; /* "matroxfb:vesa:xxxxx" */ |
1269 | static int depth = -1; /* "matrox:depth:xxxxx" */ | 1269 | static int depth = -1; /* "matroxfb:depth:xxxxx" */ |
1270 | static unsigned int xres; /* "matrox:xres:xxxxx" */ | 1270 | static unsigned int xres; /* "matroxfb:xres:xxxxx" */ |
1271 | static unsigned int yres; /* "matrox:yres:xxxxx" */ | 1271 | static unsigned int yres; /* "matroxfb:yres:xxxxx" */ |
1272 | static unsigned int upper = ~0; /* "matrox:upper:xxxxx" */ | 1272 | static unsigned int upper = ~0; /* "matroxfb:upper:xxxxx" */ |
1273 | static unsigned int lower = ~0; /* "matrox:lower:xxxxx" */ | 1273 | static unsigned int lower = ~0; /* "matroxfb:lower:xxxxx" */ |
1274 | static unsigned int vslen; /* "matrox:vslen:xxxxx" */ | 1274 | static unsigned int vslen; /* "matroxfb:vslen:xxxxx" */ |
1275 | static unsigned int left = ~0; /* "matrox:left:xxxxx" */ | 1275 | static unsigned int left = ~0; /* "matroxfb:left:xxxxx" */ |
1276 | static unsigned int right = ~0; /* "matrox:right:xxxxx" */ | 1276 | static unsigned int right = ~0; /* "matroxfb:right:xxxxx" */ |
1277 | static unsigned int hslen; /* "matrox:hslen:xxxxx" */ | 1277 | static unsigned int hslen; /* "matroxfb:hslen:xxxxx" */ |
1278 | static unsigned int pixclock; /* "matrox:pixclock:xxxxx" */ | 1278 | static unsigned int pixclock; /* "matroxfb:pixclock:xxxxx" */ |
1279 | static int sync = -1; /* "matrox:sync:xxxxx" */ | 1279 | static int sync = -1; /* "matroxfb:sync:xxxxx" */ |
1280 | static unsigned int fv; /* "matrox:fv:xxxxx" */ | 1280 | static unsigned int fv; /* "matroxfb:fv:xxxxx" */ |
1281 | static unsigned int fh; /* "matrox:fh:xxxxxk" */ | 1281 | static unsigned int fh; /* "matroxfb:fh:xxxxxk" */ |
1282 | static unsigned int maxclk; /* "matrox:maxclk:xxxxM" */ | 1282 | static unsigned int maxclk; /* "matroxfb:maxclk:xxxxM" */ |
1283 | static int dfp; /* "matrox:dfp */ | 1283 | static int dfp; /* "matroxfb:dfp */ |
1284 | static int dfp_type = -1; /* "matrox:dfp:xxx */ | 1284 | static int dfp_type = -1; /* "matroxfb:dfp:xxx */ |
1285 | static int memtype = -1; /* "matrox:memtype:xxx" */ | 1285 | static int memtype = -1; /* "matroxfb:memtype:xxx" */ |
1286 | static char outputs[8]; /* "matrox:outputs:xxx" */ | 1286 | static char outputs[8]; /* "matroxfb:outputs:xxx" */ |
1287 | 1287 | ||
1288 | #ifndef MODULE | 1288 | #ifndef MODULE |
1289 | static char videomode[64]; /* "matrox:mode:xxxxx" or "matrox:xxxxx" */ | 1289 | static char videomode[64]; /* "matroxfb:mode:xxxxx" or "matroxfb:xxxxx" */ |
1290 | #endif | 1290 | #endif |
1291 | 1291 | ||
1292 | static int matroxfb_getmemory(struct matrox_fb_info *minfo, | 1292 | static int matroxfb_getmemory(struct matrox_fb_info *minfo, |
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index d2bb365f09b3..48c3ea8652b6 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
@@ -32,300 +32,320 @@ | |||
32 | const char *fb_mode_option; | 32 | const char *fb_mode_option; |
33 | EXPORT_SYMBOL_GPL(fb_mode_option); | 33 | EXPORT_SYMBOL_GPL(fb_mode_option); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Standard video mode definitions (taken from XFree86) | 36 | * Standard video mode definitions (taken from XFree86) |
37 | */ | 37 | */ |
38 | 38 | ||
39 | static const struct fb_videomode modedb[] = { | 39 | static const struct fb_videomode modedb[] = { |
40 | { | 40 | |
41 | /* 640x400 @ 70 Hz, 31.5 kHz hsync */ | 41 | /* 640x400 @ 70 Hz, 31.5 kHz hsync */ |
42 | NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, | 42 | { NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, 0, |
43 | 0, FB_VMODE_NONINTERLACED | 43 | FB_VMODE_NONINTERLACED }, |
44 | }, { | 44 | |
45 | /* 640x480 @ 60 Hz, 31.5 kHz hsync */ | 45 | /* 640x480 @ 60 Hz, 31.5 kHz hsync */ |
46 | NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, | 46 | { NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, |
47 | 0, FB_VMODE_NONINTERLACED | 47 | FB_VMODE_NONINTERLACED }, |
48 | }, { | 48 | |
49 | /* 800x600 @ 56 Hz, 35.15 kHz hsync */ | 49 | /* 800x600 @ 56 Hz, 35.15 kHz hsync */ |
50 | NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, | 50 | { NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, 0, |
51 | 0, FB_VMODE_NONINTERLACED | 51 | FB_VMODE_NONINTERLACED }, |
52 | }, { | 52 | |
53 | /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ | 53 | /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ |
54 | NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, | 54 | { NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, 0, |
55 | 0, FB_VMODE_INTERLACED | 55 | FB_VMODE_INTERLACED }, |
56 | }, { | 56 | |
57 | /* 640x400 @ 85 Hz, 37.86 kHz hsync */ | 57 | /* 640x400 @ 85 Hz, 37.86 kHz hsync */ |
58 | NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, | 58 | { NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, |
59 | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 59 | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED }, |
60 | }, { | 60 | |
61 | /* 640x480 @ 72 Hz, 36.5 kHz hsync */ | 61 | /* 640x480 @ 72 Hz, 36.5 kHz hsync */ |
62 | NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, | 62 | { NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, 0, |
63 | 0, FB_VMODE_NONINTERLACED | 63 | FB_VMODE_NONINTERLACED }, |
64 | }, { | 64 | |
65 | /* 640x480 @ 75 Hz, 37.50 kHz hsync */ | 65 | /* 640x480 @ 75 Hz, 37.50 kHz hsync */ |
66 | NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, | 66 | { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, |
67 | 0, FB_VMODE_NONINTERLACED | 67 | FB_VMODE_NONINTERLACED }, |
68 | }, { | 68 | |
69 | /* 800x600 @ 60 Hz, 37.8 kHz hsync */ | 69 | /* 800x600 @ 60 Hz, 37.8 kHz hsync */ |
70 | NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, | 70 | { NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, |
71 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 71 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
72 | }, { | 72 | FB_VMODE_NONINTERLACED }, |
73 | |||
73 | /* 640x480 @ 85 Hz, 43.27 kHz hsync */ | 74 | /* 640x480 @ 85 Hz, 43.27 kHz hsync */ |
74 | NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, | 75 | { NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, 0, |
75 | 0, FB_VMODE_NONINTERLACED | 76 | FB_VMODE_NONINTERLACED }, |
76 | }, { | 77 | |
77 | /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ | 78 | /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ |
78 | NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, | 79 | { NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, 0, |
79 | 0, FB_VMODE_INTERLACED | 80 | FB_VMODE_INTERLACED }, |
80 | }, { | ||
81 | /* 800x600 @ 72 Hz, 48.0 kHz hsync */ | 81 | /* 800x600 @ 72 Hz, 48.0 kHz hsync */ |
82 | NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, | 82 | { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, |
83 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 83 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
84 | }, { | 84 | FB_VMODE_NONINTERLACED }, |
85 | |||
85 | /* 1024x768 @ 60 Hz, 48.4 kHz hsync */ | 86 | /* 1024x768 @ 60 Hz, 48.4 kHz hsync */ |
86 | NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, | 87 | { NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, 0, |
87 | 0, FB_VMODE_NONINTERLACED | 88 | FB_VMODE_NONINTERLACED }, |
88 | }, { | 89 | |
89 | /* 640x480 @ 100 Hz, 53.01 kHz hsync */ | 90 | /* 640x480 @ 100 Hz, 53.01 kHz hsync */ |
90 | NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, | 91 | { NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, 0, |
91 | 0, FB_VMODE_NONINTERLACED | 92 | FB_VMODE_NONINTERLACED }, |
92 | }, { | 93 | |
93 | /* 1152x864 @ 60 Hz, 53.5 kHz hsync */ | 94 | /* 1152x864 @ 60 Hz, 53.5 kHz hsync */ |
94 | NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, | 95 | { NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, 0, |
95 | 0, FB_VMODE_NONINTERLACED | 96 | FB_VMODE_NONINTERLACED }, |
96 | }, { | 97 | |
97 | /* 800x600 @ 85 Hz, 55.84 kHz hsync */ | 98 | /* 800x600 @ 85 Hz, 55.84 kHz hsync */ |
98 | NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, | 99 | { NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, 0, |
99 | 0, FB_VMODE_NONINTERLACED | 100 | FB_VMODE_NONINTERLACED }, |
100 | }, { | 101 | |
101 | /* 1024x768 @ 70 Hz, 56.5 kHz hsync */ | 102 | /* 1024x768 @ 70 Hz, 56.5 kHz hsync */ |
102 | NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, | 103 | { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 0, |
103 | 0, FB_VMODE_NONINTERLACED | 104 | FB_VMODE_NONINTERLACED }, |
104 | }, { | 105 | |
105 | /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ | 106 | /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ |
106 | NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, | 107 | { NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0, |
107 | 0, FB_VMODE_INTERLACED | 108 | FB_VMODE_INTERLACED }, |
108 | }, { | 109 | |
109 | /* 800x600 @ 100 Hz, 64.02 kHz hsync */ | 110 | /* 800x600 @ 100 Hz, 64.02 kHz hsync */ |
110 | NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, | 111 | { NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, 0, |
111 | 0, FB_VMODE_NONINTERLACED | 112 | FB_VMODE_NONINTERLACED }, |
112 | }, { | 113 | |
113 | /* 1024x768 @ 76 Hz, 62.5 kHz hsync */ | 114 | /* 1024x768 @ 76 Hz, 62.5 kHz hsync */ |
114 | NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, | 115 | { NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, 0, |
115 | 0, FB_VMODE_NONINTERLACED | 116 | FB_VMODE_NONINTERLACED }, |
116 | }, { | 117 | |
117 | /* 1152x864 @ 70 Hz, 62.4 kHz hsync */ | 118 | /* 1152x864 @ 70 Hz, 62.4 kHz hsync */ |
118 | NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, | 119 | { NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, 0, |
119 | 0, FB_VMODE_NONINTERLACED | 120 | FB_VMODE_NONINTERLACED }, |
120 | }, { | 121 | |
121 | /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ | 122 | /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ |
122 | NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, | 123 | { NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, |
123 | 0, FB_VMODE_NONINTERLACED | 124 | FB_VMODE_NONINTERLACED }, |
124 | }, { | 125 | |
125 | /* 1400x1050 @ 60Hz, 63.9 kHz hsync */ | 126 | /* 1400x1050 @ 60Hz, 63.9 kHz hsync */ |
126 | NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, | 127 | { NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, 0, |
127 | 0, FB_VMODE_NONINTERLACED | 128 | FB_VMODE_NONINTERLACED }, |
128 | }, { | 129 | |
129 | /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/ | 130 | /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/ |
130 | NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13, | 131 | { NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13, |
131 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 132 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
132 | }, { | 133 | FB_VMODE_NONINTERLACED }, |
134 | |||
133 | /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/ | 135 | /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/ |
134 | NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3, | 136 | { NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3, |
135 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 137 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
136 | }, { | 138 | FB_VMODE_NONINTERLACED }, |
139 | |||
137 | /* 1024x768 @ 85 Hz, 70.24 kHz hsync */ | 140 | /* 1024x768 @ 85 Hz, 70.24 kHz hsync */ |
138 | NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, | 141 | { NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, 0, |
139 | 0, FB_VMODE_NONINTERLACED | 142 | FB_VMODE_NONINTERLACED }, |
140 | }, { | 143 | |
141 | /* 1152x864 @ 78 Hz, 70.8 kHz hsync */ | 144 | /* 1152x864 @ 78 Hz, 70.8 kHz hsync */ |
142 | NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, | 145 | { NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, 0, |
143 | 0, FB_VMODE_NONINTERLACED | 146 | FB_VMODE_NONINTERLACED }, |
144 | }, { | 147 | |
145 | /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ | 148 | /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ |
146 | NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, | 149 | { NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, 0, |
147 | 0, FB_VMODE_NONINTERLACED | 150 | FB_VMODE_NONINTERLACED }, |
148 | }, { | 151 | |
149 | /* 1600x1200 @ 60Hz, 75.00 kHz hsync */ | 152 | /* 1600x1200 @ 60Hz, 75.00 kHz hsync */ |
150 | NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, | 153 | { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, |
151 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 154 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
152 | }, { | 155 | FB_VMODE_NONINTERLACED }, |
156 | |||
153 | /* 1152x864 @ 84 Hz, 76.0 kHz hsync */ | 157 | /* 1152x864 @ 84 Hz, 76.0 kHz hsync */ |
154 | NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, | 158 | { NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, 0, |
155 | 0, FB_VMODE_NONINTERLACED | 159 | FB_VMODE_NONINTERLACED }, |
156 | }, { | 160 | |
157 | /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ | 161 | /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ |
158 | NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, | 162 | { NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, 0, |
159 | 0, FB_VMODE_NONINTERLACED | 163 | FB_VMODE_NONINTERLACED }, |
160 | }, { | 164 | |
161 | /* 1024x768 @ 100Hz, 80.21 kHz hsync */ | 165 | /* 1024x768 @ 100Hz, 80.21 kHz hsync */ |
162 | NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, | 166 | { NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, 0, |
163 | 0, FB_VMODE_NONINTERLACED | 167 | FB_VMODE_NONINTERLACED }, |
164 | }, { | 168 | |
165 | /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ | 169 | /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ |
166 | NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, | 170 | { NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, 0, |
167 | 0, FB_VMODE_NONINTERLACED | 171 | FB_VMODE_NONINTERLACED }, |
168 | }, { | 172 | |
169 | /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ | 173 | /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ |
170 | NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, | 174 | { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, 0, |
171 | 0, FB_VMODE_NONINTERLACED | 175 | FB_VMODE_NONINTERLACED }, |
172 | }, { | 176 | |
173 | /* 1152x864 @ 100 Hz, 89.62 kHz hsync */ | 177 | /* 1152x864 @ 100 Hz, 89.62 kHz hsync */ |
174 | NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, | 178 | { NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, 0, |
175 | 0, FB_VMODE_NONINTERLACED | 179 | FB_VMODE_NONINTERLACED }, |
176 | }, { | 180 | |
177 | /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ | 181 | /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ |
178 | NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, | 182 | { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, |
179 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 183 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
180 | }, { | 184 | FB_VMODE_NONINTERLACED }, |
185 | |||
181 | /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ | 186 | /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ |
182 | NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, | 187 | { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, |
183 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 188 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
184 | }, { | 189 | FB_VMODE_NONINTERLACED }, |
190 | |||
185 | /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ | 191 | /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ |
186 | NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, | 192 | { NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, |
187 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 193 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
188 | }, { | 194 | FB_VMODE_NONINTERLACED }, |
195 | |||
189 | /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ | 196 | /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ |
190 | NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, | 197 | { NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, |
191 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 198 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
192 | }, { | 199 | FB_VMODE_NONINTERLACED }, |
200 | |||
193 | /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ | 201 | /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ |
194 | NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, | 202 | { NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, 0, |
195 | 0, FB_VMODE_NONINTERLACED | 203 | FB_VMODE_NONINTERLACED }, |
196 | }, { | 204 | |
197 | /* 1800x1440 @ 64Hz, 96.15 kHz hsync */ | 205 | /* 1800x1440 @ 64Hz, 96.15 kHz hsync */ |
198 | NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, | 206 | { NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, |
199 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 207 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
200 | }, { | 208 | FB_VMODE_NONINTERLACED }, |
209 | |||
201 | /* 1800x1440 @ 70Hz, 104.52 kHz hsync */ | 210 | /* 1800x1440 @ 70Hz, 104.52 kHz hsync */ |
202 | NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, | 211 | { NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, |
203 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 212 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
204 | }, { | 213 | FB_VMODE_NONINTERLACED }, |
214 | |||
205 | /* 512x384 @ 78 Hz, 31.50 kHz hsync */ | 215 | /* 512x384 @ 78 Hz, 31.50 kHz hsync */ |
206 | NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, | 216 | { NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, 0, |
207 | 0, FB_VMODE_NONINTERLACED | 217 | FB_VMODE_NONINTERLACED }, |
208 | }, { | 218 | |
209 | /* 512x384 @ 85 Hz, 34.38 kHz hsync */ | 219 | /* 512x384 @ 85 Hz, 34.38 kHz hsync */ |
210 | NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, | 220 | { NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, 0, |
211 | 0, FB_VMODE_NONINTERLACED | 221 | FB_VMODE_NONINTERLACED }, |
212 | }, { | 222 | |
213 | /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ | 223 | /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ |
214 | NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, | 224 | { NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, 0, |
215 | 0, FB_VMODE_DOUBLE | 225 | FB_VMODE_DOUBLE }, |
216 | }, { | 226 | |
217 | /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ | 227 | /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ |
218 | NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, | 228 | { NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, 0, |
219 | 0, FB_VMODE_DOUBLE | 229 | FB_VMODE_DOUBLE }, |
220 | }, { | 230 | |
221 | /* 320x240 @ 72 Hz, 36.5 kHz hsync */ | 231 | /* 320x240 @ 72 Hz, 36.5 kHz hsync */ |
222 | NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, | 232 | { NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, 0, |
223 | 0, FB_VMODE_DOUBLE | 233 | FB_VMODE_DOUBLE }, |
224 | }, { | 234 | |
225 | /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ | 235 | /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ |
226 | NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, | 236 | { NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, 0, |
227 | 0, FB_VMODE_DOUBLE | 237 | FB_VMODE_DOUBLE }, |
228 | }, { | 238 | |
229 | /* 400x300 @ 60 Hz, 37.8 kHz hsync */ | 239 | /* 400x300 @ 60 Hz, 37.8 kHz hsync */ |
230 | NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, | 240 | { NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, 0, |
231 | 0, FB_VMODE_DOUBLE | 241 | FB_VMODE_DOUBLE }, |
232 | }, { | 242 | |
233 | /* 400x300 @ 72 Hz, 48.0 kHz hsync */ | 243 | /* 400x300 @ 72 Hz, 48.0 kHz hsync */ |
234 | NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, | 244 | { NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, 0, |
235 | 0, FB_VMODE_DOUBLE | 245 | FB_VMODE_DOUBLE }, |
236 | }, { | 246 | |
237 | /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ | 247 | /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ |
238 | NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, | 248 | { NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, 0, |
239 | 0, FB_VMODE_DOUBLE | 249 | FB_VMODE_DOUBLE }, |
240 | }, { | 250 | |
241 | /* 480x300 @ 60 Hz, 37.8 kHz hsync */ | 251 | /* 480x300 @ 60 Hz, 37.8 kHz hsync */ |
242 | NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, | 252 | { NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, 0, |
243 | 0, FB_VMODE_DOUBLE | 253 | FB_VMODE_DOUBLE }, |
244 | }, { | 254 | |
245 | /* 480x300 @ 63 Hz, 39.6 kHz hsync */ | 255 | /* 480x300 @ 63 Hz, 39.6 kHz hsync */ |
246 | NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, | 256 | { NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, 0, |
247 | 0, FB_VMODE_DOUBLE | 257 | FB_VMODE_DOUBLE }, |
248 | }, { | 258 | |
249 | /* 480x300 @ 72 Hz, 48.0 kHz hsync */ | 259 | /* 480x300 @ 72 Hz, 48.0 kHz hsync */ |
250 | NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, | 260 | { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0, |
251 | 0, FB_VMODE_DOUBLE | 261 | FB_VMODE_DOUBLE }, |
252 | }, { | 262 | |
253 | /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ | 263 | /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ |
254 | NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, | 264 | { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, |
255 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 265 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
256 | FB_VMODE_NONINTERLACED | 266 | FB_VMODE_NONINTERLACED }, |
257 | }, { | 267 | |
258 | /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ | 268 | /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ |
259 | NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6, | 269 | { NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6, |
260 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 270 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
261 | }, { | 271 | FB_VMODE_NONINTERLACED }, |
272 | |||
262 | /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */ | 273 | /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */ |
263 | NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, | 274 | { NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, 0, |
264 | 0, FB_VMODE_NONINTERLACED | 275 | FB_VMODE_NONINTERLACED }, |
265 | }, { | 276 | |
266 | /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */ | 277 | /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */ |
267 | NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, | 278 | { NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, 0, |
268 | 0, FB_VMODE_NONINTERLACED | 279 | FB_VMODE_NONINTERLACED }, |
269 | }, { | 280 | |
270 | /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */ | 281 | /* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */ |
271 | NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, | 282 | { NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0, |
272 | 0, FB_VMODE_INTERLACED | 283 | FB_VMODE_INTERLACED }, |
273 | }, { | 284 | |
274 | /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */ | 285 | /* 800x520i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */ |
275 | NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, | 286 | { NULL, 50, 800, 520, 58823, 144, 64, 72, 28, 80, 5, 0, |
276 | 0, FB_VMODE_INTERLACED | 287 | FB_VMODE_INTERLACED }, |
277 | }, { | 288 | |
278 | /* 864x480 @ 60 Hz, 35.15 kHz hsync */ | 289 | /* 864x480 @ 60 Hz, 35.15 kHz hsync */ |
279 | NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0, | 290 | { NULL, 60, 864, 480, 27777, 1, 1, 1, 1, 0, 0, |
280 | 0, FB_VMODE_NONINTERLACED | 291 | 0, FB_VMODE_NONINTERLACED }, |
281 | }, | ||
282 | }; | 292 | }; |
283 | 293 | ||
284 | #ifdef CONFIG_FB_MODE_HELPERS | 294 | #ifdef CONFIG_FB_MODE_HELPERS |
285 | const struct fb_videomode cea_modes[64] = { | 295 | const struct fb_videomode cea_modes[64] = { |
286 | /* #1: 640x480p@59.94/60Hz */ | 296 | /* #1: 640x480p@59.94/60Hz */ |
287 | [1] = { | 297 | [1] = { |
288 | NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED, 0, | 298 | NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2, 0, |
299 | FB_VMODE_NONINTERLACED, 0, | ||
289 | }, | 300 | }, |
290 | /* #3: 720x480p@59.94/60Hz */ | 301 | /* #3: 720x480p@59.94/60Hz */ |
291 | [3] = { | 302 | [3] = { |
292 | NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, FB_VMODE_NONINTERLACED, 0, | 303 | NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0, |
304 | FB_VMODE_NONINTERLACED, 0, | ||
293 | }, | 305 | }, |
294 | /* #5: 1920x1080i@59.94/60Hz */ | 306 | /* #5: 1920x1080i@59.94/60Hz */ |
295 | [5] = { | 307 | [5] = { |
296 | NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5, | 308 | NULL, 60, 1920, 1080, 13763, 148, 88, 15, 2, 44, 5, |
297 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0, | 309 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
310 | FB_VMODE_INTERLACED, 0, | ||
298 | }, | 311 | }, |
299 | /* #7: 720(1440)x480iH@59.94/60Hz */ | 312 | /* #7: 720(1440)x480iH@59.94/60Hz */ |
300 | [7] = { | 313 | [7] = { |
301 | NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0, FB_VMODE_INTERLACED, 0, | 314 | NULL, 60, 1440, 480, 18554/*37108*/, 114, 38, 15, 4, 124, 3, 0, |
315 | FB_VMODE_INTERLACED, 0, | ||
302 | }, | 316 | }, |
303 | /* #9: 720(1440)x240pH@59.94/60Hz */ | 317 | /* #9: 720(1440)x240pH@59.94/60Hz */ |
304 | [9] = { | 318 | [9] = { |
305 | NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0, FB_VMODE_NONINTERLACED, 0, | 319 | NULL, 60, 1440, 240, 18554, 114, 38, 16, 4, 124, 3, 0, |
320 | FB_VMODE_NONINTERLACED, 0, | ||
306 | }, | 321 | }, |
307 | /* #18: 720x576pH@50Hz */ | 322 | /* #18: 720x576pH@50Hz */ |
308 | [18] = { | 323 | [18] = { |
309 | NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0, FB_VMODE_NONINTERLACED, 0, | 324 | NULL, 50, 720, 576, 37037, 68, 12, 39, 5, 64, 5, 0, |
325 | FB_VMODE_NONINTERLACED, 0, | ||
310 | }, | 326 | }, |
311 | /* #19: 1280x720p@50Hz */ | 327 | /* #19: 1280x720p@50Hz */ |
312 | [19] = { | 328 | [19] = { |
313 | NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5, | 329 | NULL, 50, 1280, 720, 13468, 220, 440, 20, 5, 40, 5, |
314 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0, | 330 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
331 | FB_VMODE_NONINTERLACED, 0, | ||
315 | }, | 332 | }, |
316 | /* #20: 1920x1080i@50Hz */ | 333 | /* #20: 1920x1080i@50Hz */ |
317 | [20] = { | 334 | [20] = { |
318 | NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5, | 335 | NULL, 50, 1920, 1080, 13480, 148, 528, 15, 5, 528, 5, |
319 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED, 0, | 336 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
337 | FB_VMODE_INTERLACED, 0, | ||
320 | }, | 338 | }, |
321 | /* #32: 1920x1080p@23.98/24Hz */ | 339 | /* #32: 1920x1080p@23.98/24Hz */ |
322 | [32] = { | 340 | [32] = { |
323 | NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5, | 341 | NULL, 24, 1920, 1080, 13468, 148, 638, 36, 4, 44, 5, |
324 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0, | 342 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
343 | FB_VMODE_NONINTERLACED, 0, | ||
325 | }, | 344 | }, |
326 | /* #35: (2880)x480p4x@59.94/60Hz */ | 345 | /* #35: (2880)x480p4x@59.94/60Hz */ |
327 | [35] = { | 346 | [35] = { |
328 | NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0, FB_VMODE_NONINTERLACED, 0, | 347 | NULL, 60, 2880, 480, 9250, 240, 64, 30, 9, 248, 6, 0, |
348 | FB_VMODE_NONINTERLACED, 0, | ||
329 | }, | 349 | }, |
330 | }; | 350 | }; |
331 | 351 | ||
@@ -340,10 +360,10 @@ const struct fb_videomode vesa_modes[] = { | |||
340 | { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3, | 360 | { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3, |
341 | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 361 | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
342 | /* 3 640x480-60 VESA */ | 362 | /* 3 640x480-60 VESA */ |
343 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, | 363 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, |
344 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 364 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
345 | /* 4 640x480-72 VESA */ | 365 | /* 4 640x480-72 VESA */ |
346 | { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2, | 366 | { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2, |
347 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 367 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
348 | /* 5 640x480-75 VESA */ | 368 | /* 5 640x480-75 VESA */ |
349 | { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, | 369 | { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, |
@@ -426,7 +446,7 @@ const struct fb_videomode vesa_modes[] = { | |||
426 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 446 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
427 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 447 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
428 | /* 26 1600x1200-75 VESA */ | 448 | /* 26 1600x1200-75 VESA */ |
429 | { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, | 449 | { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, |
430 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 450 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
431 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 451 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
432 | /* 27 1600x1200-85 VESA */ | 452 | /* 27 1600x1200-85 VESA */ |
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index 81687ed26ba9..62498bd662fc 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/err.h> | ||
18 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
19 | #include <linux/string.h> | 20 | #include <linux/string.h> |
20 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
@@ -597,9 +598,9 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev) | |||
597 | } | 598 | } |
598 | 599 | ||
599 | fbi->clk = clk_get(&pdev->dev, NULL); | 600 | fbi->clk = clk_get(&pdev->dev, NULL); |
600 | if (!fbi->clk || IS_ERR(fbi->clk)) { | 601 | if (IS_ERR(fbi->clk)) { |
601 | printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); | 602 | printk(KERN_ERR "nuc900-lcd:failed to get lcd clock source\n"); |
602 | ret = -ENOENT; | 603 | ret = PTR_ERR(fbi->clk); |
603 | goto release_irq; | 604 | goto release_irq; |
604 | } | 605 | } |
605 | 606 | ||
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c index 2fb552a6f32c..6aac6d1b937b 100644 --- a/drivers/video/nvidia/nv_backlight.c +++ b/drivers/video/nvidia/nv_backlight.c | |||
@@ -87,7 +87,7 @@ static int nvidia_bl_get_brightness(struct backlight_device *bd) | |||
87 | return bd->props.brightness; | 87 | return bd->props.brightness; |
88 | } | 88 | } |
89 | 89 | ||
90 | static struct backlight_ops nvidia_bl_ops = { | 90 | static const struct backlight_ops nvidia_bl_ops = { |
91 | .get_brightness = nvidia_bl_get_brightness, | 91 | .get_brightness = nvidia_bl_get_brightness, |
92 | .update_status = nvidia_bl_update_status, | 92 | .update_status = nvidia_bl_update_status, |
93 | }; | 93 | }; |
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 12327bbfdbbb..940cab394c2e 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig | |||
@@ -1,11 +1,13 @@ | |||
1 | menu "OMAP2/3 Display Device Drivers" | 1 | menu "OMAP2/3 Display Device Drivers" |
2 | depends on OMAP2_DSS | 2 | depends on OMAP2_DSS |
3 | 3 | ||
4 | config PANEL_GENERIC | 4 | config PANEL_GENERIC_DPI |
5 | tristate "Generic Panel" | 5 | tristate "Generic DPI Panel" |
6 | help | 6 | help |
7 | Generic panel driver. | 7 | Generic DPI panel driver. |
8 | Used for DVI output for Beagle and OMAP3 SDP. | 8 | Supports DVI output for Beagle and OMAP3 SDP. |
9 | Supports LCD Panel used in TI SDP3430 and EVM boards, | ||
10 | OMAP3517 EVM boards and CM-T35. | ||
9 | 11 | ||
10 | config PANEL_SHARP_LS037V7DW01 | 12 | config PANEL_SHARP_LS037V7DW01 |
11 | tristate "Sharp LS037V7DW01 LCD Panel" | 13 | tristate "Sharp LS037V7DW01 LCD Panel" |
@@ -14,11 +16,12 @@ config PANEL_SHARP_LS037V7DW01 | |||
14 | help | 16 | help |
15 | LCD Panel used in TI's SDP3430 and EVM boards | 17 | LCD Panel used in TI's SDP3430 and EVM boards |
16 | 18 | ||
17 | config PANEL_SHARP_LQ043T1DG01 | 19 | config PANEL_NEC_NL8048HL11_01B |
18 | tristate "Sharp LQ043T1DG01 LCD Panel" | 20 | tristate "NEC NL8048HL11-01B Panel" |
19 | depends on OMAP2_DSS | 21 | depends on OMAP2_DSS |
20 | help | 22 | help |
21 | LCD Panel used in TI's OMAP3517 EVM boards | 23 | This NEC NL8048HL11-01B panel is TFT LCD |
24 | used in the Zoom2/3/3630 sdp boards. | ||
22 | 25 | ||
23 | config PANEL_TAAL | 26 | config PANEL_TAAL |
24 | tristate "Taal DSI Panel" | 27 | tristate "Taal DSI Panel" |
@@ -26,12 +29,6 @@ config PANEL_TAAL | |||
26 | help | 29 | help |
27 | Taal DSI command mode panel from TPO. | 30 | Taal DSI command mode panel from TPO. |
28 | 31 | ||
29 | config PANEL_TOPPOLY_TDO35S | ||
30 | tristate "Toppoly TDO35S LCD Panel support" | ||
31 | depends on OMAP2_DSS | ||
32 | help | ||
33 | LCD Panel used in CM-T35 | ||
34 | |||
35 | config PANEL_TPO_TD043MTEA1 | 32 | config PANEL_TPO_TD043MTEA1 |
36 | tristate "TPO TD043MTEA1 LCD Panel" | 33 | tristate "TPO TD043MTEA1 LCD Panel" |
37 | depends on OMAP2_DSS && SPI | 34 | depends on OMAP2_DSS && SPI |
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index aa386095d7c4..861f0255ec6b 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile | |||
@@ -1,8 +1,7 @@ | |||
1 | obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o | 1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o |
2 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o | 2 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o |
3 | obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o | 3 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o |
4 | 4 | ||
5 | obj-$(CONFIG_PANEL_TAAL) += panel-taal.o | 5 | obj-$(CONFIG_PANEL_TAAL) += panel-taal.o |
6 | obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o | ||
7 | obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o | 6 | obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o |
8 | obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o | 7 | obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o |
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c new file mode 100644 index 000000000000..07eb30ee59c8 --- /dev/null +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * Generic DPI Panels support | ||
3 | * | ||
4 | * Copyright (C) 2010 Canonical Ltd. | ||
5 | * Author: Bryan Wu <bryan.wu@canonical.com> | ||
6 | * | ||
7 | * LCD panel driver for Sharp LQ043T1DG01 | ||
8 | * | ||
9 | * Copyright (C) 2009 Texas Instruments Inc | ||
10 | * Author: Vaibhav Hiremath <hvaibhav@ti.com> | ||
11 | * | ||
12 | * LCD panel driver for Toppoly TDO35S | ||
13 | * | ||
14 | * Copyright (C) 2009 CompuLab, Ltd. | ||
15 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
16 | * | ||
17 | * Copyright (C) 2008 Nokia Corporation | ||
18 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or modify it | ||
21 | * under the terms of the GNU General Public License version 2 as published by | ||
22 | * the Free Software Foundation. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
25 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
26 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
27 | * more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License along with | ||
30 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/slab.h> | ||
36 | |||
37 | #include <plat/panel-generic-dpi.h> | ||
38 | |||
39 | struct panel_config { | ||
40 | struct omap_video_timings timings; | ||
41 | |||
42 | int acbi; /* ac-bias pin transitions per interrupt */ | ||
43 | /* Unit: line clocks */ | ||
44 | int acb; /* ac-bias pin frequency */ | ||
45 | |||
46 | enum omap_panel_config config; | ||
47 | |||
48 | int power_on_delay; | ||
49 | int power_off_delay; | ||
50 | |||
51 | /* | ||
52 | * Used to match device to panel configuration | ||
53 | * when use generic panel driver | ||
54 | */ | ||
55 | const char *name; | ||
56 | }; | ||
57 | |||
58 | /* Panel configurations */ | ||
59 | static struct panel_config generic_dpi_panels[] = { | ||
60 | /* Generic Panel */ | ||
61 | { | ||
62 | { | ||
63 | .x_res = 640, | ||
64 | .y_res = 480, | ||
65 | |||
66 | .pixel_clock = 23500, | ||
67 | |||
68 | .hfp = 48, | ||
69 | .hsw = 32, | ||
70 | .hbp = 80, | ||
71 | |||
72 | .vfp = 3, | ||
73 | .vsw = 4, | ||
74 | .vbp = 7, | ||
75 | }, | ||
76 | .acbi = 0x0, | ||
77 | .acb = 0x0, | ||
78 | .config = OMAP_DSS_LCD_TFT, | ||
79 | .power_on_delay = 0, | ||
80 | .power_off_delay = 0, | ||
81 | .name = "generic", | ||
82 | }, | ||
83 | |||
84 | /* Sharp LQ043T1DG01 */ | ||
85 | { | ||
86 | { | ||
87 | .x_res = 480, | ||
88 | .y_res = 272, | ||
89 | |||
90 | .pixel_clock = 9000, | ||
91 | |||
92 | .hsw = 42, | ||
93 | .hfp = 3, | ||
94 | .hbp = 2, | ||
95 | |||
96 | .vsw = 11, | ||
97 | .vfp = 3, | ||
98 | .vbp = 2, | ||
99 | }, | ||
100 | .acbi = 0x0, | ||
101 | .acb = 0x0, | ||
102 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
103 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO, | ||
104 | .power_on_delay = 50, | ||
105 | .power_off_delay = 100, | ||
106 | .name = "sharp_lq", | ||
107 | }, | ||
108 | |||
109 | /* Sharp LS037V7DW01 */ | ||
110 | { | ||
111 | { | ||
112 | .x_res = 480, | ||
113 | .y_res = 640, | ||
114 | |||
115 | .pixel_clock = 19200, | ||
116 | |||
117 | .hsw = 2, | ||
118 | .hfp = 1, | ||
119 | .hbp = 28, | ||
120 | |||
121 | .vsw = 1, | ||
122 | .vfp = 1, | ||
123 | .vbp = 1, | ||
124 | }, | ||
125 | .acbi = 0x0, | ||
126 | .acb = 0x28, | ||
127 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
128 | OMAP_DSS_LCD_IHS, | ||
129 | .power_on_delay = 50, | ||
130 | .power_off_delay = 100, | ||
131 | .name = "sharp_ls", | ||
132 | }, | ||
133 | |||
134 | /* Toppoly TDO35S */ | ||
135 | { | ||
136 | { | ||
137 | .x_res = 480, | ||
138 | .y_res = 640, | ||
139 | |||
140 | .pixel_clock = 26000, | ||
141 | |||
142 | .hfp = 104, | ||
143 | .hsw = 8, | ||
144 | .hbp = 8, | ||
145 | |||
146 | .vfp = 4, | ||
147 | .vsw = 2, | ||
148 | .vbp = 2, | ||
149 | }, | ||
150 | .acbi = 0x0, | ||
151 | .acb = 0x0, | ||
152 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
153 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC | | ||
154 | OMAP_DSS_LCD_ONOFF, | ||
155 | .power_on_delay = 0, | ||
156 | .power_off_delay = 0, | ||
157 | .name = "toppoly_tdo35s", | ||
158 | }, | ||
159 | }; | ||
160 | |||
161 | struct panel_drv_data { | ||
162 | |||
163 | struct omap_dss_device *dssdev; | ||
164 | |||
165 | struct panel_config *panel_config; | ||
166 | }; | ||
167 | |||
168 | static inline struct panel_generic_dpi_data | ||
169 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
170 | { | ||
171 | return (struct panel_generic_dpi_data *) dssdev->data; | ||
172 | } | ||
173 | |||
174 | static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) | ||
175 | { | ||
176 | int r; | ||
177 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | ||
178 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | ||
179 | struct panel_config *panel_config = drv_data->panel_config; | ||
180 | |||
181 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
182 | return 0; | ||
183 | |||
184 | r = omapdss_dpi_display_enable(dssdev); | ||
185 | if (r) | ||
186 | goto err0; | ||
187 | |||
188 | /* wait couple of vsyncs until enabling the LCD */ | ||
189 | if (panel_config->power_on_delay) | ||
190 | msleep(panel_config->power_on_delay); | ||
191 | |||
192 | if (panel_data->platform_enable) { | ||
193 | r = panel_data->platform_enable(dssdev); | ||
194 | if (r) | ||
195 | goto err1; | ||
196 | } | ||
197 | |||
198 | return 0; | ||
199 | err1: | ||
200 | omapdss_dpi_display_disable(dssdev); | ||
201 | err0: | ||
202 | return r; | ||
203 | } | ||
204 | |||
205 | static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev) | ||
206 | { | ||
207 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | ||
208 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | ||
209 | struct panel_config *panel_config = drv_data->panel_config; | ||
210 | |||
211 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
212 | return; | ||
213 | |||
214 | if (panel_data->platform_disable) | ||
215 | panel_data->platform_disable(dssdev); | ||
216 | |||
217 | /* wait couple of vsyncs after disabling the LCD */ | ||
218 | if (panel_config->power_off_delay) | ||
219 | msleep(panel_config->power_off_delay); | ||
220 | |||
221 | omapdss_dpi_display_disable(dssdev); | ||
222 | } | ||
223 | |||
224 | static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) | ||
225 | { | ||
226 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | ||
227 | struct panel_config *panel_config = NULL; | ||
228 | struct panel_drv_data *drv_data = NULL; | ||
229 | int i; | ||
230 | |||
231 | dev_dbg(&dssdev->dev, "probe\n"); | ||
232 | |||
233 | if (!panel_data || !panel_data->name) | ||
234 | return -EINVAL; | ||
235 | |||
236 | for (i = 0; i < ARRAY_SIZE(generic_dpi_panels); i++) { | ||
237 | if (strcmp(panel_data->name, generic_dpi_panels[i].name) == 0) { | ||
238 | panel_config = &generic_dpi_panels[i]; | ||
239 | break; | ||
240 | } | ||
241 | } | ||
242 | |||
243 | if (!panel_config) | ||
244 | return -EINVAL; | ||
245 | |||
246 | dssdev->panel.config = panel_config->config; | ||
247 | dssdev->panel.timings = panel_config->timings; | ||
248 | dssdev->panel.acb = panel_config->acb; | ||
249 | dssdev->panel.acbi = panel_config->acbi; | ||
250 | |||
251 | drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); | ||
252 | if (!drv_data) | ||
253 | return -ENOMEM; | ||
254 | |||
255 | drv_data->dssdev = dssdev; | ||
256 | drv_data->panel_config = panel_config; | ||
257 | |||
258 | dev_set_drvdata(&dssdev->dev, drv_data); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void generic_dpi_panel_remove(struct omap_dss_device *dssdev) | ||
264 | { | ||
265 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | ||
266 | |||
267 | dev_dbg(&dssdev->dev, "remove\n"); | ||
268 | |||
269 | kfree(drv_data); | ||
270 | |||
271 | dev_set_drvdata(&dssdev->dev, NULL); | ||
272 | } | ||
273 | |||
274 | static int generic_dpi_panel_enable(struct omap_dss_device *dssdev) | ||
275 | { | ||
276 | int r = 0; | ||
277 | |||
278 | r = generic_dpi_panel_power_on(dssdev); | ||
279 | if (r) | ||
280 | return r; | ||
281 | |||
282 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static void generic_dpi_panel_disable(struct omap_dss_device *dssdev) | ||
288 | { | ||
289 | generic_dpi_panel_power_off(dssdev); | ||
290 | |||
291 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
292 | } | ||
293 | |||
294 | static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev) | ||
295 | { | ||
296 | generic_dpi_panel_power_off(dssdev); | ||
297 | |||
298 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int generic_dpi_panel_resume(struct omap_dss_device *dssdev) | ||
304 | { | ||
305 | int r = 0; | ||
306 | |||
307 | r = generic_dpi_panel_power_on(dssdev); | ||
308 | if (r) | ||
309 | return r; | ||
310 | |||
311 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, | ||
317 | struct omap_video_timings *timings) | ||
318 | { | ||
319 | dpi_set_timings(dssdev, timings); | ||
320 | } | ||
321 | |||
322 | static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev, | ||
323 | struct omap_video_timings *timings) | ||
324 | { | ||
325 | *timings = dssdev->panel.timings; | ||
326 | } | ||
327 | |||
328 | static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, | ||
329 | struct omap_video_timings *timings) | ||
330 | { | ||
331 | return dpi_check_timings(dssdev, timings); | ||
332 | } | ||
333 | |||
334 | static struct omap_dss_driver dpi_driver = { | ||
335 | .probe = generic_dpi_panel_probe, | ||
336 | .remove = generic_dpi_panel_remove, | ||
337 | |||
338 | .enable = generic_dpi_panel_enable, | ||
339 | .disable = generic_dpi_panel_disable, | ||
340 | .suspend = generic_dpi_panel_suspend, | ||
341 | .resume = generic_dpi_panel_resume, | ||
342 | |||
343 | .set_timings = generic_dpi_panel_set_timings, | ||
344 | .get_timings = generic_dpi_panel_get_timings, | ||
345 | .check_timings = generic_dpi_panel_check_timings, | ||
346 | |||
347 | .driver = { | ||
348 | .name = "generic_dpi_panel", | ||
349 | .owner = THIS_MODULE, | ||
350 | }, | ||
351 | }; | ||
352 | |||
353 | static int __init generic_dpi_panel_drv_init(void) | ||
354 | { | ||
355 | return omap_dss_register_driver(&dpi_driver); | ||
356 | } | ||
357 | |||
358 | static void __exit generic_dpi_panel_drv_exit(void) | ||
359 | { | ||
360 | omap_dss_unregister_driver(&dpi_driver); | ||
361 | } | ||
362 | |||
363 | module_init(generic_dpi_panel_drv_init); | ||
364 | module_exit(generic_dpi_panel_drv_exit); | ||
365 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c deleted file mode 100644 index 395a68de3990..000000000000 --- a/drivers/video/omap2/displays/panel-generic.c +++ /dev/null | |||
@@ -1,174 +0,0 @@ | |||
1 | /* | ||
2 | * Generic panel support | ||
3 | * | ||
4 | * Copyright (C) 2008 Nokia Corporation | ||
5 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/delay.h> | ||
22 | |||
23 | #include <plat/display.h> | ||
24 | |||
25 | static struct omap_video_timings generic_panel_timings = { | ||
26 | /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
27 | .x_res = 640, | ||
28 | .y_res = 480, | ||
29 | .pixel_clock = 23500, | ||
30 | .hfp = 48, | ||
31 | .hsw = 32, | ||
32 | .hbp = 80, | ||
33 | .vfp = 3, | ||
34 | .vsw = 4, | ||
35 | .vbp = 7, | ||
36 | }; | ||
37 | |||
38 | static int generic_panel_power_on(struct omap_dss_device *dssdev) | ||
39 | { | ||
40 | int r; | ||
41 | |||
42 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
43 | return 0; | ||
44 | |||
45 | r = omapdss_dpi_display_enable(dssdev); | ||
46 | if (r) | ||
47 | goto err0; | ||
48 | |||
49 | if (dssdev->platform_enable) { | ||
50 | r = dssdev->platform_enable(dssdev); | ||
51 | if (r) | ||
52 | goto err1; | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | err1: | ||
57 | omapdss_dpi_display_disable(dssdev); | ||
58 | err0: | ||
59 | return r; | ||
60 | } | ||
61 | |||
62 | static void generic_panel_power_off(struct omap_dss_device *dssdev) | ||
63 | { | ||
64 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
65 | return; | ||
66 | |||
67 | if (dssdev->platform_disable) | ||
68 | dssdev->platform_disable(dssdev); | ||
69 | |||
70 | omapdss_dpi_display_disable(dssdev); | ||
71 | } | ||
72 | |||
73 | static int generic_panel_probe(struct omap_dss_device *dssdev) | ||
74 | { | ||
75 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | ||
76 | dssdev->panel.timings = generic_panel_timings; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static void generic_panel_remove(struct omap_dss_device *dssdev) | ||
82 | { | ||
83 | } | ||
84 | |||
85 | static int generic_panel_enable(struct omap_dss_device *dssdev) | ||
86 | { | ||
87 | int r = 0; | ||
88 | |||
89 | r = generic_panel_power_on(dssdev); | ||
90 | if (r) | ||
91 | return r; | ||
92 | |||
93 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static void generic_panel_disable(struct omap_dss_device *dssdev) | ||
99 | { | ||
100 | generic_panel_power_off(dssdev); | ||
101 | |||
102 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
103 | } | ||
104 | |||
105 | static int generic_panel_suspend(struct omap_dss_device *dssdev) | ||
106 | { | ||
107 | generic_panel_power_off(dssdev); | ||
108 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int generic_panel_resume(struct omap_dss_device *dssdev) | ||
113 | { | ||
114 | int r = 0; | ||
115 | |||
116 | r = generic_panel_power_on(dssdev); | ||
117 | if (r) | ||
118 | return r; | ||
119 | |||
120 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static void generic_panel_set_timings(struct omap_dss_device *dssdev, | ||
126 | struct omap_video_timings *timings) | ||
127 | { | ||
128 | dpi_set_timings(dssdev, timings); | ||
129 | } | ||
130 | |||
131 | static void generic_panel_get_timings(struct omap_dss_device *dssdev, | ||
132 | struct omap_video_timings *timings) | ||
133 | { | ||
134 | *timings = dssdev->panel.timings; | ||
135 | } | ||
136 | |||
137 | static int generic_panel_check_timings(struct omap_dss_device *dssdev, | ||
138 | struct omap_video_timings *timings) | ||
139 | { | ||
140 | return dpi_check_timings(dssdev, timings); | ||
141 | } | ||
142 | |||
143 | static struct omap_dss_driver generic_driver = { | ||
144 | .probe = generic_panel_probe, | ||
145 | .remove = generic_panel_remove, | ||
146 | |||
147 | .enable = generic_panel_enable, | ||
148 | .disable = generic_panel_disable, | ||
149 | .suspend = generic_panel_suspend, | ||
150 | .resume = generic_panel_resume, | ||
151 | |||
152 | .set_timings = generic_panel_set_timings, | ||
153 | .get_timings = generic_panel_get_timings, | ||
154 | .check_timings = generic_panel_check_timings, | ||
155 | |||
156 | .driver = { | ||
157 | .name = "generic_panel", | ||
158 | .owner = THIS_MODULE, | ||
159 | }, | ||
160 | }; | ||
161 | |||
162 | static int __init generic_panel_drv_init(void) | ||
163 | { | ||
164 | return omap_dss_register_driver(&generic_driver); | ||
165 | } | ||
166 | |||
167 | static void __exit generic_panel_drv_exit(void) | ||
168 | { | ||
169 | omap_dss_unregister_driver(&generic_driver); | ||
170 | } | ||
171 | |||
172 | module_init(generic_panel_drv_init); | ||
173 | module_exit(generic_panel_drv_exit); | ||
174 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c new file mode 100644 index 000000000000..925e0fadff54 --- /dev/null +++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * Support for NEC-nl8048hl11-01b panel driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments Inc. | ||
5 | * Author: Erik Gilling <konkers@android.com> | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/backlight.h> | ||
23 | #include <linux/fb.h> | ||
24 | |||
25 | #include <plat/display.h> | ||
26 | |||
27 | #define LCD_XRES 800 | ||
28 | #define LCD_YRES 480 | ||
29 | /* | ||
30 | * NEC PIX Clock Ratings | ||
31 | * MIN:21.8MHz TYP:23.8MHz MAX:25.7MHz | ||
32 | */ | ||
33 | #define LCD_PIXEL_CLOCK 23800 | ||
34 | |||
35 | struct nec_8048_data { | ||
36 | struct backlight_device *bl; | ||
37 | }; | ||
38 | |||
39 | static const struct { | ||
40 | unsigned char addr; | ||
41 | unsigned char dat; | ||
42 | } nec_8048_init_seq[] = { | ||
43 | { 3, 0x01 }, { 0, 0x00 }, { 1, 0x01 }, { 4, 0x00 }, { 5, 0x14 }, | ||
44 | { 6, 0x24 }, { 16, 0xD7 }, { 17, 0x00 }, { 18, 0x00 }, { 19, 0x55 }, | ||
45 | { 20, 0x01 }, { 21, 0x70 }, { 22, 0x1E }, { 23, 0x25 }, { 24, 0x25 }, | ||
46 | { 25, 0x02 }, { 26, 0x02 }, { 27, 0xA0 }, { 32, 0x2F }, { 33, 0x0F }, | ||
47 | { 34, 0x0F }, { 35, 0x0F }, { 36, 0x0F }, { 37, 0x0F }, { 38, 0x0F }, | ||
48 | { 39, 0x00 }, { 40, 0x02 }, { 41, 0x02 }, { 42, 0x02 }, { 43, 0x0F }, | ||
49 | { 44, 0x0F }, { 45, 0x0F }, { 46, 0x0F }, { 47, 0x0F }, { 48, 0x0F }, | ||
50 | { 49, 0x0F }, { 50, 0x00 }, { 51, 0x02 }, { 52, 0x02 }, { 53, 0x02 }, | ||
51 | { 80, 0x0C }, { 83, 0x42 }, { 84, 0x42 }, { 85, 0x41 }, { 86, 0x14 }, | ||
52 | { 89, 0x88 }, { 90, 0x01 }, { 91, 0x00 }, { 92, 0x02 }, { 93, 0x0C }, | ||
53 | { 94, 0x1C }, { 95, 0x27 }, { 98, 0x49 }, { 99, 0x27 }, { 102, 0x76 }, | ||
54 | { 103, 0x27 }, { 112, 0x01 }, { 113, 0x0E }, { 114, 0x02 }, | ||
55 | { 115, 0x0C }, { 118, 0x0C }, { 121, 0x30 }, { 130, 0x00 }, | ||
56 | { 131, 0x00 }, { 132, 0xFC }, { 134, 0x00 }, { 136, 0x00 }, | ||
57 | { 138, 0x00 }, { 139, 0x00 }, { 140, 0x00 }, { 141, 0xFC }, | ||
58 | { 143, 0x00 }, { 145, 0x00 }, { 147, 0x00 }, { 148, 0x00 }, | ||
59 | { 149, 0x00 }, { 150, 0xFC }, { 152, 0x00 }, { 154, 0x00 }, | ||
60 | { 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 }, | ||
61 | }; | ||
62 | |||
63 | /* | ||
64 | * NEC NL8048HL11-01B Manual | ||
65 | * defines HFB, HSW, HBP, VFP, VSW, VBP as shown below | ||
66 | */ | ||
67 | |||
68 | static struct omap_video_timings nec_8048_panel_timings = { | ||
69 | /* 800 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
70 | .x_res = LCD_XRES, | ||
71 | .y_res = LCD_YRES, | ||
72 | .pixel_clock = LCD_PIXEL_CLOCK, | ||
73 | .hfp = 6, | ||
74 | .hsw = 1, | ||
75 | .hbp = 4, | ||
76 | .vfp = 3, | ||
77 | .vsw = 1, | ||
78 | .vbp = 4, | ||
79 | }; | ||
80 | |||
81 | static int nec_8048_bl_update_status(struct backlight_device *bl) | ||
82 | { | ||
83 | struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev); | ||
84 | int level; | ||
85 | |||
86 | if (!dssdev->set_backlight) | ||
87 | return -EINVAL; | ||
88 | |||
89 | if (bl->props.fb_blank == FB_BLANK_UNBLANK && | ||
90 | bl->props.power == FB_BLANK_UNBLANK) | ||
91 | level = bl->props.brightness; | ||
92 | else | ||
93 | level = 0; | ||
94 | |||
95 | return dssdev->set_backlight(dssdev, level); | ||
96 | } | ||
97 | |||
98 | static int nec_8048_bl_get_brightness(struct backlight_device *bl) | ||
99 | { | ||
100 | if (bl->props.fb_blank == FB_BLANK_UNBLANK && | ||
101 | bl->props.power == FB_BLANK_UNBLANK) | ||
102 | return bl->props.brightness; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static const struct backlight_ops nec_8048_bl_ops = { | ||
108 | .get_brightness = nec_8048_bl_get_brightness, | ||
109 | .update_status = nec_8048_bl_update_status, | ||
110 | }; | ||
111 | |||
112 | static int nec_8048_panel_probe(struct omap_dss_device *dssdev) | ||
113 | { | ||
114 | struct backlight_device *bl; | ||
115 | struct nec_8048_data *necd; | ||
116 | struct backlight_properties props; | ||
117 | int r; | ||
118 | |||
119 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
120 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_RF | | ||
121 | OMAP_DSS_LCD_ONOFF; | ||
122 | dssdev->panel.timings = nec_8048_panel_timings; | ||
123 | |||
124 | necd = kzalloc(sizeof(*necd), GFP_KERNEL); | ||
125 | if (!necd) | ||
126 | return -ENOMEM; | ||
127 | |||
128 | dev_set_drvdata(&dssdev->dev, necd); | ||
129 | |||
130 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
131 | props.max_brightness = 255; | ||
132 | |||
133 | bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev, | ||
134 | &nec_8048_bl_ops, &props); | ||
135 | if (IS_ERR(bl)) { | ||
136 | r = PTR_ERR(bl); | ||
137 | kfree(necd); | ||
138 | return r; | ||
139 | } | ||
140 | necd->bl = bl; | ||
141 | |||
142 | bl->props.fb_blank = FB_BLANK_UNBLANK; | ||
143 | bl->props.power = FB_BLANK_UNBLANK; | ||
144 | bl->props.max_brightness = dssdev->max_backlight_level; | ||
145 | bl->props.brightness = dssdev->max_backlight_level; | ||
146 | |||
147 | r = nec_8048_bl_update_status(bl); | ||
148 | if (r < 0) | ||
149 | dev_err(&dssdev->dev, "failed to set lcd brightness\n"); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static void nec_8048_panel_remove(struct omap_dss_device *dssdev) | ||
155 | { | ||
156 | struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); | ||
157 | struct backlight_device *bl = necd->bl; | ||
158 | |||
159 | bl->props.power = FB_BLANK_POWERDOWN; | ||
160 | nec_8048_bl_update_status(bl); | ||
161 | backlight_device_unregister(bl); | ||
162 | |||
163 | kfree(necd); | ||
164 | } | ||
165 | |||
166 | static int nec_8048_panel_enable(struct omap_dss_device *dssdev) | ||
167 | { | ||
168 | int r = 0; | ||
169 | struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); | ||
170 | struct backlight_device *bl = necd->bl; | ||
171 | |||
172 | if (dssdev->platform_enable) { | ||
173 | r = dssdev->platform_enable(dssdev); | ||
174 | if (r) | ||
175 | return r; | ||
176 | } | ||
177 | |||
178 | r = nec_8048_bl_update_status(bl); | ||
179 | if (r < 0) | ||
180 | dev_err(&dssdev->dev, "failed to set lcd brightness\n"); | ||
181 | |||
182 | r = omapdss_dpi_display_enable(dssdev); | ||
183 | |||
184 | return r; | ||
185 | } | ||
186 | |||
187 | static void nec_8048_panel_disable(struct omap_dss_device *dssdev) | ||
188 | { | ||
189 | struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); | ||
190 | struct backlight_device *bl = necd->bl; | ||
191 | |||
192 | omapdss_dpi_display_disable(dssdev); | ||
193 | |||
194 | bl->props.brightness = 0; | ||
195 | nec_8048_bl_update_status(bl); | ||
196 | |||
197 | if (dssdev->platform_disable) | ||
198 | dssdev->platform_disable(dssdev); | ||
199 | } | ||
200 | |||
201 | static int nec_8048_panel_suspend(struct omap_dss_device *dssdev) | ||
202 | { | ||
203 | nec_8048_panel_disable(dssdev); | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int nec_8048_panel_resume(struct omap_dss_device *dssdev) | ||
208 | { | ||
209 | return nec_8048_panel_enable(dssdev); | ||
210 | } | ||
211 | |||
212 | static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev) | ||
213 | { | ||
214 | return 16; | ||
215 | } | ||
216 | |||
217 | static struct omap_dss_driver nec_8048_driver = { | ||
218 | .probe = nec_8048_panel_probe, | ||
219 | .remove = nec_8048_panel_remove, | ||
220 | .enable = nec_8048_panel_enable, | ||
221 | .disable = nec_8048_panel_disable, | ||
222 | .suspend = nec_8048_panel_suspend, | ||
223 | .resume = nec_8048_panel_resume, | ||
224 | .get_recommended_bpp = nec_8048_recommended_bpp, | ||
225 | |||
226 | .driver = { | ||
227 | .name = "NEC_8048_panel", | ||
228 | .owner = THIS_MODULE, | ||
229 | }, | ||
230 | }; | ||
231 | |||
232 | static int nec_8048_spi_send(struct spi_device *spi, unsigned char reg_addr, | ||
233 | unsigned char reg_data) | ||
234 | { | ||
235 | int ret = 0; | ||
236 | unsigned int cmd = 0, data = 0; | ||
237 | |||
238 | cmd = 0x0000 | reg_addr; /* register address write */ | ||
239 | data = 0x0100 | reg_data ; /* register data write */ | ||
240 | data = (cmd << 16) | data; | ||
241 | |||
242 | ret = spi_write(spi, (unsigned char *)&data, 4); | ||
243 | if (ret) | ||
244 | pr_err("error in spi_write %x\n", data); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int init_nec_8048_wvga_lcd(struct spi_device *spi) | ||
250 | { | ||
251 | unsigned int i; | ||
252 | /* Initialization Sequence */ | ||
253 | /* nec_8048_spi_send(spi, REG, VAL) */ | ||
254 | for (i = 0; i < (ARRAY_SIZE(nec_8048_init_seq) - 1); i++) | ||
255 | nec_8048_spi_send(spi, nec_8048_init_seq[i].addr, | ||
256 | nec_8048_init_seq[i].dat); | ||
257 | udelay(20); | ||
258 | nec_8048_spi_send(spi, nec_8048_init_seq[i].addr, | ||
259 | nec_8048_init_seq[i].dat); | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int nec_8048_spi_probe(struct spi_device *spi) | ||
264 | { | ||
265 | spi->mode = SPI_MODE_0; | ||
266 | spi->bits_per_word = 32; | ||
267 | spi_setup(spi); | ||
268 | |||
269 | init_nec_8048_wvga_lcd(spi); | ||
270 | |||
271 | return omap_dss_register_driver(&nec_8048_driver); | ||
272 | } | ||
273 | |||
274 | static int nec_8048_spi_remove(struct spi_device *spi) | ||
275 | { | ||
276 | omap_dss_unregister_driver(&nec_8048_driver); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg) | ||
282 | { | ||
283 | nec_8048_spi_send(spi, 2, 0x01); | ||
284 | mdelay(40); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int nec_8048_spi_resume(struct spi_device *spi) | ||
290 | { | ||
291 | /* reinitialize the panel */ | ||
292 | spi_setup(spi); | ||
293 | nec_8048_spi_send(spi, 2, 0x00); | ||
294 | init_nec_8048_wvga_lcd(spi); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static struct spi_driver nec_8048_spi_driver = { | ||
300 | .probe = nec_8048_spi_probe, | ||
301 | .remove = __devexit_p(nec_8048_spi_remove), | ||
302 | .suspend = nec_8048_spi_suspend, | ||
303 | .resume = nec_8048_spi_resume, | ||
304 | .driver = { | ||
305 | .name = "nec_8048_spi", | ||
306 | .bus = &spi_bus_type, | ||
307 | .owner = THIS_MODULE, | ||
308 | }, | ||
309 | }; | ||
310 | |||
311 | static int __init nec_8048_lcd_init(void) | ||
312 | { | ||
313 | return spi_register_driver(&nec_8048_spi_driver); | ||
314 | } | ||
315 | |||
316 | static void __exit nec_8048_lcd_exit(void) | ||
317 | { | ||
318 | return spi_unregister_driver(&nec_8048_spi_driver); | ||
319 | } | ||
320 | |||
321 | module_init(nec_8048_lcd_init); | ||
322 | module_exit(nec_8048_lcd_exit); | ||
323 | MODULE_AUTHOR("Erik Gilling <konkers@android.com>"); | ||
324 | MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver"); | ||
325 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c b/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c deleted file mode 100644 index 0c6896cea2d0..000000000000 --- a/drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel driver for Sharp LQ043T1DG01 | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments Inc | ||
5 | * Author: Vaibhav Hiremath <hvaibhav@ti.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/device.h> | ||
23 | #include <linux/err.h> | ||
24 | |||
25 | #include <plat/display.h> | ||
26 | |||
27 | static struct omap_video_timings sharp_lq_timings = { | ||
28 | .x_res = 480, | ||
29 | .y_res = 272, | ||
30 | |||
31 | .pixel_clock = 9000, | ||
32 | |||
33 | .hsw = 42, | ||
34 | .hfp = 3, | ||
35 | .hbp = 2, | ||
36 | |||
37 | .vsw = 11, | ||
38 | .vfp = 3, | ||
39 | .vbp = 2, | ||
40 | }; | ||
41 | |||
42 | static int sharp_lq_panel_power_on(struct omap_dss_device *dssdev) | ||
43 | { | ||
44 | int r; | ||
45 | |||
46 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
47 | return 0; | ||
48 | |||
49 | r = omapdss_dpi_display_enable(dssdev); | ||
50 | if (r) | ||
51 | goto err0; | ||
52 | |||
53 | /* wait couple of vsyncs until enabling the LCD */ | ||
54 | msleep(50); | ||
55 | |||
56 | if (dssdev->platform_enable) { | ||
57 | r = dssdev->platform_enable(dssdev); | ||
58 | if (r) | ||
59 | goto err1; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | err1: | ||
64 | omapdss_dpi_display_disable(dssdev); | ||
65 | err0: | ||
66 | return r; | ||
67 | } | ||
68 | |||
69 | static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev) | ||
70 | { | ||
71 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
72 | return; | ||
73 | |||
74 | if (dssdev->platform_disable) | ||
75 | dssdev->platform_disable(dssdev); | ||
76 | |||
77 | /* wait at least 5 vsyncs after disabling the LCD */ | ||
78 | msleep(100); | ||
79 | |||
80 | omapdss_dpi_display_disable(dssdev); | ||
81 | } | ||
82 | |||
83 | static int sharp_lq_panel_probe(struct omap_dss_device *dssdev) | ||
84 | { | ||
85 | |||
86 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
87 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO; | ||
88 | dssdev->panel.acb = 0x0; | ||
89 | dssdev->panel.timings = sharp_lq_timings; | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | static void sharp_lq_panel_remove(struct omap_dss_device *dssdev) | ||
95 | { | ||
96 | } | ||
97 | |||
98 | static int sharp_lq_panel_enable(struct omap_dss_device *dssdev) | ||
99 | { | ||
100 | int r = 0; | ||
101 | |||
102 | r = sharp_lq_panel_power_on(dssdev); | ||
103 | if (r) | ||
104 | return r; | ||
105 | |||
106 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void sharp_lq_panel_disable(struct omap_dss_device *dssdev) | ||
112 | { | ||
113 | sharp_lq_panel_power_off(dssdev); | ||
114 | |||
115 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
116 | } | ||
117 | |||
118 | static int sharp_lq_panel_suspend(struct omap_dss_device *dssdev) | ||
119 | { | ||
120 | sharp_lq_panel_power_off(dssdev); | ||
121 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static int sharp_lq_panel_resume(struct omap_dss_device *dssdev) | ||
126 | { | ||
127 | int r = 0; | ||
128 | |||
129 | r = sharp_lq_panel_power_on(dssdev); | ||
130 | if (r) | ||
131 | return r; | ||
132 | |||
133 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static struct omap_dss_driver sharp_lq_driver = { | ||
139 | .probe = sharp_lq_panel_probe, | ||
140 | .remove = sharp_lq_panel_remove, | ||
141 | |||
142 | .enable = sharp_lq_panel_enable, | ||
143 | .disable = sharp_lq_panel_disable, | ||
144 | .suspend = sharp_lq_panel_suspend, | ||
145 | .resume = sharp_lq_panel_resume, | ||
146 | |||
147 | .driver = { | ||
148 | .name = "sharp_lq_panel", | ||
149 | .owner = THIS_MODULE, | ||
150 | }, | ||
151 | }; | ||
152 | |||
153 | static int __init sharp_lq_panel_drv_init(void) | ||
154 | { | ||
155 | return omap_dss_register_driver(&sharp_lq_driver); | ||
156 | } | ||
157 | |||
158 | static void __exit sharp_lq_panel_drv_exit(void) | ||
159 | { | ||
160 | omap_dss_unregister_driver(&sharp_lq_driver); | ||
161 | } | ||
162 | |||
163 | module_init(sharp_lq_panel_drv_init); | ||
164 | module_exit(sharp_lq_panel_drv_exit); | ||
165 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index e1c765d11419..61026f96ad20 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -465,7 +465,7 @@ static int taal_bl_get_intensity(struct backlight_device *dev) | |||
465 | return 0; | 465 | return 0; |
466 | } | 466 | } |
467 | 467 | ||
468 | static struct backlight_ops taal_bl_ops = { | 468 | static const struct backlight_ops taal_bl_ops = { |
469 | .get_brightness = taal_bl_get_intensity, | 469 | .get_brightness = taal_bl_get_intensity, |
470 | .update_status = taal_bl_update_status, | 470 | .update_status = taal_bl_update_status, |
471 | }; | 471 | }; |
diff --git a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c b/drivers/video/omap2/displays/panel-toppoly-tdo35s.c deleted file mode 100644 index 526e906c8a6c..000000000000 --- a/drivers/video/omap2/displays/panel-toppoly-tdo35s.c +++ /dev/null | |||
@@ -1,164 +0,0 @@ | |||
1 | /* | ||
2 | * LCD panel driver for Toppoly TDO35S | ||
3 | * | ||
4 | * Copyright (C) 2009 CompuLab, Ltd. | ||
5 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on generic panel support | ||
8 | * Copyright (C) 2008 Nokia Corporation | ||
9 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License version 2 as published by | ||
13 | * the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
18 | * more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along with | ||
21 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #include <plat/display.h> | ||
28 | |||
29 | static struct omap_video_timings toppoly_tdo_panel_timings = { | ||
30 | /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
31 | .x_res = 480, | ||
32 | .y_res = 640, | ||
33 | |||
34 | .pixel_clock = 26000, | ||
35 | |||
36 | .hfp = 104, | ||
37 | .hsw = 8, | ||
38 | .hbp = 8, | ||
39 | |||
40 | .vfp = 4, | ||
41 | .vsw = 2, | ||
42 | .vbp = 2, | ||
43 | }; | ||
44 | |||
45 | static int toppoly_tdo_panel_power_on(struct omap_dss_device *dssdev) | ||
46 | { | ||
47 | int r; | ||
48 | |||
49 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
50 | return 0; | ||
51 | |||
52 | r = omapdss_dpi_display_enable(dssdev); | ||
53 | if (r) | ||
54 | goto err0; | ||
55 | |||
56 | if (dssdev->platform_enable) { | ||
57 | r = dssdev->platform_enable(dssdev); | ||
58 | if (r) | ||
59 | goto err1; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | err1: | ||
64 | omapdss_dpi_display_disable(dssdev); | ||
65 | err0: | ||
66 | return r; | ||
67 | } | ||
68 | |||
69 | static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev) | ||
70 | { | ||
71 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
72 | return; | ||
73 | |||
74 | if (dssdev->platform_disable) | ||
75 | dssdev->platform_disable(dssdev); | ||
76 | |||
77 | omapdss_dpi_display_disable(dssdev); | ||
78 | } | ||
79 | |||
80 | static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev) | ||
81 | { | ||
82 | dssdev->panel.config = OMAP_DSS_LCD_TFT | | ||
83 | OMAP_DSS_LCD_IVS | | ||
84 | OMAP_DSS_LCD_IHS | | ||
85 | OMAP_DSS_LCD_IPC | | ||
86 | OMAP_DSS_LCD_ONOFF; | ||
87 | |||
88 | dssdev->panel.timings = toppoly_tdo_panel_timings; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static void toppoly_tdo_panel_remove(struct omap_dss_device *dssdev) | ||
94 | { | ||
95 | } | ||
96 | |||
97 | static int toppoly_tdo_panel_enable(struct omap_dss_device *dssdev) | ||
98 | { | ||
99 | int r = 0; | ||
100 | |||
101 | r = toppoly_tdo_panel_power_on(dssdev); | ||
102 | if (r) | ||
103 | return r; | ||
104 | |||
105 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static void toppoly_tdo_panel_disable(struct omap_dss_device *dssdev) | ||
111 | { | ||
112 | toppoly_tdo_panel_power_off(dssdev); | ||
113 | |||
114 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
115 | } | ||
116 | |||
117 | static int toppoly_tdo_panel_suspend(struct omap_dss_device *dssdev) | ||
118 | { | ||
119 | toppoly_tdo_panel_power_off(dssdev); | ||
120 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int toppoly_tdo_panel_resume(struct omap_dss_device *dssdev) | ||
125 | { | ||
126 | int r = 0; | ||
127 | |||
128 | r = toppoly_tdo_panel_power_on(dssdev); | ||
129 | if (r) | ||
130 | return r; | ||
131 | |||
132 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static struct omap_dss_driver generic_driver = { | ||
138 | .probe = toppoly_tdo_panel_probe, | ||
139 | .remove = toppoly_tdo_panel_remove, | ||
140 | |||
141 | .enable = toppoly_tdo_panel_enable, | ||
142 | .disable = toppoly_tdo_panel_disable, | ||
143 | .suspend = toppoly_tdo_panel_suspend, | ||
144 | .resume = toppoly_tdo_panel_resume, | ||
145 | |||
146 | .driver = { | ||
147 | .name = "toppoly_tdo35s_panel", | ||
148 | .owner = THIS_MODULE, | ||
149 | }, | ||
150 | }; | ||
151 | |||
152 | static int __init toppoly_tdo_panel_drv_init(void) | ||
153 | { | ||
154 | return omap_dss_register_driver(&generic_driver); | ||
155 | } | ||
156 | |||
157 | static void __exit toppoly_tdo_panel_drv_exit(void) | ||
158 | { | ||
159 | omap_dss_unregister_driver(&generic_driver); | ||
160 | } | ||
161 | |||
162 | module_init(toppoly_tdo_panel_drv_init); | ||
163 | module_exit(toppoly_tdo_panel_drv_exit); | ||
164 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index fa40fa59a9ac..9f8c69f16e61 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -44,34 +44,40 @@ | |||
44 | /* DISPC */ | 44 | /* DISPC */ |
45 | #define DISPC_BASE 0x48050400 | 45 | #define DISPC_BASE 0x48050400 |
46 | 46 | ||
47 | #define DISPC_SZ_REGS SZ_1K | 47 | #define DISPC_SZ_REGS SZ_4K |
48 | 48 | ||
49 | struct dispc_reg { u16 idx; }; | 49 | struct dispc_reg { u16 idx; }; |
50 | 50 | ||
51 | #define DISPC_REG(idx) ((const struct dispc_reg) { idx }) | 51 | #define DISPC_REG(idx) ((const struct dispc_reg) { idx }) |
52 | 52 | ||
53 | /* DISPC common */ | 53 | /* |
54 | * DISPC common registers and | ||
55 | * DISPC channel registers , ch = 0 for LCD, ch = 1 for | ||
56 | * DIGIT, and ch = 2 for LCD2 | ||
57 | */ | ||
54 | #define DISPC_REVISION DISPC_REG(0x0000) | 58 | #define DISPC_REVISION DISPC_REG(0x0000) |
55 | #define DISPC_SYSCONFIG DISPC_REG(0x0010) | 59 | #define DISPC_SYSCONFIG DISPC_REG(0x0010) |
56 | #define DISPC_SYSSTATUS DISPC_REG(0x0014) | 60 | #define DISPC_SYSSTATUS DISPC_REG(0x0014) |
57 | #define DISPC_IRQSTATUS DISPC_REG(0x0018) | 61 | #define DISPC_IRQSTATUS DISPC_REG(0x0018) |
58 | #define DISPC_IRQENABLE DISPC_REG(0x001C) | 62 | #define DISPC_IRQENABLE DISPC_REG(0x001C) |
59 | #define DISPC_CONTROL DISPC_REG(0x0040) | 63 | #define DISPC_CONTROL DISPC_REG(0x0040) |
64 | #define DISPC_CONTROL2 DISPC_REG(0x0238) | ||
60 | #define DISPC_CONFIG DISPC_REG(0x0044) | 65 | #define DISPC_CONFIG DISPC_REG(0x0044) |
66 | #define DISPC_CONFIG2 DISPC_REG(0x0620) | ||
61 | #define DISPC_CAPABLE DISPC_REG(0x0048) | 67 | #define DISPC_CAPABLE DISPC_REG(0x0048) |
62 | #define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) | 68 | #define DISPC_DEFAULT_COLOR(ch) DISPC_REG(ch == 0 ? 0x004C : \ |
63 | #define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) | 69 | (ch == 1 ? 0x0050 : 0x03AC)) |
64 | #define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) | 70 | #define DISPC_TRANS_COLOR(ch) DISPC_REG(ch == 0 ? 0x0054 : \ |
65 | #define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) | 71 | (ch == 1 ? 0x0058 : 0x03B0)) |
66 | #define DISPC_LINE_STATUS DISPC_REG(0x005C) | 72 | #define DISPC_LINE_STATUS DISPC_REG(0x005C) |
67 | #define DISPC_LINE_NUMBER DISPC_REG(0x0060) | 73 | #define DISPC_LINE_NUMBER DISPC_REG(0x0060) |
68 | #define DISPC_TIMING_H DISPC_REG(0x0064) | 74 | #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) |
69 | #define DISPC_TIMING_V DISPC_REG(0x0068) | 75 | #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) |
70 | #define DISPC_POL_FREQ DISPC_REG(0x006C) | 76 | #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) |
71 | #define DISPC_DIVISOR DISPC_REG(0x0070) | 77 | #define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) |
72 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) | 78 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) |
73 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) | 79 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) |
74 | #define DISPC_SIZE_LCD DISPC_REG(0x007C) | 80 | #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) |
75 | 81 | ||
76 | /* DISPC GFX plane */ | 82 | /* DISPC GFX plane */ |
77 | #define DISPC_GFX_BA0 DISPC_REG(0x0080) | 83 | #define DISPC_GFX_BA0 DISPC_REG(0x0080) |
@@ -86,13 +92,12 @@ struct dispc_reg { u16 idx; }; | |||
86 | #define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) | 92 | #define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) |
87 | #define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) | 93 | #define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) |
88 | 94 | ||
89 | #define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) | 95 | #define DISPC_DATA_CYCLE1(ch) DISPC_REG(ch != 2 ? 0x01D4 : 0x03C0) |
90 | #define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) | 96 | #define DISPC_DATA_CYCLE2(ch) DISPC_REG(ch != 2 ? 0x01D8 : 0x03C4) |
91 | #define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) | 97 | #define DISPC_DATA_CYCLE3(ch) DISPC_REG(ch != 2 ? 0x01DC : 0x03C8) |
92 | 98 | #define DISPC_CPR_COEF_R(ch) DISPC_REG(ch != 2 ? 0x0220 : 0x03BC) | |
93 | #define DISPC_CPR_COEF_R DISPC_REG(0x0220) | 99 | #define DISPC_CPR_COEF_G(ch) DISPC_REG(ch != 2 ? 0x0224 : 0x03B8) |
94 | #define DISPC_CPR_COEF_G DISPC_REG(0x0224) | 100 | #define DISPC_CPR_COEF_B(ch) DISPC_REG(ch != 2 ? 0x0228 : 0x03B4) |
95 | #define DISPC_CPR_COEF_B DISPC_REG(0x0228) | ||
96 | 101 | ||
97 | #define DISPC_GFX_PRELOAD DISPC_REG(0x022C) | 102 | #define DISPC_GFX_PRELOAD DISPC_REG(0x022C) |
98 | 103 | ||
@@ -217,18 +222,29 @@ void dispc_save_context(void) | |||
217 | SR(IRQENABLE); | 222 | SR(IRQENABLE); |
218 | SR(CONTROL); | 223 | SR(CONTROL); |
219 | SR(CONFIG); | 224 | SR(CONFIG); |
220 | SR(DEFAULT_COLOR0); | 225 | SR(DEFAULT_COLOR(0)); |
221 | SR(DEFAULT_COLOR1); | 226 | SR(DEFAULT_COLOR(1)); |
222 | SR(TRANS_COLOR0); | 227 | SR(TRANS_COLOR(0)); |
223 | SR(TRANS_COLOR1); | 228 | SR(TRANS_COLOR(1)); |
224 | SR(LINE_NUMBER); | 229 | SR(LINE_NUMBER); |
225 | SR(TIMING_H); | 230 | SR(TIMING_H(0)); |
226 | SR(TIMING_V); | 231 | SR(TIMING_V(0)); |
227 | SR(POL_FREQ); | 232 | SR(POL_FREQ(0)); |
228 | SR(DIVISOR); | 233 | SR(DIVISOR(0)); |
229 | SR(GLOBAL_ALPHA); | 234 | SR(GLOBAL_ALPHA); |
230 | SR(SIZE_DIG); | 235 | SR(SIZE_DIG); |
231 | SR(SIZE_LCD); | 236 | SR(SIZE_LCD(0)); |
237 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
238 | SR(CONTROL2); | ||
239 | SR(DEFAULT_COLOR(2)); | ||
240 | SR(TRANS_COLOR(2)); | ||
241 | SR(SIZE_LCD(2)); | ||
242 | SR(TIMING_H(2)); | ||
243 | SR(TIMING_V(2)); | ||
244 | SR(POL_FREQ(2)); | ||
245 | SR(DIVISOR(2)); | ||
246 | SR(CONFIG2); | ||
247 | } | ||
232 | 248 | ||
233 | SR(GFX_BA0); | 249 | SR(GFX_BA0); |
234 | SR(GFX_BA1); | 250 | SR(GFX_BA1); |
@@ -241,13 +257,22 @@ void dispc_save_context(void) | |||
241 | SR(GFX_WINDOW_SKIP); | 257 | SR(GFX_WINDOW_SKIP); |
242 | SR(GFX_TABLE_BA); | 258 | SR(GFX_TABLE_BA); |
243 | 259 | ||
244 | SR(DATA_CYCLE1); | 260 | SR(DATA_CYCLE1(0)); |
245 | SR(DATA_CYCLE2); | 261 | SR(DATA_CYCLE2(0)); |
246 | SR(DATA_CYCLE3); | 262 | SR(DATA_CYCLE3(0)); |
247 | 263 | ||
248 | SR(CPR_COEF_R); | 264 | SR(CPR_COEF_R(0)); |
249 | SR(CPR_COEF_G); | 265 | SR(CPR_COEF_G(0)); |
250 | SR(CPR_COEF_B); | 266 | SR(CPR_COEF_B(0)); |
267 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
268 | SR(CPR_COEF_B(2)); | ||
269 | SR(CPR_COEF_G(2)); | ||
270 | SR(CPR_COEF_R(2)); | ||
271 | |||
272 | SR(DATA_CYCLE1(2)); | ||
273 | SR(DATA_CYCLE2(2)); | ||
274 | SR(DATA_CYCLE3(2)); | ||
275 | } | ||
251 | 276 | ||
252 | SR(GFX_PRELOAD); | 277 | SR(GFX_PRELOAD); |
253 | 278 | ||
@@ -356,18 +381,28 @@ void dispc_restore_context(void) | |||
356 | /*RR(IRQENABLE);*/ | 381 | /*RR(IRQENABLE);*/ |
357 | /*RR(CONTROL);*/ | 382 | /*RR(CONTROL);*/ |
358 | RR(CONFIG); | 383 | RR(CONFIG); |
359 | RR(DEFAULT_COLOR0); | 384 | RR(DEFAULT_COLOR(0)); |
360 | RR(DEFAULT_COLOR1); | 385 | RR(DEFAULT_COLOR(1)); |
361 | RR(TRANS_COLOR0); | 386 | RR(TRANS_COLOR(0)); |
362 | RR(TRANS_COLOR1); | 387 | RR(TRANS_COLOR(1)); |
363 | RR(LINE_NUMBER); | 388 | RR(LINE_NUMBER); |
364 | RR(TIMING_H); | 389 | RR(TIMING_H(0)); |
365 | RR(TIMING_V); | 390 | RR(TIMING_V(0)); |
366 | RR(POL_FREQ); | 391 | RR(POL_FREQ(0)); |
367 | RR(DIVISOR); | 392 | RR(DIVISOR(0)); |
368 | RR(GLOBAL_ALPHA); | 393 | RR(GLOBAL_ALPHA); |
369 | RR(SIZE_DIG); | 394 | RR(SIZE_DIG); |
370 | RR(SIZE_LCD); | 395 | RR(SIZE_LCD(0)); |
396 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
397 | RR(DEFAULT_COLOR(2)); | ||
398 | RR(TRANS_COLOR(2)); | ||
399 | RR(SIZE_LCD(2)); | ||
400 | RR(TIMING_H(2)); | ||
401 | RR(TIMING_V(2)); | ||
402 | RR(POL_FREQ(2)); | ||
403 | RR(DIVISOR(2)); | ||
404 | RR(CONFIG2); | ||
405 | } | ||
371 | 406 | ||
372 | RR(GFX_BA0); | 407 | RR(GFX_BA0); |
373 | RR(GFX_BA1); | 408 | RR(GFX_BA1); |
@@ -380,13 +415,22 @@ void dispc_restore_context(void) | |||
380 | RR(GFX_WINDOW_SKIP); | 415 | RR(GFX_WINDOW_SKIP); |
381 | RR(GFX_TABLE_BA); | 416 | RR(GFX_TABLE_BA); |
382 | 417 | ||
383 | RR(DATA_CYCLE1); | 418 | RR(DATA_CYCLE1(0)); |
384 | RR(DATA_CYCLE2); | 419 | RR(DATA_CYCLE2(0)); |
385 | RR(DATA_CYCLE3); | 420 | RR(DATA_CYCLE3(0)); |
386 | 421 | ||
387 | RR(CPR_COEF_R); | 422 | RR(CPR_COEF_R(0)); |
388 | RR(CPR_COEF_G); | 423 | RR(CPR_COEF_G(0)); |
389 | RR(CPR_COEF_B); | 424 | RR(CPR_COEF_B(0)); |
425 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
426 | RR(DATA_CYCLE1(2)); | ||
427 | RR(DATA_CYCLE2(2)); | ||
428 | RR(DATA_CYCLE3(2)); | ||
429 | |||
430 | RR(CPR_COEF_B(2)); | ||
431 | RR(CPR_COEF_G(2)); | ||
432 | RR(CPR_COEF_R(2)); | ||
433 | } | ||
390 | 434 | ||
391 | RR(GFX_PRELOAD); | 435 | RR(GFX_PRELOAD); |
392 | 436 | ||
@@ -490,7 +534,8 @@ void dispc_restore_context(void) | |||
490 | 534 | ||
491 | /* enable last, because LCD & DIGIT enable are here */ | 535 | /* enable last, because LCD & DIGIT enable are here */ |
492 | RR(CONTROL); | 536 | RR(CONTROL); |
493 | 537 | if (dss_has_feature(FEAT_MGR_LCD2)) | |
538 | RR(CONTROL2); | ||
494 | /* clear spurious SYNC_LOST_DIGIT interrupts */ | 539 | /* clear spurious SYNC_LOST_DIGIT interrupts */ |
495 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 540 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); |
496 | 541 | ||
@@ -516,42 +561,63 @@ bool dispc_go_busy(enum omap_channel channel) | |||
516 | { | 561 | { |
517 | int bit; | 562 | int bit; |
518 | 563 | ||
519 | if (channel == OMAP_DSS_CHANNEL_LCD) | 564 | if (channel == OMAP_DSS_CHANNEL_LCD || |
565 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
520 | bit = 5; /* GOLCD */ | 566 | bit = 5; /* GOLCD */ |
521 | else | 567 | else |
522 | bit = 6; /* GODIGIT */ | 568 | bit = 6; /* GODIGIT */ |
523 | 569 | ||
524 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; | 570 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
571 | return REG_GET(DISPC_CONTROL2, bit, bit) == 1; | ||
572 | else | ||
573 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; | ||
525 | } | 574 | } |
526 | 575 | ||
527 | void dispc_go(enum omap_channel channel) | 576 | void dispc_go(enum omap_channel channel) |
528 | { | 577 | { |
529 | int bit; | 578 | int bit; |
579 | bool enable_bit, go_bit; | ||
530 | 580 | ||
531 | enable_clocks(1); | 581 | enable_clocks(1); |
532 | 582 | ||
533 | if (channel == OMAP_DSS_CHANNEL_LCD) | 583 | if (channel == OMAP_DSS_CHANNEL_LCD || |
584 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
534 | bit = 0; /* LCDENABLE */ | 585 | bit = 0; /* LCDENABLE */ |
535 | else | 586 | else |
536 | bit = 1; /* DIGITALENABLE */ | 587 | bit = 1; /* DIGITALENABLE */ |
537 | 588 | ||
538 | /* if the channel is not enabled, we don't need GO */ | 589 | /* if the channel is not enabled, we don't need GO */ |
539 | if (REG_GET(DISPC_CONTROL, bit, bit) == 0) | 590 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
591 | enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1; | ||
592 | else | ||
593 | enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; | ||
594 | |||
595 | if (!enable_bit) | ||
540 | goto end; | 596 | goto end; |
541 | 597 | ||
542 | if (channel == OMAP_DSS_CHANNEL_LCD) | 598 | if (channel == OMAP_DSS_CHANNEL_LCD || |
599 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
543 | bit = 5; /* GOLCD */ | 600 | bit = 5; /* GOLCD */ |
544 | else | 601 | else |
545 | bit = 6; /* GODIGIT */ | 602 | bit = 6; /* GODIGIT */ |
546 | 603 | ||
547 | if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { | 604 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
605 | go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1; | ||
606 | else | ||
607 | go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; | ||
608 | |||
609 | if (go_bit) { | ||
548 | DSSERR("GO bit not down for channel %d\n", channel); | 610 | DSSERR("GO bit not down for channel %d\n", channel); |
549 | goto end; | 611 | goto end; |
550 | } | 612 | } |
551 | 613 | ||
552 | DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); | 614 | DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : |
615 | (channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT")); | ||
553 | 616 | ||
554 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); | 617 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
618 | REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit); | ||
619 | else | ||
620 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); | ||
555 | end: | 621 | end: |
556 | enable_clocks(0); | 622 | enable_clocks(0); |
557 | } | 623 | } |
@@ -773,13 +839,26 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | |||
773 | dispc_write_reg(vsi_reg[plane-1], val); | 839 | dispc_write_reg(vsi_reg[plane-1], val); |
774 | } | 840 | } |
775 | 841 | ||
842 | static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) | ||
843 | { | ||
844 | if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) | ||
845 | return; | ||
846 | |||
847 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
848 | plane == OMAP_DSS_VIDEO1) | ||
849 | return; | ||
850 | |||
851 | REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 28, 28); | ||
852 | } | ||
853 | |||
776 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | 854 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) |
777 | { | 855 | { |
778 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 856 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) |
779 | return; | 857 | return; |
780 | 858 | ||
781 | BUG_ON(!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 859 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && |
782 | plane == OMAP_DSS_VIDEO1); | 860 | plane == OMAP_DSS_VIDEO1) |
861 | return; | ||
783 | 862 | ||
784 | if (plane == OMAP_DSS_GFX) | 863 | if (plane == OMAP_DSS_GFX) |
785 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); | 864 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); |
@@ -851,6 +930,7 @@ static void _dispc_set_channel_out(enum omap_plane plane, | |||
851 | { | 930 | { |
852 | int shift; | 931 | int shift; |
853 | u32 val; | 932 | u32 val; |
933 | int chan = 0, chan2 = 0; | ||
854 | 934 | ||
855 | switch (plane) { | 935 | switch (plane) { |
856 | case OMAP_DSS_GFX: | 936 | case OMAP_DSS_GFX: |
@@ -866,7 +946,29 @@ static void _dispc_set_channel_out(enum omap_plane plane, | |||
866 | } | 946 | } |
867 | 947 | ||
868 | val = dispc_read_reg(dispc_reg_att[plane]); | 948 | val = dispc_read_reg(dispc_reg_att[plane]); |
869 | val = FLD_MOD(val, channel, shift, shift); | 949 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
950 | switch (channel) { | ||
951 | case OMAP_DSS_CHANNEL_LCD: | ||
952 | chan = 0; | ||
953 | chan2 = 0; | ||
954 | break; | ||
955 | case OMAP_DSS_CHANNEL_DIGIT: | ||
956 | chan = 1; | ||
957 | chan2 = 0; | ||
958 | break; | ||
959 | case OMAP_DSS_CHANNEL_LCD2: | ||
960 | chan = 0; | ||
961 | chan2 = 1; | ||
962 | break; | ||
963 | default: | ||
964 | BUG(); | ||
965 | } | ||
966 | |||
967 | val = FLD_MOD(val, chan, shift, shift); | ||
968 | val = FLD_MOD(val, chan2, 31, 30); | ||
969 | } else { | ||
970 | val = FLD_MOD(val, channel, shift, shift); | ||
971 | } | ||
870 | dispc_write_reg(dispc_reg_att[plane], val); | 972 | dispc_write_reg(dispc_reg_att[plane], val); |
871 | } | 973 | } |
872 | 974 | ||
@@ -923,13 +1025,13 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) | |||
923 | enable_clocks(0); | 1025 | enable_clocks(0); |
924 | } | 1026 | } |
925 | 1027 | ||
926 | void dispc_set_lcd_size(u16 width, u16 height) | 1028 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) |
927 | { | 1029 | { |
928 | u32 val; | 1030 | u32 val; |
929 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1031 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
930 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 1032 | val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
931 | enable_clocks(1); | 1033 | enable_clocks(1); |
932 | dispc_write_reg(DISPC_SIZE_LCD, val); | 1034 | dispc_write_reg(DISPC_SIZE_LCD(channel), val); |
933 | enable_clocks(0); | 1035 | enable_clocks(0); |
934 | } | 1036 | } |
935 | 1037 | ||
@@ -1426,12 +1528,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror, | |||
1426 | } | 1528 | } |
1427 | } | 1529 | } |
1428 | 1530 | ||
1429 | static unsigned long calc_fclk_five_taps(u16 width, u16 height, | 1531 | static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, |
1430 | u16 out_width, u16 out_height, enum omap_color_mode color_mode) | 1532 | u16 height, u16 out_width, u16 out_height, |
1533 | enum omap_color_mode color_mode) | ||
1431 | { | 1534 | { |
1432 | u32 fclk = 0; | 1535 | u32 fclk = 0; |
1433 | /* FIXME venc pclk? */ | 1536 | /* FIXME venc pclk? */ |
1434 | u64 tmp, pclk = dispc_pclk_rate(); | 1537 | u64 tmp, pclk = dispc_pclk_rate(channel); |
1435 | 1538 | ||
1436 | if (height > out_height) { | 1539 | if (height > out_height) { |
1437 | /* FIXME get real display PPL */ | 1540 | /* FIXME get real display PPL */ |
@@ -1463,8 +1566,8 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height, | |||
1463 | return fclk; | 1566 | return fclk; |
1464 | } | 1567 | } |
1465 | 1568 | ||
1466 | static unsigned long calc_fclk(u16 width, u16 height, | 1569 | static unsigned long calc_fclk(enum omap_channel channel, u16 width, |
1467 | u16 out_width, u16 out_height) | 1570 | u16 height, u16 out_width, u16 out_height) |
1468 | { | 1571 | { |
1469 | unsigned int hf, vf; | 1572 | unsigned int hf, vf; |
1470 | 1573 | ||
@@ -1488,7 +1591,7 @@ static unsigned long calc_fclk(u16 width, u16 height, | |||
1488 | vf = 1; | 1591 | vf = 1; |
1489 | 1592 | ||
1490 | /* FIXME venc pclk? */ | 1593 | /* FIXME venc pclk? */ |
1491 | return dispc_pclk_rate() * vf * hf; | 1594 | return dispc_pclk_rate(channel) * vf * hf; |
1492 | } | 1595 | } |
1493 | 1596 | ||
1494 | void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) | 1597 | void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) |
@@ -1507,7 +1610,8 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1507 | bool ilace, | 1610 | bool ilace, |
1508 | enum omap_dss_rotation_type rotation_type, | 1611 | enum omap_dss_rotation_type rotation_type, |
1509 | u8 rotation, int mirror, | 1612 | u8 rotation, int mirror, |
1510 | u8 global_alpha) | 1613 | u8 global_alpha, u8 pre_mult_alpha, |
1614 | enum omap_channel channel) | ||
1511 | { | 1615 | { |
1512 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | 1616 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; |
1513 | bool five_taps = 0; | 1617 | bool five_taps = 0; |
@@ -1536,29 +1640,12 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1536 | height, pos_y, out_height); | 1640 | height, pos_y, out_height); |
1537 | } | 1641 | } |
1538 | 1642 | ||
1643 | if (!dss_feat_color_mode_supported(plane, color_mode)) | ||
1644 | return -EINVAL; | ||
1645 | |||
1539 | if (plane == OMAP_DSS_GFX) { | 1646 | if (plane == OMAP_DSS_GFX) { |
1540 | if (width != out_width || height != out_height) | 1647 | if (width != out_width || height != out_height) |
1541 | return -EINVAL; | 1648 | return -EINVAL; |
1542 | |||
1543 | switch (color_mode) { | ||
1544 | case OMAP_DSS_COLOR_ARGB16: | ||
1545 | case OMAP_DSS_COLOR_ARGB32: | ||
1546 | case OMAP_DSS_COLOR_RGBA32: | ||
1547 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
1548 | return -EINVAL; | ||
1549 | case OMAP_DSS_COLOR_RGBX32: | ||
1550 | if (cpu_is_omap24xx()) | ||
1551 | return -EINVAL; | ||
1552 | /* fall through */ | ||
1553 | case OMAP_DSS_COLOR_RGB12U: | ||
1554 | case OMAP_DSS_COLOR_RGB16: | ||
1555 | case OMAP_DSS_COLOR_RGB24P: | ||
1556 | case OMAP_DSS_COLOR_RGB24U: | ||
1557 | break; | ||
1558 | |||
1559 | default: | ||
1560 | return -EINVAL; | ||
1561 | } | ||
1562 | } else { | 1649 | } else { |
1563 | /* video plane */ | 1650 | /* video plane */ |
1564 | 1651 | ||
@@ -1572,42 +1659,16 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1572 | out_height > height * 8) | 1659 | out_height > height * 8) |
1573 | return -EINVAL; | 1660 | return -EINVAL; |
1574 | 1661 | ||
1575 | switch (color_mode) { | 1662 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1576 | case OMAP_DSS_COLOR_RGBX32: | 1663 | color_mode == OMAP_DSS_COLOR_UYVY) |
1577 | case OMAP_DSS_COLOR_RGB12U: | ||
1578 | if (cpu_is_omap24xx()) | ||
1579 | return -EINVAL; | ||
1580 | /* fall through */ | ||
1581 | case OMAP_DSS_COLOR_RGB16: | ||
1582 | case OMAP_DSS_COLOR_RGB24P: | ||
1583 | case OMAP_DSS_COLOR_RGB24U: | ||
1584 | break; | ||
1585 | |||
1586 | case OMAP_DSS_COLOR_ARGB16: | ||
1587 | case OMAP_DSS_COLOR_ARGB32: | ||
1588 | case OMAP_DSS_COLOR_RGBA32: | ||
1589 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
1590 | return -EINVAL; | ||
1591 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
1592 | plane == OMAP_DSS_VIDEO1) | ||
1593 | return -EINVAL; | ||
1594 | break; | ||
1595 | |||
1596 | case OMAP_DSS_COLOR_YUV2: | ||
1597 | case OMAP_DSS_COLOR_UYVY: | ||
1598 | cconv = 1; | 1664 | cconv = 1; |
1599 | break; | ||
1600 | |||
1601 | default: | ||
1602 | return -EINVAL; | ||
1603 | } | ||
1604 | 1665 | ||
1605 | /* Must use 5-tap filter? */ | 1666 | /* Must use 5-tap filter? */ |
1606 | five_taps = height > out_height * 2; | 1667 | five_taps = height > out_height * 2; |
1607 | 1668 | ||
1608 | if (!five_taps) { | 1669 | if (!five_taps) { |
1609 | fclk = calc_fclk(width, height, | 1670 | fclk = calc_fclk(channel, width, height, out_width, |
1610 | out_width, out_height); | 1671 | out_height); |
1611 | 1672 | ||
1612 | /* Try 5-tap filter if 3-tap fclk is too high */ | 1673 | /* Try 5-tap filter if 3-tap fclk is too high */ |
1613 | if (cpu_is_omap34xx() && height > out_height && | 1674 | if (cpu_is_omap34xx() && height > out_height && |
@@ -1621,7 +1682,7 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1621 | } | 1682 | } |
1622 | 1683 | ||
1623 | if (five_taps) | 1684 | if (five_taps) |
1624 | fclk = calc_fclk_five_taps(width, height, | 1685 | fclk = calc_fclk_five_taps(channel, width, height, |
1625 | out_width, out_height, color_mode); | 1686 | out_width, out_height, color_mode); |
1626 | 1687 | ||
1627 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | 1688 | DSSDBG("required fclk rate = %lu Hz\n", fclk); |
@@ -1693,8 +1754,8 @@ static int _dispc_setup_plane(enum omap_plane plane, | |||
1693 | 1754 | ||
1694 | _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); | 1755 | _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); |
1695 | 1756 | ||
1696 | if (plane != OMAP_DSS_VIDEO1) | 1757 | _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); |
1697 | _dispc_setup_global_alpha(plane, global_alpha); | 1758 | _dispc_setup_global_alpha(plane, global_alpha); |
1698 | 1759 | ||
1699 | return 0; | 1760 | return 0; |
1700 | } | 1761 | } |
@@ -1710,36 +1771,44 @@ static void dispc_disable_isr(void *data, u32 mask) | |||
1710 | complete(compl); | 1771 | complete(compl); |
1711 | } | 1772 | } |
1712 | 1773 | ||
1713 | static void _enable_lcd_out(bool enable) | 1774 | static void _enable_lcd_out(enum omap_channel channel, bool enable) |
1714 | { | 1775 | { |
1715 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); | 1776 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
1777 | REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0); | ||
1778 | else | ||
1779 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); | ||
1716 | } | 1780 | } |
1717 | 1781 | ||
1718 | static void dispc_enable_lcd_out(bool enable) | 1782 | static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) |
1719 | { | 1783 | { |
1720 | struct completion frame_done_completion; | 1784 | struct completion frame_done_completion; |
1721 | bool is_on; | 1785 | bool is_on; |
1722 | int r; | 1786 | int r; |
1787 | u32 irq; | ||
1723 | 1788 | ||
1724 | enable_clocks(1); | 1789 | enable_clocks(1); |
1725 | 1790 | ||
1726 | /* When we disable LCD output, we need to wait until frame is done. | 1791 | /* When we disable LCD output, we need to wait until frame is done. |
1727 | * Otherwise the DSS is still working, and turning off the clocks | 1792 | * Otherwise the DSS is still working, and turning off the clocks |
1728 | * prevents DSS from going to OFF mode */ | 1793 | * prevents DSS from going to OFF mode */ |
1729 | is_on = REG_GET(DISPC_CONTROL, 0, 0); | 1794 | is_on = channel == OMAP_DSS_CHANNEL_LCD2 ? |
1795 | REG_GET(DISPC_CONTROL2, 0, 0) : | ||
1796 | REG_GET(DISPC_CONTROL, 0, 0); | ||
1797 | |||
1798 | irq = channel == OMAP_DSS_CHANNEL_LCD2 ? DISPC_IRQ_FRAMEDONE2 : | ||
1799 | DISPC_IRQ_FRAMEDONE; | ||
1730 | 1800 | ||
1731 | if (!enable && is_on) { | 1801 | if (!enable && is_on) { |
1732 | init_completion(&frame_done_completion); | 1802 | init_completion(&frame_done_completion); |
1733 | 1803 | ||
1734 | r = omap_dispc_register_isr(dispc_disable_isr, | 1804 | r = omap_dispc_register_isr(dispc_disable_isr, |
1735 | &frame_done_completion, | 1805 | &frame_done_completion, irq); |
1736 | DISPC_IRQ_FRAMEDONE); | ||
1737 | 1806 | ||
1738 | if (r) | 1807 | if (r) |
1739 | DSSERR("failed to register FRAMEDONE isr\n"); | 1808 | DSSERR("failed to register FRAMEDONE isr\n"); |
1740 | } | 1809 | } |
1741 | 1810 | ||
1742 | _enable_lcd_out(enable); | 1811 | _enable_lcd_out(channel, enable); |
1743 | 1812 | ||
1744 | if (!enable && is_on) { | 1813 | if (!enable && is_on) { |
1745 | if (!wait_for_completion_timeout(&frame_done_completion, | 1814 | if (!wait_for_completion_timeout(&frame_done_completion, |
@@ -1747,8 +1816,7 @@ static void dispc_enable_lcd_out(bool enable) | |||
1747 | DSSERR("timeout waiting for FRAME DONE\n"); | 1816 | DSSERR("timeout waiting for FRAME DONE\n"); |
1748 | 1817 | ||
1749 | r = omap_dispc_unregister_isr(dispc_disable_isr, | 1818 | r = omap_dispc_unregister_isr(dispc_disable_isr, |
1750 | &frame_done_completion, | 1819 | &frame_done_completion, irq); |
1751 | DISPC_IRQ_FRAMEDONE); | ||
1752 | 1820 | ||
1753 | if (r) | 1821 | if (r) |
1754 | DSSERR("failed to unregister FRAMEDONE isr\n"); | 1822 | DSSERR("failed to unregister FRAMEDONE isr\n"); |
@@ -1818,6 +1886,8 @@ static void dispc_enable_digit_out(bool enable) | |||
1818 | unsigned long flags; | 1886 | unsigned long flags; |
1819 | spin_lock_irqsave(&dispc.irq_lock, flags); | 1887 | spin_lock_irqsave(&dispc.irq_lock, flags); |
1820 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 1888 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; |
1889 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
1890 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
1821 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 1891 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); |
1822 | _omap_dispc_set_irqs(); | 1892 | _omap_dispc_set_irqs(); |
1823 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 1893 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
@@ -1832,14 +1902,17 @@ bool dispc_is_channel_enabled(enum omap_channel channel) | |||
1832 | return !!REG_GET(DISPC_CONTROL, 0, 0); | 1902 | return !!REG_GET(DISPC_CONTROL, 0, 0); |
1833 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | 1903 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) |
1834 | return !!REG_GET(DISPC_CONTROL, 1, 1); | 1904 | return !!REG_GET(DISPC_CONTROL, 1, 1); |
1905 | else if (channel == OMAP_DSS_CHANNEL_LCD2) | ||
1906 | return !!REG_GET(DISPC_CONTROL2, 0, 0); | ||
1835 | else | 1907 | else |
1836 | BUG(); | 1908 | BUG(); |
1837 | } | 1909 | } |
1838 | 1910 | ||
1839 | void dispc_enable_channel(enum omap_channel channel, bool enable) | 1911 | void dispc_enable_channel(enum omap_channel channel, bool enable) |
1840 | { | 1912 | { |
1841 | if (channel == OMAP_DSS_CHANNEL_LCD) | 1913 | if (channel == OMAP_DSS_CHANNEL_LCD || |
1842 | dispc_enable_lcd_out(enable); | 1914 | channel == OMAP_DSS_CHANNEL_LCD2) |
1915 | dispc_enable_lcd_out(channel, enable); | ||
1843 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | 1916 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) |
1844 | dispc_enable_digit_out(enable); | 1917 | dispc_enable_digit_out(enable); |
1845 | else | 1918 | else |
@@ -1848,6 +1921,9 @@ void dispc_enable_channel(enum omap_channel channel, bool enable) | |||
1848 | 1921 | ||
1849 | void dispc_lcd_enable_signal_polarity(bool act_high) | 1922 | void dispc_lcd_enable_signal_polarity(bool act_high) |
1850 | { | 1923 | { |
1924 | if (!dss_has_feature(FEAT_LCDENABLEPOL)) | ||
1925 | return; | ||
1926 | |||
1851 | enable_clocks(1); | 1927 | enable_clocks(1); |
1852 | REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); | 1928 | REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); |
1853 | enable_clocks(0); | 1929 | enable_clocks(0); |
@@ -1855,6 +1931,9 @@ void dispc_lcd_enable_signal_polarity(bool act_high) | |||
1855 | 1931 | ||
1856 | void dispc_lcd_enable_signal(bool enable) | 1932 | void dispc_lcd_enable_signal(bool enable) |
1857 | { | 1933 | { |
1934 | if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) | ||
1935 | return; | ||
1936 | |||
1858 | enable_clocks(1); | 1937 | enable_clocks(1); |
1859 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); | 1938 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); |
1860 | enable_clocks(0); | 1939 | enable_clocks(0); |
@@ -1862,20 +1941,27 @@ void dispc_lcd_enable_signal(bool enable) | |||
1862 | 1941 | ||
1863 | void dispc_pck_free_enable(bool enable) | 1942 | void dispc_pck_free_enable(bool enable) |
1864 | { | 1943 | { |
1944 | if (!dss_has_feature(FEAT_PCKFREEENABLE)) | ||
1945 | return; | ||
1946 | |||
1865 | enable_clocks(1); | 1947 | enable_clocks(1); |
1866 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); | 1948 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); |
1867 | enable_clocks(0); | 1949 | enable_clocks(0); |
1868 | } | 1950 | } |
1869 | 1951 | ||
1870 | void dispc_enable_fifohandcheck(bool enable) | 1952 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) |
1871 | { | 1953 | { |
1872 | enable_clocks(1); | 1954 | enable_clocks(1); |
1873 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); | 1955 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
1956 | REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); | ||
1957 | else | ||
1958 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); | ||
1874 | enable_clocks(0); | 1959 | enable_clocks(0); |
1875 | } | 1960 | } |
1876 | 1961 | ||
1877 | 1962 | ||
1878 | void dispc_set_lcd_display_type(enum omap_lcd_display_type type) | 1963 | void dispc_set_lcd_display_type(enum omap_channel channel, |
1964 | enum omap_lcd_display_type type) | ||
1879 | { | 1965 | { |
1880 | int mode; | 1966 | int mode; |
1881 | 1967 | ||
@@ -1894,7 +1980,10 @@ void dispc_set_lcd_display_type(enum omap_lcd_display_type type) | |||
1894 | } | 1980 | } |
1895 | 1981 | ||
1896 | enable_clocks(1); | 1982 | enable_clocks(1); |
1897 | REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); | 1983 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
1984 | REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3); | ||
1985 | else | ||
1986 | REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); | ||
1898 | enable_clocks(0); | 1987 | enable_clocks(0); |
1899 | } | 1988 | } |
1900 | 1989 | ||
@@ -1908,25 +1997,21 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode) | |||
1908 | 1997 | ||
1909 | void dispc_set_default_color(enum omap_channel channel, u32 color) | 1998 | void dispc_set_default_color(enum omap_channel channel, u32 color) |
1910 | { | 1999 | { |
1911 | const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, | ||
1912 | DISPC_DEFAULT_COLOR1 }; | ||
1913 | |||
1914 | enable_clocks(1); | 2000 | enable_clocks(1); |
1915 | dispc_write_reg(def_reg[channel], color); | 2001 | dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); |
1916 | enable_clocks(0); | 2002 | enable_clocks(0); |
1917 | } | 2003 | } |
1918 | 2004 | ||
1919 | u32 dispc_get_default_color(enum omap_channel channel) | 2005 | u32 dispc_get_default_color(enum omap_channel channel) |
1920 | { | 2006 | { |
1921 | const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, | ||
1922 | DISPC_DEFAULT_COLOR1 }; | ||
1923 | u32 l; | 2007 | u32 l; |
1924 | 2008 | ||
1925 | BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && | 2009 | BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && |
1926 | channel != OMAP_DSS_CHANNEL_LCD); | 2010 | channel != OMAP_DSS_CHANNEL_LCD && |
2011 | channel != OMAP_DSS_CHANNEL_LCD2); | ||
1927 | 2012 | ||
1928 | enable_clocks(1); | 2013 | enable_clocks(1); |
1929 | l = dispc_read_reg(def_reg[channel]); | 2014 | l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); |
1930 | enable_clocks(0); | 2015 | enable_clocks(0); |
1931 | 2016 | ||
1932 | return l; | 2017 | return l; |
@@ -1936,16 +2021,15 @@ void dispc_set_trans_key(enum omap_channel ch, | |||
1936 | enum omap_dss_trans_key_type type, | 2021 | enum omap_dss_trans_key_type type, |
1937 | u32 trans_key) | 2022 | u32 trans_key) |
1938 | { | 2023 | { |
1939 | const struct dispc_reg tr_reg[] = { | ||
1940 | DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; | ||
1941 | |||
1942 | enable_clocks(1); | 2024 | enable_clocks(1); |
1943 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2025 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1944 | REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); | 2026 | REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); |
1945 | else /* OMAP_DSS_CHANNEL_DIGIT */ | 2027 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
1946 | REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); | 2028 | REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); |
2029 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2030 | REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11); | ||
1947 | 2031 | ||
1948 | dispc_write_reg(tr_reg[ch], trans_key); | 2032 | dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); |
1949 | enable_clocks(0); | 2033 | enable_clocks(0); |
1950 | } | 2034 | } |
1951 | 2035 | ||
@@ -1953,21 +2037,20 @@ void dispc_get_trans_key(enum omap_channel ch, | |||
1953 | enum omap_dss_trans_key_type *type, | 2037 | enum omap_dss_trans_key_type *type, |
1954 | u32 *trans_key) | 2038 | u32 *trans_key) |
1955 | { | 2039 | { |
1956 | const struct dispc_reg tr_reg[] = { | ||
1957 | DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; | ||
1958 | |||
1959 | enable_clocks(1); | 2040 | enable_clocks(1); |
1960 | if (type) { | 2041 | if (type) { |
1961 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2042 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1962 | *type = REG_GET(DISPC_CONFIG, 11, 11); | 2043 | *type = REG_GET(DISPC_CONFIG, 11, 11); |
1963 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2044 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
1964 | *type = REG_GET(DISPC_CONFIG, 13, 13); | 2045 | *type = REG_GET(DISPC_CONFIG, 13, 13); |
2046 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2047 | *type = REG_GET(DISPC_CONFIG2, 11, 11); | ||
1965 | else | 2048 | else |
1966 | BUG(); | 2049 | BUG(); |
1967 | } | 2050 | } |
1968 | 2051 | ||
1969 | if (trans_key) | 2052 | if (trans_key) |
1970 | *trans_key = dispc_read_reg(tr_reg[ch]); | 2053 | *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); |
1971 | enable_clocks(0); | 2054 | enable_clocks(0); |
1972 | } | 2055 | } |
1973 | 2056 | ||
@@ -1976,8 +2059,10 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable) | |||
1976 | enable_clocks(1); | 2059 | enable_clocks(1); |
1977 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2060 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1978 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); | 2061 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); |
1979 | else /* OMAP_DSS_CHANNEL_DIGIT */ | 2062 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
1980 | REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); | 2063 | REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); |
2064 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2065 | REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); | ||
1981 | enable_clocks(0); | 2066 | enable_clocks(0); |
1982 | } | 2067 | } |
1983 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) | 2068 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) |
@@ -1988,8 +2073,10 @@ void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) | |||
1988 | enable_clocks(1); | 2073 | enable_clocks(1); |
1989 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2074 | if (ch == OMAP_DSS_CHANNEL_LCD) |
1990 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); | 2075 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); |
1991 | else /* OMAP_DSS_CHANNEL_DIGIT */ | 2076 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
1992 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); | 2077 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); |
2078 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
2079 | REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); | ||
1993 | enable_clocks(0); | 2080 | enable_clocks(0); |
1994 | } | 2081 | } |
1995 | bool dispc_alpha_blending_enabled(enum omap_channel ch) | 2082 | bool dispc_alpha_blending_enabled(enum omap_channel ch) |
@@ -2003,13 +2090,14 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch) | |||
2003 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2090 | if (ch == OMAP_DSS_CHANNEL_LCD) |
2004 | enabled = REG_GET(DISPC_CONFIG, 18, 18); | 2091 | enabled = REG_GET(DISPC_CONFIG, 18, 18); |
2005 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2092 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2006 | enabled = REG_GET(DISPC_CONFIG, 18, 18); | 2093 | enabled = REG_GET(DISPC_CONFIG, 19, 19); |
2094 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2095 | enabled = REG_GET(DISPC_CONFIG2, 18, 18); | ||
2007 | else | 2096 | else |
2008 | BUG(); | 2097 | BUG(); |
2009 | enable_clocks(0); | 2098 | enable_clocks(0); |
2010 | 2099 | ||
2011 | return enabled; | 2100 | return enabled; |
2012 | |||
2013 | } | 2101 | } |
2014 | 2102 | ||
2015 | 2103 | ||
@@ -2022,6 +2110,8 @@ bool dispc_trans_key_enabled(enum omap_channel ch) | |||
2022 | enabled = REG_GET(DISPC_CONFIG, 10, 10); | 2110 | enabled = REG_GET(DISPC_CONFIG, 10, 10); |
2023 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2111 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
2024 | enabled = REG_GET(DISPC_CONFIG, 12, 12); | 2112 | enabled = REG_GET(DISPC_CONFIG, 12, 12); |
2113 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
2114 | enabled = REG_GET(DISPC_CONFIG2, 10, 10); | ||
2025 | else | 2115 | else |
2026 | BUG(); | 2116 | BUG(); |
2027 | enable_clocks(0); | 2117 | enable_clocks(0); |
@@ -2030,7 +2120,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) | |||
2030 | } | 2120 | } |
2031 | 2121 | ||
2032 | 2122 | ||
2033 | void dispc_set_tft_data_lines(u8 data_lines) | 2123 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) |
2034 | { | 2124 | { |
2035 | int code; | 2125 | int code; |
2036 | 2126 | ||
@@ -2053,11 +2143,15 @@ void dispc_set_tft_data_lines(u8 data_lines) | |||
2053 | } | 2143 | } |
2054 | 2144 | ||
2055 | enable_clocks(1); | 2145 | enable_clocks(1); |
2056 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); | 2146 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
2147 | REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8); | ||
2148 | else | ||
2149 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); | ||
2057 | enable_clocks(0); | 2150 | enable_clocks(0); |
2058 | } | 2151 | } |
2059 | 2152 | ||
2060 | void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) | 2153 | void dispc_set_parallel_interface_mode(enum omap_channel channel, |
2154 | enum omap_parallel_interface_mode mode) | ||
2061 | { | 2155 | { |
2062 | u32 l; | 2156 | u32 l; |
2063 | int stallmode; | 2157 | int stallmode; |
@@ -2087,13 +2181,17 @@ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) | |||
2087 | 2181 | ||
2088 | enable_clocks(1); | 2182 | enable_clocks(1); |
2089 | 2183 | ||
2090 | l = dispc_read_reg(DISPC_CONTROL); | 2184 | if (channel == OMAP_DSS_CHANNEL_LCD2) { |
2091 | 2185 | l = dispc_read_reg(DISPC_CONTROL2); | |
2092 | l = FLD_MOD(l, stallmode, 11, 11); | 2186 | l = FLD_MOD(l, stallmode, 11, 11); |
2093 | l = FLD_MOD(l, gpout0, 15, 15); | 2187 | dispc_write_reg(DISPC_CONTROL2, l); |
2094 | l = FLD_MOD(l, gpout1, 16, 16); | 2188 | } else { |
2095 | 2189 | l = dispc_read_reg(DISPC_CONTROL); | |
2096 | dispc_write_reg(DISPC_CONTROL, l); | 2190 | l = FLD_MOD(l, stallmode, 11, 11); |
2191 | l = FLD_MOD(l, gpout0, 15, 15); | ||
2192 | l = FLD_MOD(l, gpout1, 16, 16); | ||
2193 | dispc_write_reg(DISPC_CONTROL, l); | ||
2194 | } | ||
2097 | 2195 | ||
2098 | enable_clocks(0); | 2196 | enable_clocks(0); |
2099 | } | 2197 | } |
@@ -2129,8 +2227,8 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings) | |||
2129 | timings->vfp, timings->vbp); | 2227 | timings->vfp, timings->vbp); |
2130 | } | 2228 | } |
2131 | 2229 | ||
2132 | static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, | 2230 | static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, |
2133 | int vsw, int vfp, int vbp) | 2231 | int hfp, int hbp, int vsw, int vfp, int vbp) |
2134 | { | 2232 | { |
2135 | u32 timing_h, timing_v; | 2233 | u32 timing_h, timing_v; |
2136 | 2234 | ||
@@ -2149,13 +2247,14 @@ static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, | |||
2149 | } | 2247 | } |
2150 | 2248 | ||
2151 | enable_clocks(1); | 2249 | enable_clocks(1); |
2152 | dispc_write_reg(DISPC_TIMING_H, timing_h); | 2250 | dispc_write_reg(DISPC_TIMING_H(channel), timing_h); |
2153 | dispc_write_reg(DISPC_TIMING_V, timing_v); | 2251 | dispc_write_reg(DISPC_TIMING_V(channel), timing_v); |
2154 | enable_clocks(0); | 2252 | enable_clocks(0); |
2155 | } | 2253 | } |
2156 | 2254 | ||
2157 | /* change name to mode? */ | 2255 | /* change name to mode? */ |
2158 | void dispc_set_lcd_timings(struct omap_video_timings *timings) | 2256 | void dispc_set_lcd_timings(enum omap_channel channel, |
2257 | struct omap_video_timings *timings) | ||
2159 | { | 2258 | { |
2160 | unsigned xtot, ytot; | 2259 | unsigned xtot, ytot; |
2161 | unsigned long ht, vt; | 2260 | unsigned long ht, vt; |
@@ -2165,10 +2264,11 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings) | |||
2165 | timings->vfp, timings->vbp)) | 2264 | timings->vfp, timings->vbp)) |
2166 | BUG(); | 2265 | BUG(); |
2167 | 2266 | ||
2168 | _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, | 2267 | _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp, |
2169 | timings->vsw, timings->vfp, timings->vbp); | 2268 | timings->hbp, timings->vsw, timings->vfp, |
2269 | timings->vbp); | ||
2170 | 2270 | ||
2171 | dispc_set_lcd_size(timings->x_res, timings->y_res); | 2271 | dispc_set_lcd_size(channel, timings->x_res, timings->y_res); |
2172 | 2272 | ||
2173 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; | 2273 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; |
2174 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; | 2274 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; |
@@ -2176,7 +2276,8 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings) | |||
2176 | ht = (timings->pixel_clock * 1000) / xtot; | 2276 | ht = (timings->pixel_clock * 1000) / xtot; |
2177 | vt = (timings->pixel_clock * 1000) / xtot / ytot; | 2277 | vt = (timings->pixel_clock * 1000) / xtot / ytot; |
2178 | 2278 | ||
2179 | DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); | 2279 | DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, |
2280 | timings->y_res); | ||
2180 | DSSDBG("pck %u\n", timings->pixel_clock); | 2281 | DSSDBG("pck %u\n", timings->pixel_clock); |
2181 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", | 2282 | DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", |
2182 | timings->hsw, timings->hfp, timings->hbp, | 2283 | timings->hsw, timings->hfp, timings->hbp, |
@@ -2185,21 +2286,23 @@ void dispc_set_lcd_timings(struct omap_video_timings *timings) | |||
2185 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); | 2286 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); |
2186 | } | 2287 | } |
2187 | 2288 | ||
2188 | static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) | 2289 | static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, |
2290 | u16 pck_div) | ||
2189 | { | 2291 | { |
2190 | BUG_ON(lck_div < 1); | 2292 | BUG_ON(lck_div < 1); |
2191 | BUG_ON(pck_div < 2); | 2293 | BUG_ON(pck_div < 2); |
2192 | 2294 | ||
2193 | enable_clocks(1); | 2295 | enable_clocks(1); |
2194 | dispc_write_reg(DISPC_DIVISOR, | 2296 | dispc_write_reg(DISPC_DIVISOR(channel), |
2195 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2297 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
2196 | enable_clocks(0); | 2298 | enable_clocks(0); |
2197 | } | 2299 | } |
2198 | 2300 | ||
2199 | static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) | 2301 | static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, |
2302 | int *pck_div) | ||
2200 | { | 2303 | { |
2201 | u32 l; | 2304 | u32 l; |
2202 | l = dispc_read_reg(DISPC_DIVISOR); | 2305 | l = dispc_read_reg(DISPC_DIVISOR(channel)); |
2203 | *lck_div = FLD_GET(l, 23, 16); | 2306 | *lck_div = FLD_GET(l, 23, 16); |
2204 | *pck_div = FLD_GET(l, 7, 0); | 2307 | *pck_div = FLD_GET(l, 7, 0); |
2205 | } | 2308 | } |
@@ -2219,13 +2322,13 @@ unsigned long dispc_fclk_rate(void) | |||
2219 | return r; | 2322 | return r; |
2220 | } | 2323 | } |
2221 | 2324 | ||
2222 | unsigned long dispc_lclk_rate(void) | 2325 | unsigned long dispc_lclk_rate(enum omap_channel channel) |
2223 | { | 2326 | { |
2224 | int lcd; | 2327 | int lcd; |
2225 | unsigned long r; | 2328 | unsigned long r; |
2226 | u32 l; | 2329 | u32 l; |
2227 | 2330 | ||
2228 | l = dispc_read_reg(DISPC_DIVISOR); | 2331 | l = dispc_read_reg(DISPC_DIVISOR(channel)); |
2229 | 2332 | ||
2230 | lcd = FLD_GET(l, 23, 16); | 2333 | lcd = FLD_GET(l, 23, 16); |
2231 | 2334 | ||
@@ -2234,13 +2337,13 @@ unsigned long dispc_lclk_rate(void) | |||
2234 | return r / lcd; | 2337 | return r / lcd; |
2235 | } | 2338 | } |
2236 | 2339 | ||
2237 | unsigned long dispc_pclk_rate(void) | 2340 | unsigned long dispc_pclk_rate(enum omap_channel channel) |
2238 | { | 2341 | { |
2239 | int lcd, pcd; | 2342 | int lcd, pcd; |
2240 | unsigned long r; | 2343 | unsigned long r; |
2241 | u32 l; | 2344 | u32 l; |
2242 | 2345 | ||
2243 | l = dispc_read_reg(DISPC_DIVISOR); | 2346 | l = dispc_read_reg(DISPC_DIVISOR(channel)); |
2244 | 2347 | ||
2245 | lcd = FLD_GET(l, 23, 16); | 2348 | lcd = FLD_GET(l, 23, 16); |
2246 | pcd = FLD_GET(l, 7, 0); | 2349 | pcd = FLD_GET(l, 7, 0); |
@@ -2256,8 +2359,6 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2256 | 2359 | ||
2257 | enable_clocks(1); | 2360 | enable_clocks(1); |
2258 | 2361 | ||
2259 | dispc_get_lcd_divisor(&lcd, &pcd); | ||
2260 | |||
2261 | seq_printf(s, "- DISPC -\n"); | 2362 | seq_printf(s, "- DISPC -\n"); |
2262 | 2363 | ||
2263 | seq_printf(s, "dispc fclk source = %s\n", | 2364 | seq_printf(s, "dispc fclk source = %s\n", |
@@ -2265,9 +2366,25 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2265 | "dss1_alwon_fclk" : "dsi1_pll_fclk"); | 2366 | "dss1_alwon_fclk" : "dsi1_pll_fclk"); |
2266 | 2367 | ||
2267 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); | 2368 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); |
2268 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd); | ||
2269 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd); | ||
2270 | 2369 | ||
2370 | seq_printf(s, "- LCD1 -\n"); | ||
2371 | |||
2372 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); | ||
2373 | |||
2374 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2375 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); | ||
2376 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | ||
2377 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); | ||
2378 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
2379 | seq_printf(s, "- LCD2 -\n"); | ||
2380 | |||
2381 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); | ||
2382 | |||
2383 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2384 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); | ||
2385 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | ||
2386 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); | ||
2387 | } | ||
2271 | enable_clocks(0); | 2388 | enable_clocks(0); |
2272 | } | 2389 | } |
2273 | 2390 | ||
@@ -2309,6 +2426,12 @@ void dispc_dump_irqs(struct seq_file *s) | |||
2309 | PIS(SYNC_LOST); | 2426 | PIS(SYNC_LOST); |
2310 | PIS(SYNC_LOST_DIGIT); | 2427 | PIS(SYNC_LOST_DIGIT); |
2311 | PIS(WAKEUP); | 2428 | PIS(WAKEUP); |
2429 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
2430 | PIS(FRAMEDONE2); | ||
2431 | PIS(VSYNC2); | ||
2432 | PIS(ACBIAS_COUNT_STAT2); | ||
2433 | PIS(SYNC_LOST2); | ||
2434 | } | ||
2312 | #undef PIS | 2435 | #undef PIS |
2313 | } | 2436 | } |
2314 | #endif | 2437 | #endif |
@@ -2327,19 +2450,30 @@ void dispc_dump_regs(struct seq_file *s) | |||
2327 | DUMPREG(DISPC_CONTROL); | 2450 | DUMPREG(DISPC_CONTROL); |
2328 | DUMPREG(DISPC_CONFIG); | 2451 | DUMPREG(DISPC_CONFIG); |
2329 | DUMPREG(DISPC_CAPABLE); | 2452 | DUMPREG(DISPC_CAPABLE); |
2330 | DUMPREG(DISPC_DEFAULT_COLOR0); | 2453 | DUMPREG(DISPC_DEFAULT_COLOR(0)); |
2331 | DUMPREG(DISPC_DEFAULT_COLOR1); | 2454 | DUMPREG(DISPC_DEFAULT_COLOR(1)); |
2332 | DUMPREG(DISPC_TRANS_COLOR0); | 2455 | DUMPREG(DISPC_TRANS_COLOR(0)); |
2333 | DUMPREG(DISPC_TRANS_COLOR1); | 2456 | DUMPREG(DISPC_TRANS_COLOR(1)); |
2334 | DUMPREG(DISPC_LINE_STATUS); | 2457 | DUMPREG(DISPC_LINE_STATUS); |
2335 | DUMPREG(DISPC_LINE_NUMBER); | 2458 | DUMPREG(DISPC_LINE_NUMBER); |
2336 | DUMPREG(DISPC_TIMING_H); | 2459 | DUMPREG(DISPC_TIMING_H(0)); |
2337 | DUMPREG(DISPC_TIMING_V); | 2460 | DUMPREG(DISPC_TIMING_V(0)); |
2338 | DUMPREG(DISPC_POL_FREQ); | 2461 | DUMPREG(DISPC_POL_FREQ(0)); |
2339 | DUMPREG(DISPC_DIVISOR); | 2462 | DUMPREG(DISPC_DIVISOR(0)); |
2340 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2463 | DUMPREG(DISPC_GLOBAL_ALPHA); |
2341 | DUMPREG(DISPC_SIZE_DIG); | 2464 | DUMPREG(DISPC_SIZE_DIG); |
2342 | DUMPREG(DISPC_SIZE_LCD); | 2465 | DUMPREG(DISPC_SIZE_LCD(0)); |
2466 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
2467 | DUMPREG(DISPC_CONTROL2); | ||
2468 | DUMPREG(DISPC_CONFIG2); | ||
2469 | DUMPREG(DISPC_DEFAULT_COLOR(2)); | ||
2470 | DUMPREG(DISPC_TRANS_COLOR(2)); | ||
2471 | DUMPREG(DISPC_TIMING_H(2)); | ||
2472 | DUMPREG(DISPC_TIMING_V(2)); | ||
2473 | DUMPREG(DISPC_POL_FREQ(2)); | ||
2474 | DUMPREG(DISPC_DIVISOR(2)); | ||
2475 | DUMPREG(DISPC_SIZE_LCD(2)); | ||
2476 | } | ||
2343 | 2477 | ||
2344 | DUMPREG(DISPC_GFX_BA0); | 2478 | DUMPREG(DISPC_GFX_BA0); |
2345 | DUMPREG(DISPC_GFX_BA1); | 2479 | DUMPREG(DISPC_GFX_BA1); |
@@ -2353,13 +2487,22 @@ void dispc_dump_regs(struct seq_file *s) | |||
2353 | DUMPREG(DISPC_GFX_WINDOW_SKIP); | 2487 | DUMPREG(DISPC_GFX_WINDOW_SKIP); |
2354 | DUMPREG(DISPC_GFX_TABLE_BA); | 2488 | DUMPREG(DISPC_GFX_TABLE_BA); |
2355 | 2489 | ||
2356 | DUMPREG(DISPC_DATA_CYCLE1); | 2490 | DUMPREG(DISPC_DATA_CYCLE1(0)); |
2357 | DUMPREG(DISPC_DATA_CYCLE2); | 2491 | DUMPREG(DISPC_DATA_CYCLE2(0)); |
2358 | DUMPREG(DISPC_DATA_CYCLE3); | 2492 | DUMPREG(DISPC_DATA_CYCLE3(0)); |
2359 | 2493 | ||
2360 | DUMPREG(DISPC_CPR_COEF_R); | 2494 | DUMPREG(DISPC_CPR_COEF_R(0)); |
2361 | DUMPREG(DISPC_CPR_COEF_G); | 2495 | DUMPREG(DISPC_CPR_COEF_G(0)); |
2362 | DUMPREG(DISPC_CPR_COEF_B); | 2496 | DUMPREG(DISPC_CPR_COEF_B(0)); |
2497 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
2498 | DUMPREG(DISPC_DATA_CYCLE1(2)); | ||
2499 | DUMPREG(DISPC_DATA_CYCLE2(2)); | ||
2500 | DUMPREG(DISPC_DATA_CYCLE3(2)); | ||
2501 | |||
2502 | DUMPREG(DISPC_CPR_COEF_R(2)); | ||
2503 | DUMPREG(DISPC_CPR_COEF_G(2)); | ||
2504 | DUMPREG(DISPC_CPR_COEF_B(2)); | ||
2505 | } | ||
2363 | 2506 | ||
2364 | DUMPREG(DISPC_GFX_PRELOAD); | 2507 | DUMPREG(DISPC_GFX_PRELOAD); |
2365 | 2508 | ||
@@ -2458,8 +2601,8 @@ void dispc_dump_regs(struct seq_file *s) | |||
2458 | #undef DUMPREG | 2601 | #undef DUMPREG |
2459 | } | 2602 | } |
2460 | 2603 | ||
2461 | static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, | 2604 | static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, |
2462 | bool ihs, bool ivs, u8 acbi, u8 acb) | 2605 | bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb) |
2463 | { | 2606 | { |
2464 | u32 l = 0; | 2607 | u32 l = 0; |
2465 | 2608 | ||
@@ -2476,13 +2619,14 @@ static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, | |||
2476 | l |= FLD_VAL(acb, 7, 0); | 2619 | l |= FLD_VAL(acb, 7, 0); |
2477 | 2620 | ||
2478 | enable_clocks(1); | 2621 | enable_clocks(1); |
2479 | dispc_write_reg(DISPC_POL_FREQ, l); | 2622 | dispc_write_reg(DISPC_POL_FREQ(channel), l); |
2480 | enable_clocks(0); | 2623 | enable_clocks(0); |
2481 | } | 2624 | } |
2482 | 2625 | ||
2483 | void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) | 2626 | void dispc_set_pol_freq(enum omap_channel channel, |
2627 | enum omap_panel_config config, u8 acbi, u8 acb) | ||
2484 | { | 2628 | { |
2485 | _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, | 2629 | _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, |
2486 | (config & OMAP_DSS_LCD_RF) != 0, | 2630 | (config & OMAP_DSS_LCD_RF) != 0, |
2487 | (config & OMAP_DSS_LCD_IEO) != 0, | 2631 | (config & OMAP_DSS_LCD_IEO) != 0, |
2488 | (config & OMAP_DSS_LCD_IPC) != 0, | 2632 | (config & OMAP_DSS_LCD_IPC) != 0, |
@@ -2551,24 +2695,26 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
2551 | return 0; | 2695 | return 0; |
2552 | } | 2696 | } |
2553 | 2697 | ||
2554 | int dispc_set_clock_div(struct dispc_clock_info *cinfo) | 2698 | int dispc_set_clock_div(enum omap_channel channel, |
2699 | struct dispc_clock_info *cinfo) | ||
2555 | { | 2700 | { |
2556 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); | 2701 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); |
2557 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); | 2702 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); |
2558 | 2703 | ||
2559 | dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); | 2704 | dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); |
2560 | 2705 | ||
2561 | return 0; | 2706 | return 0; |
2562 | } | 2707 | } |
2563 | 2708 | ||
2564 | int dispc_get_clock_div(struct dispc_clock_info *cinfo) | 2709 | int dispc_get_clock_div(enum omap_channel channel, |
2710 | struct dispc_clock_info *cinfo) | ||
2565 | { | 2711 | { |
2566 | unsigned long fck; | 2712 | unsigned long fck; |
2567 | 2713 | ||
2568 | fck = dispc_fclk_rate(); | 2714 | fck = dispc_fclk_rate(); |
2569 | 2715 | ||
2570 | cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); | 2716 | cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16); |
2571 | cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); | 2717 | cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0); |
2572 | 2718 | ||
2573 | cinfo->lck = fck / cinfo->lck_div; | 2719 | cinfo->lck = fck / cinfo->lck_div; |
2574 | cinfo->pck = cinfo->lck / cinfo->pck_div; | 2720 | cinfo->pck = cinfo->lck / cinfo->pck_div; |
@@ -2708,6 +2854,8 @@ static void print_irq_status(u32 status) | |||
2708 | PIS(VID2_FIFO_UNDERFLOW); | 2854 | PIS(VID2_FIFO_UNDERFLOW); |
2709 | PIS(SYNC_LOST); | 2855 | PIS(SYNC_LOST); |
2710 | PIS(SYNC_LOST_DIGIT); | 2856 | PIS(SYNC_LOST_DIGIT); |
2857 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
2858 | PIS(SYNC_LOST2); | ||
2711 | #undef PIS | 2859 | #undef PIS |
2712 | 2860 | ||
2713 | printk("\n"); | 2861 | printk("\n"); |
@@ -2926,6 +3074,45 @@ static void dispc_error_worker(struct work_struct *work) | |||
2926 | } | 3074 | } |
2927 | } | 3075 | } |
2928 | 3076 | ||
3077 | if (errors & DISPC_IRQ_SYNC_LOST2) { | ||
3078 | struct omap_overlay_manager *manager = NULL; | ||
3079 | bool enable = false; | ||
3080 | |||
3081 | DSSERR("SYNC_LOST for LCD2, disabling LCD2\n"); | ||
3082 | |||
3083 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | ||
3084 | struct omap_overlay_manager *mgr; | ||
3085 | mgr = omap_dss_get_overlay_manager(i); | ||
3086 | |||
3087 | if (mgr->id == OMAP_DSS_CHANNEL_LCD2) { | ||
3088 | manager = mgr; | ||
3089 | enable = mgr->device->state == | ||
3090 | OMAP_DSS_DISPLAY_ACTIVE; | ||
3091 | mgr->device->driver->disable(mgr->device); | ||
3092 | break; | ||
3093 | } | ||
3094 | } | ||
3095 | |||
3096 | if (manager) { | ||
3097 | struct omap_dss_device *dssdev = manager->device; | ||
3098 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
3099 | struct omap_overlay *ovl; | ||
3100 | ovl = omap_dss_get_overlay(i); | ||
3101 | |||
3102 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
3103 | continue; | ||
3104 | |||
3105 | if (ovl->id != 0 && ovl->manager == manager) | ||
3106 | dispc_enable_plane(ovl->id, 0); | ||
3107 | } | ||
3108 | |||
3109 | dispc_go(manager->id); | ||
3110 | mdelay(50); | ||
3111 | if (enable) | ||
3112 | dssdev->driver->enable(dssdev); | ||
3113 | } | ||
3114 | } | ||
3115 | |||
2929 | if (errors & DISPC_IRQ_OCP_ERR) { | 3116 | if (errors & DISPC_IRQ_OCP_ERR) { |
2930 | DSSERR("OCP_ERR\n"); | 3117 | DSSERR("OCP_ERR\n"); |
2931 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3118 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
@@ -3033,6 +3220,8 @@ static void _omap_dispc_initialize_irq(void) | |||
3033 | memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); | 3220 | memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); |
3034 | 3221 | ||
3035 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 3222 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; |
3223 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
3224 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
3036 | 3225 | ||
3037 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, | 3226 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, |
3038 | * so clear it */ | 3227 | * so clear it */ |
@@ -3065,7 +3254,8 @@ static void _omap_dispc_initial_config(void) | |||
3065 | dispc_write_reg(DISPC_SYSCONFIG, l); | 3254 | dispc_write_reg(DISPC_SYSCONFIG, l); |
3066 | 3255 | ||
3067 | /* FUNCGATED */ | 3256 | /* FUNCGATED */ |
3068 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); | 3257 | if (dss_has_feature(FEAT_FUNCGATED)) |
3258 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); | ||
3069 | 3259 | ||
3070 | /* L3 firewall setting: enable access to OCM RAM */ | 3260 | /* L3 firewall setting: enable access to OCM RAM */ |
3071 | /* XXX this should be somewhere in plat-omap */ | 3261 | /* XXX this should be somewhere in plat-omap */ |
@@ -3139,17 +3329,18 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3139 | enum omap_color_mode color_mode, | 3329 | enum omap_color_mode color_mode, |
3140 | bool ilace, | 3330 | bool ilace, |
3141 | enum omap_dss_rotation_type rotation_type, | 3331 | enum omap_dss_rotation_type rotation_type, |
3142 | u8 rotation, bool mirror, u8 global_alpha) | 3332 | u8 rotation, bool mirror, u8 global_alpha, |
3333 | u8 pre_mult_alpha, enum omap_channel channel) | ||
3143 | { | 3334 | { |
3144 | int r = 0; | 3335 | int r = 0; |
3145 | 3336 | ||
3146 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " | 3337 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " |
3147 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", | 3338 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", |
3148 | plane, paddr, screen_width, pos_x, pos_y, | 3339 | plane, paddr, screen_width, pos_x, pos_y, |
3149 | width, height, | 3340 | width, height, |
3150 | out_width, out_height, | 3341 | out_width, out_height, |
3151 | ilace, color_mode, | 3342 | ilace, color_mode, |
3152 | rotation, mirror); | 3343 | rotation, mirror, channel); |
3153 | 3344 | ||
3154 | enable_clocks(1); | 3345 | enable_clocks(1); |
3155 | 3346 | ||
@@ -3161,7 +3352,8 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3161 | color_mode, ilace, | 3352 | color_mode, ilace, |
3162 | rotation_type, | 3353 | rotation_type, |
3163 | rotation, mirror, | 3354 | rotation, mirror, |
3164 | global_alpha); | 3355 | global_alpha, |
3356 | pre_mult_alpha, channel); | ||
3165 | 3357 | ||
3166 | enable_clocks(0); | 3358 | enable_clocks(0); |
3167 | 3359 | ||
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 960e977a8bf0..75fb0a515430 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -40,8 +40,9 @@ static struct { | |||
40 | } dpi; | 40 | } dpi; |
41 | 41 | ||
42 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 42 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
43 | static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, | 43 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, |
44 | unsigned long *fck, int *lck_div, int *pck_div) | 44 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
45 | int *pck_div) | ||
45 | { | 46 | { |
46 | struct dsi_clock_info dsi_cinfo; | 47 | struct dsi_clock_info dsi_cinfo; |
47 | struct dispc_clock_info dispc_cinfo; | 48 | struct dispc_clock_info dispc_cinfo; |
@@ -58,7 +59,7 @@ static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, | |||
58 | 59 | ||
59 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 60 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); |
60 | 61 | ||
61 | r = dispc_set_clock_div(&dispc_cinfo); | 62 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
62 | if (r) | 63 | if (r) |
63 | return r; | 64 | return r; |
64 | 65 | ||
@@ -69,8 +70,9 @@ static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, | |||
69 | return 0; | 70 | return 0; |
70 | } | 71 | } |
71 | #else | 72 | #else |
72 | static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | 73 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, |
73 | unsigned long *fck, int *lck_div, int *pck_div) | 74 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
75 | int *pck_div) | ||
74 | { | 76 | { |
75 | struct dss_clock_info dss_cinfo; | 77 | struct dss_clock_info dss_cinfo; |
76 | struct dispc_clock_info dispc_cinfo; | 78 | struct dispc_clock_info dispc_cinfo; |
@@ -84,7 +86,7 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | |||
84 | if (r) | 86 | if (r) |
85 | return r; | 87 | return r; |
86 | 88 | ||
87 | r = dispc_set_clock_div(&dispc_cinfo); | 89 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
88 | if (r) | 90 | if (r) |
89 | return r; | 91 | return r; |
90 | 92 | ||
@@ -107,17 +109,17 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
107 | 109 | ||
108 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 110 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); |
109 | 111 | ||
110 | dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, | 112 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
111 | dssdev->panel.acb); | 113 | dssdev->panel.acbi, dssdev->panel.acb); |
112 | 114 | ||
113 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 115 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
114 | 116 | ||
115 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 117 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
116 | r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, | 118 | r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, |
117 | &fck, &lck_div, &pck_div); | 119 | &lck_div, &pck_div); |
118 | #else | 120 | #else |
119 | r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, | 121 | r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck, |
120 | &fck, &lck_div, &pck_div); | 122 | &lck_div, &pck_div); |
121 | #endif | 123 | #endif |
122 | if (r) | 124 | if (r) |
123 | goto err0; | 125 | goto err0; |
@@ -132,7 +134,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
132 | t->pixel_clock = pck; | 134 | t->pixel_clock = pck; |
133 | } | 135 | } |
134 | 136 | ||
135 | dispc_set_lcd_timings(t); | 137 | dispc_set_lcd_timings(dssdev->manager->id, t); |
136 | 138 | ||
137 | err0: | 139 | err0: |
138 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 140 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); |
@@ -145,10 +147,12 @@ static int dpi_basic_init(struct omap_dss_device *dssdev) | |||
145 | 147 | ||
146 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 148 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
147 | 149 | ||
148 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); | 150 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
149 | dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : | 151 | OMAP_DSS_PARALLELMODE_BYPASS); |
150 | OMAP_DSS_LCD_DISPLAY_STN); | 152 | dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? |
151 | dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); | 153 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); |
154 | dispc_set_tft_data_lines(dssdev->manager->id, | ||
155 | dssdev->phy.dpi.data_lines); | ||
152 | 156 | ||
153 | return 0; | 157 | return 0; |
154 | } | 158 | } |
@@ -234,7 +238,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev, | |||
234 | dssdev->panel.timings = *timings; | 238 | dssdev->panel.timings = *timings; |
235 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | 239 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
236 | dpi_set_mode(dssdev); | 240 | dpi_set_mode(dssdev); |
237 | dispc_go(OMAP_DSS_CHANNEL_LCD); | 241 | dispc_go(dssdev->manager->id); |
238 | } | 242 | } |
239 | } | 243 | } |
240 | EXPORT_SYMBOL(dpi_set_timings); | 244 | EXPORT_SYMBOL(dpi_set_timings); |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index aa4f7a5fae29..ddf3a0560822 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -792,7 +792,8 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
792 | } | 792 | } |
793 | 793 | ||
794 | /* calculate clock rates using dividers in cinfo */ | 794 | /* calculate clock rates using dividers in cinfo */ |
795 | static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) | 795 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, |
796 | struct dsi_clock_info *cinfo) | ||
796 | { | 797 | { |
797 | if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) | 798 | if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) |
798 | return -EINVAL; | 799 | return -EINVAL; |
@@ -812,7 +813,7 @@ static int dsi_calc_clock_rates(struct dsi_clock_info *cinfo) | |||
812 | * with DSS2_FCK source also */ | 813 | * with DSS2_FCK source also */ |
813 | cinfo->highfreq = 0; | 814 | cinfo->highfreq = 0; |
814 | } else { | 815 | } else { |
815 | cinfo->clkin = dispc_pclk_rate(); | 816 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); |
816 | 817 | ||
817 | if (cinfo->clkin < 32000000) | 818 | if (cinfo->clkin < 32000000) |
818 | cinfo->highfreq = 0; | 819 | cinfo->highfreq = 0; |
@@ -1206,8 +1207,8 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1206 | 1207 | ||
1207 | seq_printf(s, "VP_CLK\t\t%lu\n" | 1208 | seq_printf(s, "VP_CLK\t\t%lu\n" |
1208 | "VP_PCLK\t\t%lu\n", | 1209 | "VP_PCLK\t\t%lu\n", |
1209 | dispc_lclk_rate(), | 1210 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), |
1210 | dispc_pclk_rate()); | 1211 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD)); |
1211 | 1212 | ||
1212 | enable_clocks(0); | 1213 | enable_clocks(0); |
1213 | } | 1214 | } |
@@ -2888,7 +2889,7 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | |||
2888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 2889 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
2889 | dss_setup_partial_planes(dssdev, x, y, w, h, | 2890 | dss_setup_partial_planes(dssdev, x, y, w, h, |
2890 | enlarge_update_area); | 2891 | enlarge_update_area); |
2891 | dispc_set_lcd_size(*w, *h); | 2892 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); |
2892 | } | 2893 | } |
2893 | 2894 | ||
2894 | return 0; | 2895 | return 0; |
@@ -2947,12 +2948,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
2947 | return r; | 2948 | return r; |
2948 | } | 2949 | } |
2949 | 2950 | ||
2950 | dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); | 2951 | dispc_set_lcd_display_type(dssdev->manager->id, |
2952 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
2951 | 2953 | ||
2952 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI); | 2954 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
2953 | dispc_enable_fifohandcheck(1); | 2955 | OMAP_DSS_PARALLELMODE_DSI); |
2956 | dispc_enable_fifohandcheck(dssdev->manager->id, 1); | ||
2954 | 2957 | ||
2955 | dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); | 2958 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); |
2956 | 2959 | ||
2957 | { | 2960 | { |
2958 | struct omap_video_timings timings = { | 2961 | struct omap_video_timings timings = { |
@@ -2964,7 +2967,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
2964 | .vbp = 0, | 2967 | .vbp = 0, |
2965 | }; | 2968 | }; |
2966 | 2969 | ||
2967 | dispc_set_lcd_timings(&timings); | 2970 | dispc_set_lcd_timings(dssdev->manager->id, &timings); |
2968 | } | 2971 | } |
2969 | 2972 | ||
2970 | return 0; | 2973 | return 0; |
@@ -2987,7 +2990,7 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
2987 | cinfo.regm = dssdev->phy.dsi.div.regm; | 2990 | cinfo.regm = dssdev->phy.dsi.div.regm; |
2988 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; | 2991 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; |
2989 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; | 2992 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; |
2990 | r = dsi_calc_clock_rates(&cinfo); | 2993 | r = dsi_calc_clock_rates(dssdev, &cinfo); |
2991 | if (r) { | 2994 | if (r) { |
2992 | DSSERR("Failed to calc dsi clocks\n"); | 2995 | DSSERR("Failed to calc dsi clocks\n"); |
2993 | return r; | 2996 | return r; |
@@ -3019,7 +3022,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3019 | return r; | 3022 | return r; |
3020 | } | 3023 | } |
3021 | 3024 | ||
3022 | r = dispc_set_clock_div(&dispc_cinfo); | 3025 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
3023 | if (r) { | 3026 | if (r) { |
3024 | DSSERR("Failed to set dispc clocks\n"); | 3027 | DSSERR("Failed to set dispc clocks\n"); |
3025 | return r; | 3028 | return r; |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 5c7940d5f282..b394951120ac 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -333,9 +333,9 @@ void dispc_disable_sidle(void); | |||
333 | void dispc_lcd_enable_signal_polarity(bool act_high); | 333 | void dispc_lcd_enable_signal_polarity(bool act_high); |
334 | void dispc_lcd_enable_signal(bool enable); | 334 | void dispc_lcd_enable_signal(bool enable); |
335 | void dispc_pck_free_enable(bool enable); | 335 | void dispc_pck_free_enable(bool enable); |
336 | void dispc_enable_fifohandcheck(bool enable); | 336 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable); |
337 | 337 | ||
338 | void dispc_set_lcd_size(u16 width, u16 height); | 338 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height); |
339 | void dispc_set_digit_size(u16 width, u16 height); | 339 | void dispc_set_digit_size(u16 width, u16 height); |
340 | u32 dispc_get_plane_fifo_size(enum omap_plane plane); | 340 | u32 dispc_get_plane_fifo_size(enum omap_plane plane); |
341 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); | 341 | void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); |
@@ -359,7 +359,8 @@ int dispc_setup_plane(enum omap_plane plane, | |||
359 | bool ilace, | 359 | bool ilace, |
360 | enum omap_dss_rotation_type rotation_type, | 360 | enum omap_dss_rotation_type rotation_type, |
361 | u8 rotation, bool mirror, | 361 | u8 rotation, bool mirror, |
362 | u8 global_alpha); | 362 | u8 global_alpha, u8 pre_mult_alpha, |
363 | enum omap_channel channel); | ||
363 | 364 | ||
364 | bool dispc_go_busy(enum omap_channel channel); | 365 | bool dispc_go_busy(enum omap_channel channel); |
365 | void dispc_go(enum omap_channel channel); | 366 | void dispc_go(enum omap_channel channel); |
@@ -368,9 +369,11 @@ bool dispc_is_channel_enabled(enum omap_channel channel); | |||
368 | int dispc_enable_plane(enum omap_plane plane, bool enable); | 369 | int dispc_enable_plane(enum omap_plane plane, bool enable); |
369 | void dispc_enable_replication(enum omap_plane plane, bool enable); | 370 | void dispc_enable_replication(enum omap_plane plane, bool enable); |
370 | 371 | ||
371 | void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode); | 372 | void dispc_set_parallel_interface_mode(enum omap_channel channel, |
372 | void dispc_set_tft_data_lines(u8 data_lines); | 373 | enum omap_parallel_interface_mode mode); |
373 | void dispc_set_lcd_display_type(enum omap_lcd_display_type type); | 374 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines); |
375 | void dispc_set_lcd_display_type(enum omap_channel channel, | ||
376 | enum omap_lcd_display_type type); | ||
374 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 377 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
375 | 378 | ||
376 | void dispc_set_default_color(enum omap_channel channel, u32 color); | 379 | void dispc_set_default_color(enum omap_channel channel, u32 color); |
@@ -387,17 +390,21 @@ bool dispc_trans_key_enabled(enum omap_channel ch); | |||
387 | bool dispc_alpha_blending_enabled(enum omap_channel ch); | 390 | bool dispc_alpha_blending_enabled(enum omap_channel ch); |
388 | 391 | ||
389 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); | 392 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); |
390 | void dispc_set_lcd_timings(struct omap_video_timings *timings); | 393 | void dispc_set_lcd_timings(enum omap_channel channel, |
394 | struct omap_video_timings *timings); | ||
391 | unsigned long dispc_fclk_rate(void); | 395 | unsigned long dispc_fclk_rate(void); |
392 | unsigned long dispc_lclk_rate(void); | 396 | unsigned long dispc_lclk_rate(enum omap_channel channel); |
393 | unsigned long dispc_pclk_rate(void); | 397 | unsigned long dispc_pclk_rate(enum omap_channel channel); |
394 | void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb); | 398 | void dispc_set_pol_freq(enum omap_channel channel, |
399 | enum omap_panel_config config, u8 acbi, u8 acb); | ||
395 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 400 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
396 | struct dispc_clock_info *cinfo); | 401 | struct dispc_clock_info *cinfo); |
397 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 402 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, |
398 | struct dispc_clock_info *cinfo); | 403 | struct dispc_clock_info *cinfo); |
399 | int dispc_set_clock_div(struct dispc_clock_info *cinfo); | 404 | int dispc_set_clock_div(enum omap_channel channel, |
400 | int dispc_get_clock_div(struct dispc_clock_info *cinfo); | 405 | struct dispc_clock_info *cinfo); |
406 | int dispc_get_clock_div(enum omap_channel channel, | ||
407 | struct dispc_clock_info *cinfo); | ||
401 | 408 | ||
402 | 409 | ||
403 | /* VENC */ | 410 | /* VENC */ |
@@ -424,8 +431,8 @@ void rfbi_dump_regs(struct seq_file *s); | |||
424 | 431 | ||
425 | int rfbi_configure(int rfbi_module, int bpp, int lines); | 432 | int rfbi_configure(int rfbi_module, int bpp, int lines); |
426 | void rfbi_enable_rfbi(bool enable); | 433 | void rfbi_enable_rfbi(bool enable); |
427 | void rfbi_transfer_area(u16 width, u16 height, | 434 | void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, |
428 | void (callback)(void *data), void *data); | 435 | u16 height, void (callback)(void *data), void *data); |
429 | void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); | 436 | void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); |
430 | unsigned long rfbi_get_max_tx_rate(void); | 437 | unsigned long rfbi_get_max_tx_rate(void); |
431 | int rfbi_init_display(struct omap_dss_device *display); | 438 | int rfbi_init_display(struct omap_dss_device *display); |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 867f68de125f..cf3ef696e141 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -82,6 +82,18 @@ static const enum omap_display_type omap3_dss_supported_displays[] = { | |||
82 | OMAP_DISPLAY_TYPE_VENC, | 82 | OMAP_DISPLAY_TYPE_VENC, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static const enum omap_display_type omap4_dss_supported_displays[] = { | ||
86 | /* OMAP_DSS_CHANNEL_LCD */ | ||
87 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, | ||
88 | |||
89 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
90 | OMAP_DISPLAY_TYPE_VENC, | ||
91 | |||
92 | /* OMAP_DSS_CHANNEL_LCD2 */ | ||
93 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | ||
94 | OMAP_DISPLAY_TYPE_DSI, | ||
95 | }; | ||
96 | |||
85 | static const enum omap_color_mode omap2_dss_supported_color_modes[] = { | 97 | static const enum omap_color_mode omap2_dss_supported_color_modes[] = { |
86 | /* OMAP_DSS_GFX */ | 98 | /* OMAP_DSS_GFX */ |
87 | OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | | 99 | OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | |
@@ -127,6 +139,10 @@ static struct omap_dss_features omap2_dss_features = { | |||
127 | .reg_fields = omap2_dss_reg_fields, | 139 | .reg_fields = omap2_dss_reg_fields, |
128 | .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), | 140 | .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), |
129 | 141 | ||
142 | .has_feature = | ||
143 | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | | ||
144 | FEAT_PCKFREEENABLE | FEAT_FUNCGATED, | ||
145 | |||
130 | .num_mgrs = 2, | 146 | .num_mgrs = 2, |
131 | .num_ovls = 3, | 147 | .num_ovls = 3, |
132 | .supported_displays = omap2_dss_supported_displays, | 148 | .supported_displays = omap2_dss_supported_displays, |
@@ -134,11 +150,29 @@ static struct omap_dss_features omap2_dss_features = { | |||
134 | }; | 150 | }; |
135 | 151 | ||
136 | /* OMAP3 DSS Features */ | 152 | /* OMAP3 DSS Features */ |
137 | static struct omap_dss_features omap3_dss_features = { | 153 | static struct omap_dss_features omap3430_dss_features = { |
154 | .reg_fields = omap3_dss_reg_fields, | ||
155 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | ||
156 | |||
157 | .has_feature = | ||
158 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | ||
159 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | ||
160 | FEAT_FUNCGATED, | ||
161 | |||
162 | .num_mgrs = 2, | ||
163 | .num_ovls = 3, | ||
164 | .supported_displays = omap3_dss_supported_displays, | ||
165 | .supported_color_modes = omap3_dss_supported_color_modes, | ||
166 | }; | ||
167 | |||
168 | static struct omap_dss_features omap3630_dss_features = { | ||
138 | .reg_fields = omap3_dss_reg_fields, | 169 | .reg_fields = omap3_dss_reg_fields, |
139 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 170 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
140 | 171 | ||
141 | .has_feature = FEAT_GLOBAL_ALPHA, | 172 | .has_feature = |
173 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | ||
174 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | ||
175 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED, | ||
142 | 176 | ||
143 | .num_mgrs = 2, | 177 | .num_mgrs = 2, |
144 | .num_ovls = 3, | 178 | .num_ovls = 3, |
@@ -146,6 +180,21 @@ static struct omap_dss_features omap3_dss_features = { | |||
146 | .supported_color_modes = omap3_dss_supported_color_modes, | 180 | .supported_color_modes = omap3_dss_supported_color_modes, |
147 | }; | 181 | }; |
148 | 182 | ||
183 | /* OMAP4 DSS Features */ | ||
184 | static struct omap_dss_features omap4_dss_features = { | ||
185 | .reg_fields = omap3_dss_reg_fields, | ||
186 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | ||
187 | |||
188 | .has_feature = | ||
189 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | ||
190 | FEAT_MGR_LCD2, | ||
191 | |||
192 | .num_mgrs = 3, | ||
193 | .num_ovls = 3, | ||
194 | .supported_displays = omap4_dss_supported_displays, | ||
195 | .supported_color_modes = omap3_dss_supported_color_modes, | ||
196 | }; | ||
197 | |||
149 | /* Functions returning values related to a DSS feature */ | 198 | /* Functions returning values related to a DSS feature */ |
150 | int dss_feat_get_num_mgrs(void) | 199 | int dss_feat_get_num_mgrs(void) |
151 | { | 200 | { |
@@ -167,6 +216,13 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) | |||
167 | return omap_current_dss_features->supported_color_modes[plane]; | 216 | return omap_current_dss_features->supported_color_modes[plane]; |
168 | } | 217 | } |
169 | 218 | ||
219 | bool dss_feat_color_mode_supported(enum omap_plane plane, | ||
220 | enum omap_color_mode color_mode) | ||
221 | { | ||
222 | return omap_current_dss_features->supported_color_modes[plane] & | ||
223 | color_mode; | ||
224 | } | ||
225 | |||
170 | /* DSS has_feature check */ | 226 | /* DSS has_feature check */ |
171 | bool dss_has_feature(enum dss_feat_id id) | 227 | bool dss_has_feature(enum dss_feat_id id) |
172 | { | 228 | { |
@@ -186,6 +242,10 @@ void dss_features_init(void) | |||
186 | { | 242 | { |
187 | if (cpu_is_omap24xx()) | 243 | if (cpu_is_omap24xx()) |
188 | omap_current_dss_features = &omap2_dss_features; | 244 | omap_current_dss_features = &omap2_dss_features; |
245 | else if (cpu_is_omap3630()) | ||
246 | omap_current_dss_features = &omap3630_dss_features; | ||
247 | else if (cpu_is_omap34xx()) | ||
248 | omap_current_dss_features = &omap3430_dss_features; | ||
189 | else | 249 | else |
190 | omap_current_dss_features = &omap3_dss_features; | 250 | omap_current_dss_features = &omap4_dss_features; |
191 | } | 251 | } |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index cb231eaa9b31..b9c70be92588 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -20,13 +20,19 @@ | |||
20 | #ifndef __OMAP2_DSS_FEATURES_H | 20 | #ifndef __OMAP2_DSS_FEATURES_H |
21 | #define __OMAP2_DSS_FEATURES_H | 21 | #define __OMAP2_DSS_FEATURES_H |
22 | 22 | ||
23 | #define MAX_DSS_MANAGERS 2 | 23 | #define MAX_DSS_MANAGERS 3 |
24 | #define MAX_DSS_OVERLAYS 3 | 24 | #define MAX_DSS_OVERLAYS 3 |
25 | 25 | ||
26 | /* DSS has feature id */ | 26 | /* DSS has feature id */ |
27 | enum dss_feat_id { | 27 | enum dss_feat_id { |
28 | FEAT_GLOBAL_ALPHA = 1 << 0, | 28 | FEAT_GLOBAL_ALPHA = 1 << 0, |
29 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, | 29 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, |
30 | FEAT_PRE_MULT_ALPHA = 1 << 2, | ||
31 | FEAT_LCDENABLEPOL = 1 << 3, | ||
32 | FEAT_LCDENABLESIGNAL = 1 << 4, | ||
33 | FEAT_PCKFREEENABLE = 1 << 5, | ||
34 | FEAT_FUNCGATED = 1 << 6, | ||
35 | FEAT_MGR_LCD2 = 1 << 7, | ||
30 | }; | 36 | }; |
31 | 37 | ||
32 | /* DSS register field id */ | 38 | /* DSS register field id */ |
@@ -43,6 +49,8 @@ int dss_feat_get_num_mgrs(void); | |||
43 | int dss_feat_get_num_ovls(void); | 49 | int dss_feat_get_num_ovls(void); |
44 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | 50 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); |
45 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 51 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
52 | bool dss_feat_color_mode_supported(enum omap_plane plane, | ||
53 | enum omap_color_mode color_mode); | ||
46 | 54 | ||
47 | bool dss_has_feature(enum dss_feat_id id); | 55 | bool dss_has_feature(enum dss_feat_id id); |
48 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 56 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 545e9b9a4d92..172d4e697309 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -406,6 +406,7 @@ struct overlay_cache_data { | |||
406 | u16 out_width; /* if 0, out_width == width */ | 406 | u16 out_width; /* if 0, out_width == width */ |
407 | u16 out_height; /* if 0, out_height == height */ | 407 | u16 out_height; /* if 0, out_height == height */ |
408 | u8 global_alpha; | 408 | u8 global_alpha; |
409 | u8 pre_mult_alpha; | ||
409 | 410 | ||
410 | enum omap_channel channel; | 411 | enum omap_channel channel; |
411 | bool replication; | 412 | bool replication; |
@@ -512,11 +513,14 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | |||
512 | unsigned long timeout = msecs_to_jiffies(500); | 513 | unsigned long timeout = msecs_to_jiffies(500); |
513 | u32 irq; | 514 | u32 irq; |
514 | 515 | ||
515 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) | 516 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { |
516 | irq = DISPC_IRQ_EVSYNC_ODD; | 517 | irq = DISPC_IRQ_EVSYNC_ODD; |
517 | else | 518 | } else { |
518 | irq = DISPC_IRQ_VSYNC; | 519 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) |
519 | 520 | irq = DISPC_IRQ_VSYNC; | |
521 | else | ||
522 | irq = DISPC_IRQ_VSYNC2; | ||
523 | } | ||
520 | return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); | 524 | return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); |
521 | } | 525 | } |
522 | 526 | ||
@@ -524,7 +528,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
524 | { | 528 | { |
525 | unsigned long timeout = msecs_to_jiffies(500); | 529 | unsigned long timeout = msecs_to_jiffies(500); |
526 | struct manager_cache_data *mc; | 530 | struct manager_cache_data *mc; |
527 | enum omap_channel channel; | ||
528 | u32 irq; | 531 | u32 irq; |
529 | int r; | 532 | int r; |
530 | int i; | 533 | int i; |
@@ -535,7 +538,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
535 | 538 | ||
536 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 539 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { |
537 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 540 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
538 | channel = OMAP_DSS_CHANNEL_DIGIT; | ||
539 | } else { | 541 | } else { |
540 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 542 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
541 | enum omap_dss_update_mode mode; | 543 | enum omap_dss_update_mode mode; |
@@ -543,11 +545,14 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
543 | if (mode != OMAP_DSS_UPDATE_AUTO) | 545 | if (mode != OMAP_DSS_UPDATE_AUTO) |
544 | return 0; | 546 | return 0; |
545 | 547 | ||
546 | irq = DISPC_IRQ_FRAMEDONE; | 548 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
549 | DISPC_IRQ_FRAMEDONE | ||
550 | : DISPC_IRQ_FRAMEDONE2; | ||
547 | } else { | 551 | } else { |
548 | irq = DISPC_IRQ_VSYNC; | 552 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
553 | DISPC_IRQ_VSYNC | ||
554 | : DISPC_IRQ_VSYNC2; | ||
549 | } | 555 | } |
550 | channel = OMAP_DSS_CHANNEL_LCD; | ||
551 | } | 556 | } |
552 | 557 | ||
553 | mc = &dss_cache.manager_cache[mgr->id]; | 558 | mc = &dss_cache.manager_cache[mgr->id]; |
@@ -594,7 +599,6 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
594 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | 599 | int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) |
595 | { | 600 | { |
596 | unsigned long timeout = msecs_to_jiffies(500); | 601 | unsigned long timeout = msecs_to_jiffies(500); |
597 | enum omap_channel channel; | ||
598 | struct overlay_cache_data *oc; | 602 | struct overlay_cache_data *oc; |
599 | struct omap_dss_device *dssdev; | 603 | struct omap_dss_device *dssdev; |
600 | u32 irq; | 604 | u32 irq; |
@@ -611,7 +615,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
611 | 615 | ||
612 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 616 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { |
613 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 617 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
614 | channel = OMAP_DSS_CHANNEL_DIGIT; | ||
615 | } else { | 618 | } else { |
616 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 619 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
617 | enum omap_dss_update_mode mode; | 620 | enum omap_dss_update_mode mode; |
@@ -619,11 +622,14 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
619 | if (mode != OMAP_DSS_UPDATE_AUTO) | 622 | if (mode != OMAP_DSS_UPDATE_AUTO) |
620 | return 0; | 623 | return 0; |
621 | 624 | ||
622 | irq = DISPC_IRQ_FRAMEDONE; | 625 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
626 | DISPC_IRQ_FRAMEDONE | ||
627 | : DISPC_IRQ_FRAMEDONE2; | ||
623 | } else { | 628 | } else { |
624 | irq = DISPC_IRQ_VSYNC; | 629 | irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? |
630 | DISPC_IRQ_VSYNC | ||
631 | : DISPC_IRQ_VSYNC2; | ||
625 | } | 632 | } |
626 | channel = OMAP_DSS_CHANNEL_LCD; | ||
627 | } | 633 | } |
628 | 634 | ||
629 | oc = &dss_cache.overlay_cache[ovl->id]; | 635 | oc = &dss_cache.overlay_cache[ovl->id]; |
@@ -842,7 +848,9 @@ static int configure_overlay(enum omap_plane plane) | |||
842 | c->rotation_type, | 848 | c->rotation_type, |
843 | c->rotation, | 849 | c->rotation, |
844 | c->mirror, | 850 | c->mirror, |
845 | c->global_alpha); | 851 | c->global_alpha, |
852 | c->pre_mult_alpha, | ||
853 | c->channel); | ||
846 | 854 | ||
847 | if (r) { | 855 | if (r) { |
848 | /* this shouldn't happen */ | 856 | /* this shouldn't happen */ |
@@ -894,10 +902,10 @@ static int configure_dispc(void) | |||
894 | r = 0; | 902 | r = 0; |
895 | busy = false; | 903 | busy = false; |
896 | 904 | ||
897 | mgr_busy[0] = dispc_go_busy(0); | 905 | for (i = 0; i < num_mgrs; i++) { |
898 | mgr_busy[1] = dispc_go_busy(1); | 906 | mgr_busy[i] = dispc_go_busy(i); |
899 | mgr_go[0] = false; | 907 | mgr_go[i] = false; |
900 | mgr_go[1] = false; | 908 | } |
901 | 909 | ||
902 | /* Commit overlay settings */ | 910 | /* Commit overlay settings */ |
903 | for (i = 0; i < num_ovls; ++i) { | 911 | for (i = 0; i < num_ovls; ++i) { |
@@ -1156,9 +1164,10 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1156 | const int num_mgrs = dss_feat_get_num_mgrs(); | 1164 | const int num_mgrs = dss_feat_get_num_mgrs(); |
1157 | int i, r; | 1165 | int i, r; |
1158 | bool mgr_busy[MAX_DSS_MANAGERS]; | 1166 | bool mgr_busy[MAX_DSS_MANAGERS]; |
1167 | u32 irq_mask; | ||
1159 | 1168 | ||
1160 | mgr_busy[0] = dispc_go_busy(0); | 1169 | for (i = 0; i < num_mgrs; i++) |
1161 | mgr_busy[1] = dispc_go_busy(1); | 1170 | mgr_busy[i] = dispc_go_busy(i); |
1162 | 1171 | ||
1163 | spin_lock(&dss_cache.lock); | 1172 | spin_lock(&dss_cache.lock); |
1164 | 1173 | ||
@@ -1179,8 +1188,8 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1179 | goto end; | 1188 | goto end; |
1180 | 1189 | ||
1181 | /* re-read busy flags */ | 1190 | /* re-read busy flags */ |
1182 | mgr_busy[0] = dispc_go_busy(0); | 1191 | for (i = 0; i < num_mgrs; i++) |
1183 | mgr_busy[1] = dispc_go_busy(1); | 1192 | mgr_busy[i] = dispc_go_busy(i); |
1184 | 1193 | ||
1185 | /* keep running as long as there are busy managers, so that | 1194 | /* keep running as long as there are busy managers, so that |
1186 | * we can collect overlay-applied information */ | 1195 | * we can collect overlay-applied information */ |
@@ -1189,9 +1198,12 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
1189 | goto end; | 1198 | goto end; |
1190 | } | 1199 | } |
1191 | 1200 | ||
1192 | omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, | 1201 | irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | |
1193 | DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | | 1202 | DISPC_IRQ_EVSYNC_EVEN; |
1194 | DISPC_IRQ_EVSYNC_EVEN); | 1203 | if (dss_has_feature(FEAT_MGR_LCD2)) |
1204 | irq_mask |= DISPC_IRQ_VSYNC2; | ||
1205 | |||
1206 | omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask); | ||
1195 | dss_cache.irq_enabled = false; | 1207 | dss_cache.irq_enabled = false; |
1196 | 1208 | ||
1197 | end: | 1209 | end: |
@@ -1265,6 +1277,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1265 | oc->out_width = ovl->info.out_width; | 1277 | oc->out_width = ovl->info.out_width; |
1266 | oc->out_height = ovl->info.out_height; | 1278 | oc->out_height = ovl->info.out_height; |
1267 | oc->global_alpha = ovl->info.global_alpha; | 1279 | oc->global_alpha = ovl->info.global_alpha; |
1280 | oc->pre_mult_alpha = ovl->info.pre_mult_alpha; | ||
1268 | 1281 | ||
1269 | oc->replication = | 1282 | oc->replication = |
1270 | dss_use_replication(dssdev, ovl->info.color_mode); | 1283 | dss_use_replication(dssdev, ovl->info.color_mode); |
@@ -1383,9 +1396,14 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1383 | r = 0; | 1396 | r = 0; |
1384 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1397 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); |
1385 | if (!dss_cache.irq_enabled) { | 1398 | if (!dss_cache.irq_enabled) { |
1386 | r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, | 1399 | u32 mask; |
1387 | DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | | 1400 | |
1388 | DISPC_IRQ_EVSYNC_EVEN); | 1401 | mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | |
1402 | DISPC_IRQ_EVSYNC_EVEN; | ||
1403 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
1404 | mask |= DISPC_IRQ_VSYNC2; | ||
1405 | |||
1406 | r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); | ||
1389 | dss_cache.irq_enabled = true; | 1407 | dss_cache.irq_enabled = true; |
1390 | } | 1408 | } |
1391 | configure_dispc(); | 1409 | configure_dispc(); |
@@ -1477,6 +1495,10 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
1477 | mgr->name = "tv"; | 1495 | mgr->name = "tv"; |
1478 | mgr->id = OMAP_DSS_CHANNEL_DIGIT; | 1496 | mgr->id = OMAP_DSS_CHANNEL_DIGIT; |
1479 | break; | 1497 | break; |
1498 | case 2: | ||
1499 | mgr->name = "lcd2"; | ||
1500 | mgr->id = OMAP_DSS_CHANNEL_LCD2; | ||
1501 | break; | ||
1480 | } | 1502 | } |
1481 | 1503 | ||
1482 | mgr->set_device = &omap_dss_set_device; | 1504 | mgr->set_device = &omap_dss_set_device; |
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 75642c22cac7..456efef03c20 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -257,6 +257,43 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
257 | return size; | 257 | return size; |
258 | } | 258 | } |
259 | 259 | ||
260 | static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl, | ||
261 | char *buf) | ||
262 | { | ||
263 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
264 | ovl->info.pre_mult_alpha); | ||
265 | } | ||
266 | |||
267 | static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | ||
268 | const char *buf, size_t size) | ||
269 | { | ||
270 | int r; | ||
271 | struct omap_overlay_info info; | ||
272 | |||
273 | ovl->get_overlay_info(ovl, &info); | ||
274 | |||
275 | /* only GFX and Video2 plane support pre alpha multiplied | ||
276 | * set zero for Video1 plane | ||
277 | */ | ||
278 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
279 | ovl->id == OMAP_DSS_VIDEO1) | ||
280 | info.pre_mult_alpha = 0; | ||
281 | else | ||
282 | info.pre_mult_alpha = simple_strtoul(buf, NULL, 10); | ||
283 | |||
284 | r = ovl->set_overlay_info(ovl, &info); | ||
285 | if (r) | ||
286 | return r; | ||
287 | |||
288 | if (ovl->manager) { | ||
289 | r = ovl->manager->apply(ovl->manager); | ||
290 | if (r) | ||
291 | return r; | ||
292 | } | ||
293 | |||
294 | return size; | ||
295 | } | ||
296 | |||
260 | struct overlay_attribute { | 297 | struct overlay_attribute { |
261 | struct attribute attr; | 298 | struct attribute attr; |
262 | ssize_t (*show)(struct omap_overlay *, char *); | 299 | ssize_t (*show)(struct omap_overlay *, char *); |
@@ -280,6 +317,9 @@ static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, | |||
280 | overlay_enabled_show, overlay_enabled_store); | 317 | overlay_enabled_show, overlay_enabled_store); |
281 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | 318 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, |
282 | overlay_global_alpha_show, overlay_global_alpha_store); | 319 | overlay_global_alpha_show, overlay_global_alpha_store); |
320 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | ||
321 | overlay_pre_mult_alpha_show, | ||
322 | overlay_pre_mult_alpha_store); | ||
283 | 323 | ||
284 | static struct attribute *overlay_sysfs_attrs[] = { | 324 | static struct attribute *overlay_sysfs_attrs[] = { |
285 | &overlay_attr_name.attr, | 325 | &overlay_attr_name.attr, |
@@ -290,6 +330,7 @@ static struct attribute *overlay_sysfs_attrs[] = { | |||
290 | &overlay_attr_output_size.attr, | 330 | &overlay_attr_output_size.attr, |
291 | &overlay_attr_enabled.attr, | 331 | &overlay_attr_enabled.attr, |
292 | &overlay_attr_global_alpha.attr, | 332 | &overlay_attr_global_alpha.attr, |
333 | &overlay_attr_pre_mult_alpha.attr, | ||
293 | NULL | 334 | NULL |
294 | }; | 335 | }; |
295 | 336 | ||
@@ -623,12 +664,22 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
623 | int i; | 664 | int i; |
624 | struct omap_overlay_manager *lcd_mgr; | 665 | struct omap_overlay_manager *lcd_mgr; |
625 | struct omap_overlay_manager *tv_mgr; | 666 | struct omap_overlay_manager *tv_mgr; |
667 | struct omap_overlay_manager *lcd2_mgr = NULL; | ||
626 | struct omap_overlay_manager *mgr = NULL; | 668 | struct omap_overlay_manager *mgr = NULL; |
627 | 669 | ||
628 | lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); | 670 | lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); |
629 | tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); | 671 | tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); |
630 | 672 | if (dss_has_feature(FEAT_MGR_LCD2)) | |
631 | if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { | 673 | lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2); |
674 | |||
675 | if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) { | ||
676 | if (!lcd2_mgr->device || force) { | ||
677 | if (lcd2_mgr->device) | ||
678 | lcd2_mgr->unset_device(lcd2_mgr); | ||
679 | lcd2_mgr->set_device(lcd2_mgr, dssdev); | ||
680 | mgr = lcd2_mgr; | ||
681 | } | ||
682 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { | ||
632 | if (!lcd_mgr->device || force) { | 683 | if (!lcd_mgr->device || force) { |
633 | if (lcd_mgr->device) | 684 | if (lcd_mgr->device) |
634 | lcd_mgr->unset_device(lcd_mgr); | 685 | lcd_mgr->unset_device(lcd_mgr); |
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index bbe62464e92d..10a2ffe02882 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -301,8 +301,8 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, | |||
301 | } | 301 | } |
302 | EXPORT_SYMBOL(omap_rfbi_write_pixels); | 302 | EXPORT_SYMBOL(omap_rfbi_write_pixels); |
303 | 303 | ||
304 | void rfbi_transfer_area(u16 width, u16 height, | 304 | void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, |
305 | void (callback)(void *data), void *data) | 305 | u16 height, void (*callback)(void *data), void *data) |
306 | { | 306 | { |
307 | u32 l; | 307 | u32 l; |
308 | 308 | ||
@@ -311,9 +311,9 @@ void rfbi_transfer_area(u16 width, u16 height, | |||
311 | 311 | ||
312 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); | 312 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); |
313 | 313 | ||
314 | dispc_set_lcd_size(width, height); | 314 | dispc_set_lcd_size(dssdev->manager->id, width, height); |
315 | 315 | ||
316 | dispc_enable_channel(OMAP_DSS_CHANNEL_LCD, true); | 316 | dispc_enable_channel(dssdev->manager->id, true); |
317 | 317 | ||
318 | rfbi.framedone_callback = callback; | 318 | rfbi.framedone_callback = callback; |
319 | rfbi.framedone_callback_data = data; | 319 | rfbi.framedone_callback_data = data; |
@@ -887,7 +887,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
887 | 887 | ||
888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 888 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
889 | dss_setup_partial_planes(dssdev, x, y, w, h, true); | 889 | dss_setup_partial_planes(dssdev, x, y, w, h, true); |
890 | dispc_set_lcd_size(*w, *h); | 890 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); |
891 | } | 891 | } |
892 | 892 | ||
893 | return 0; | 893 | return 0; |
@@ -899,7 +899,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev, | |||
899 | void (*callback)(void *), void *data) | 899 | void (*callback)(void *), void *data) |
900 | { | 900 | { |
901 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 901 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { |
902 | rfbi_transfer_area(w, h, callback, data); | 902 | rfbi_transfer_area(dssdev, w, h, callback, data); |
903 | } else { | 903 | } else { |
904 | struct omap_overlay *ovl; | 904 | struct omap_overlay *ovl; |
905 | void __iomem *addr; | 905 | void __iomem *addr; |
@@ -1018,11 +1018,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
1018 | goto err1; | 1018 | goto err1; |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); | 1021 | dispc_set_lcd_display_type(dssdev->manager->id, |
1022 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
1022 | 1023 | ||
1023 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); | 1024 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
1025 | OMAP_DSS_PARALLELMODE_RFBI); | ||
1024 | 1026 | ||
1025 | dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); | 1027 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); |
1026 | 1028 | ||
1027 | rfbi_configure(dssdev->phy.rfbi.channel, | 1029 | rfbi_configure(dssdev->phy.rfbi.channel, |
1028 | dssdev->ctrl.pixel_size, | 1030 | dssdev->ctrl.pixel_size, |
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index ee07a3cc22ef..b64adf7dfc88 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -35,12 +35,16 @@ static struct { | |||
35 | struct regulator *vdds_sdi_reg; | 35 | struct regulator *vdds_sdi_reg; |
36 | } sdi; | 36 | } sdi; |
37 | 37 | ||
38 | static void sdi_basic_init(void) | 38 | static void sdi_basic_init(struct omap_dss_device *dssdev) |
39 | |||
39 | { | 40 | { |
40 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); | 41 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
42 | OMAP_DSS_PARALLELMODE_BYPASS); | ||
43 | |||
44 | dispc_set_lcd_display_type(dssdev->manager->id, | ||
45 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
41 | 46 | ||
42 | dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); | 47 | dispc_set_tft_data_lines(dssdev->manager->id, 24); |
43 | dispc_set_tft_data_lines(24); | ||
44 | dispc_lcd_enable_signal_polarity(1); | 48 | dispc_lcd_enable_signal_polarity(1); |
45 | } | 49 | } |
46 | 50 | ||
@@ -68,20 +72,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
68 | if (!sdi.skip_init) | 72 | if (!sdi.skip_init) |
69 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 73 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); |
70 | 74 | ||
71 | sdi_basic_init(); | 75 | sdi_basic_init(dssdev); |
72 | 76 | ||
73 | /* 15.5.9.1.2 */ | 77 | /* 15.5.9.1.2 */ |
74 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; | 78 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; |
75 | 79 | ||
76 | dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, | 80 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
77 | dssdev->panel.acb); | 81 | dssdev->panel.acbi, dssdev->panel.acb); |
78 | 82 | ||
79 | if (!sdi.skip_init) { | 83 | if (!sdi.skip_init) { |
80 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | 84 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, |
81 | &dss_cinfo, &dispc_cinfo); | 85 | &dss_cinfo, &dispc_cinfo); |
82 | } else { | 86 | } else { |
83 | r = dss_get_clock_div(&dss_cinfo); | 87 | r = dss_get_clock_div(&dss_cinfo); |
84 | r = dispc_get_clock_div(&dispc_cinfo); | 88 | r = dispc_get_clock_div(dssdev->manager->id, &dispc_cinfo); |
85 | } | 89 | } |
86 | 90 | ||
87 | if (r) | 91 | if (r) |
@@ -102,13 +106,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
102 | } | 106 | } |
103 | 107 | ||
104 | 108 | ||
105 | dispc_set_lcd_timings(t); | 109 | dispc_set_lcd_timings(dssdev->manager->id, t); |
106 | 110 | ||
107 | r = dss_set_clock_div(&dss_cinfo); | 111 | r = dss_set_clock_div(&dss_cinfo); |
108 | if (r) | 112 | if (r) |
109 | goto err2; | 113 | goto err2; |
110 | 114 | ||
111 | r = dispc_set_clock_div(&dispc_cinfo); | 115 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
112 | if (r) | 116 | if (r) |
113 | goto err2; | 117 | goto err2; |
114 | 118 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 6a704f176c22..4fdab8e9c496 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -2132,8 +2132,9 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) | |||
2132 | char *str, *options, *this_opt; | 2132 | char *str, *options, *this_opt; |
2133 | int r = 0; | 2133 | int r = 0; |
2134 | 2134 | ||
2135 | str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL); | 2135 | str = kstrdup(def_mode, GFP_KERNEL); |
2136 | strcpy(str, def_mode); | 2136 | if (!str) |
2137 | return -ENOMEM; | ||
2137 | options = str; | 2138 | options = str; |
2138 | 2139 | ||
2139 | while (!r && (this_opt = strsep(&options, ",")) != NULL) { | 2140 | while (!r && (this_opt = strsep(&options, ",")) != NULL) { |
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 618f36bec10d..da388186d617 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
@@ -331,7 +331,7 @@ static int riva_bl_get_brightness(struct backlight_device *bd) | |||
331 | return bd->props.brightness; | 331 | return bd->props.brightness; |
332 | } | 332 | } |
333 | 333 | ||
334 | static struct backlight_ops riva_bl_ops = { | 334 | static const struct backlight_ops riva_bl_ops = { |
335 | .get_brightness = riva_bl_get_brightness, | 335 | .get_brightness = riva_bl_get_brightness, |
336 | .update_status = riva_bl_update_status, | 336 | .update_status = riva_bl_update_status, |
337 | }; | 337 | }; |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 46b430978bcc..61c819e35f7f 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/err.h> | ||
16 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
17 | #include <linux/string.h> | 18 | #include <linux/string.h> |
18 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
@@ -918,9 +919,9 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev, | |||
918 | } | 919 | } |
919 | 920 | ||
920 | info->clk = clk_get(NULL, "lcd"); | 921 | info->clk = clk_get(NULL, "lcd"); |
921 | if (!info->clk || IS_ERR(info->clk)) { | 922 | if (IS_ERR(info->clk)) { |
922 | printk(KERN_ERR "failed to get lcd clock source\n"); | 923 | printk(KERN_ERR "failed to get lcd clock source\n"); |
923 | ret = -ENOENT; | 924 | ret = PTR_ERR(info->clk); |
924 | goto release_irq; | 925 | goto release_irq; |
925 | } | 926 | } |
926 | 927 | ||
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 8c59cc8c5a9c..74d9f546a2e8 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | 26 | #include <sound/soc-dapm.h> |
26 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
27 | 28 | ||
@@ -221,6 +222,7 @@ struct sh_hdmi { | |||
221 | struct delayed_work edid_work; | 222 | struct delayed_work edid_work; |
222 | struct fb_var_screeninfo var; | 223 | struct fb_var_screeninfo var; |
223 | struct fb_monspecs monspec; | 224 | struct fb_monspecs monspec; |
225 | struct notifier_block notifier; | ||
224 | }; | 226 | }; |
225 | 227 | ||
226 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) | 228 | static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) |
@@ -737,7 +739,7 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
737 | struct fb_modelist *modelist = NULL; | 739 | struct fb_modelist *modelist = NULL; |
738 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; | 740 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; |
739 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ | 741 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ |
740 | bool exact_match = false; | 742 | bool scanning = false, preferred_bad = false; |
741 | u8 edid[128]; | 743 | u8 edid[128]; |
742 | char *forced; | 744 | char *forced; |
743 | int i; | 745 | int i; |
@@ -800,6 +802,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
800 | if (i < 2) { | 802 | if (i < 2) { |
801 | f_width = 0; | 803 | f_width = 0; |
802 | f_height = 0; | 804 | f_height = 0; |
805 | } else { | ||
806 | /* The user wants us to use the EDID data */ | ||
807 | scanning = true; | ||
803 | } | 808 | } |
804 | dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", | 809 | dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n", |
805 | f_width, f_height, f_refresh); | 810 | f_width, f_height, f_refresh); |
@@ -807,37 +812,56 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
807 | 812 | ||
808 | /* Walk monitor modes to find the best or the exact match */ | 813 | /* Walk monitor modes to find the best or the exact match */ |
809 | for (i = 0, mode = hdmi->monspec.modedb; | 814 | for (i = 0, mode = hdmi->monspec.modedb; |
810 | f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match; | 815 | i < hdmi->monspec.modedb_len && scanning; |
811 | i++, mode++) { | 816 | i++, mode++) { |
812 | unsigned long rate_error; | 817 | unsigned long rate_error; |
813 | 818 | ||
814 | /* No interest in unmatching modes */ | 819 | if (!f_width && !f_height) { |
815 | if (f_width != mode->xres || f_height != mode->yres) | 820 | /* |
821 | * A parameter string "video=sh_mobile_lcdc:0x0" means | ||
822 | * use the preferred EDID mode. If it is rejected by | ||
823 | * .fb_check_var(), keep looking, until an acceptable | ||
824 | * one is found. | ||
825 | */ | ||
826 | if ((mode->flag & FB_MODE_IS_FIRST) || preferred_bad) | ||
827 | scanning = false; | ||
828 | else | ||
829 | continue; | ||
830 | } else if (f_width != mode->xres || f_height != mode->yres) { | ||
831 | /* No interest in unmatching modes */ | ||
816 | continue; | 832 | continue; |
833 | } | ||
817 | 834 | ||
818 | rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate); | 835 | rate_error = sh_hdmi_rate_error(hdmi, mode, hdmi_rate, parent_rate); |
819 | 836 | ||
820 | if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) | 837 | if (scanning) { |
821 | /* | 838 | if (f_refresh == mode->refresh || (!f_refresh && !rate_error)) |
822 | * Exact match if either the refresh rate matches or it | 839 | /* |
823 | * hasn't been specified and we've found a mode, for | 840 | * Exact match if either the refresh rate |
824 | * which we can configure the clock precisely | 841 | * matches or it hasn't been specified and we've |
825 | */ | 842 | * found a mode, for which we can configure the |
826 | exact_match = true; | 843 | * clock precisely |
827 | else if (found && found_rate_error <= rate_error) | 844 | */ |
828 | /* | 845 | scanning = false; |
829 | * We otherwise search for the closest matching clock | 846 | else if (found && found_rate_error <= rate_error) |
830 | * rate - either if no refresh rate has been specified | 847 | /* |
831 | * or we cannot find an exactly matching one | 848 | * We otherwise search for the closest matching |
832 | */ | 849 | * clock rate - either if no refresh rate has |
833 | continue; | 850 | * been specified or we cannot find an exactly |
851 | * matching one | ||
852 | */ | ||
853 | continue; | ||
854 | } | ||
834 | 855 | ||
835 | /* Check if supported: sufficient fb memory, supported clock-rate */ | 856 | /* Check if supported: sufficient fb memory, supported clock-rate */ |
836 | fb_videomode_to_var(var, mode); | 857 | fb_videomode_to_var(var, mode); |
837 | 858 | ||
859 | var->bits_per_pixel = info->var.bits_per_pixel; | ||
860 | |||
838 | if (info && info->fbops->fb_check_var && | 861 | if (info && info->fbops->fb_check_var && |
839 | info->fbops->fb_check_var(var, info)) { | 862 | info->fbops->fb_check_var(var, info)) { |
840 | exact_match = false; | 863 | scanning = true; |
864 | preferred_bad = true; | ||
841 | continue; | 865 | continue; |
842 | } | 866 | } |
843 | 867 | ||
@@ -855,9 +879,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
855 | * driver, and passing ->info with HDMI platform data. | 879 | * driver, and passing ->info with HDMI platform data. |
856 | */ | 880 | */ |
857 | if (info && !found) { | 881 | if (info && !found) { |
858 | modelist = hdmi->info->modelist.next && | 882 | modelist = info->modelist.next && |
859 | !list_empty(&hdmi->info->modelist) ? | 883 | !list_empty(&info->modelist) ? |
860 | list_entry(hdmi->info->modelist.next, | 884 | list_entry(info->modelist.next, |
861 | struct fb_modelist, list) : | 885 | struct fb_modelist, list) : |
862 | NULL; | 886 | NULL; |
863 | 887 | ||
@@ -1100,6 +1124,7 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1100 | mutex_lock(&hdmi->mutex); | 1124 | mutex_lock(&hdmi->mutex); |
1101 | 1125 | ||
1102 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { | 1126 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { |
1127 | struct fb_info *info = hdmi->info; | ||
1103 | unsigned long parent_rate = 0, hdmi_rate; | 1128 | unsigned long parent_rate = 0, hdmi_rate; |
1104 | 1129 | ||
1105 | /* A device has been plugged in */ | 1130 | /* A device has been plugged in */ |
@@ -1121,22 +1146,21 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1121 | /* Switched to another (d) power-save mode */ | 1146 | /* Switched to another (d) power-save mode */ |
1122 | msleep(10); | 1147 | msleep(10); |
1123 | 1148 | ||
1124 | if (!hdmi->info) | 1149 | if (!info) |
1125 | goto out; | 1150 | goto out; |
1126 | 1151 | ||
1127 | ch = hdmi->info->par; | 1152 | ch = info->par; |
1128 | 1153 | ||
1129 | acquire_console_sem(); | 1154 | acquire_console_sem(); |
1130 | 1155 | ||
1131 | /* HDMI plug in */ | 1156 | /* HDMI plug in */ |
1132 | if (!sh_hdmi_must_reconfigure(hdmi) && | 1157 | if (!sh_hdmi_must_reconfigure(hdmi) && |
1133 | hdmi->info->state == FBINFO_STATE_RUNNING) { | 1158 | info->state == FBINFO_STATE_RUNNING) { |
1134 | /* | 1159 | /* |
1135 | * First activation with the default monitor - just turn | 1160 | * First activation with the default monitor - just turn |
1136 | * on, if we run a resume here, the logo disappears | 1161 | * on, if we run a resume here, the logo disappears |
1137 | */ | 1162 | */ |
1138 | if (lock_fb_info(hdmi->info)) { | 1163 | if (lock_fb_info(info)) { |
1139 | struct fb_info *info = hdmi->info; | ||
1140 | info->var.width = hdmi->var.width; | 1164 | info->var.width = hdmi->var.width; |
1141 | info->var.height = hdmi->var.height; | 1165 | info->var.height = hdmi->var.height; |
1142 | sh_hdmi_display_on(hdmi, info); | 1166 | sh_hdmi_display_on(hdmi, info); |
@@ -1144,7 +1168,7 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1144 | } | 1168 | } |
1145 | } else { | 1169 | } else { |
1146 | /* New monitor or have to wake up */ | 1170 | /* New monitor or have to wake up */ |
1147 | fb_set_suspend(hdmi->info, 0); | 1171 | fb_set_suspend(info, 0); |
1148 | } | 1172 | } |
1149 | 1173 | ||
1150 | release_console_sem(); | 1174 | release_console_sem(); |
@@ -1175,13 +1199,6 @@ out: | |||
1175 | } | 1199 | } |
1176 | 1200 | ||
1177 | static int sh_hdmi_notify(struct notifier_block *nb, | 1201 | static int sh_hdmi_notify(struct notifier_block *nb, |
1178 | unsigned long action, void *data); | ||
1179 | |||
1180 | static struct notifier_block sh_hdmi_notifier = { | ||
1181 | .notifier_call = sh_hdmi_notify, | ||
1182 | }; | ||
1183 | |||
1184 | static int sh_hdmi_notify(struct notifier_block *nb, | ||
1185 | unsigned long action, void *data) | 1202 | unsigned long action, void *data) |
1186 | { | 1203 | { |
1187 | struct fb_event *event = data; | 1204 | struct fb_event *event = data; |
@@ -1190,7 +1207,7 @@ static int sh_hdmi_notify(struct notifier_block *nb, | |||
1190 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; | 1207 | struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg; |
1191 | struct sh_hdmi *hdmi = board_cfg->board_data; | 1208 | struct sh_hdmi *hdmi = board_cfg->board_data; |
1192 | 1209 | ||
1193 | if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info) | 1210 | if (!hdmi || nb != &hdmi->notifier || hdmi->info != info) |
1194 | return NOTIFY_DONE; | 1211 | return NOTIFY_DONE; |
1195 | 1212 | ||
1196 | switch(action) { | 1213 | switch(action) { |
@@ -1209,11 +1226,11 @@ static int sh_hdmi_notify(struct notifier_block *nb, | |||
1209 | * temporarily, synchronise with the work queue and re-acquire | 1226 | * temporarily, synchronise with the work queue and re-acquire |
1210 | * the info->lock. | 1227 | * the info->lock. |
1211 | */ | 1228 | */ |
1212 | unlock_fb_info(hdmi->info); | 1229 | unlock_fb_info(info); |
1213 | mutex_lock(&hdmi->mutex); | 1230 | mutex_lock(&hdmi->mutex); |
1214 | hdmi->info = NULL; | 1231 | hdmi->info = NULL; |
1215 | mutex_unlock(&hdmi->mutex); | 1232 | mutex_unlock(&hdmi->mutex); |
1216 | lock_fb_info(hdmi->info); | 1233 | lock_fb_info(info); |
1217 | return NOTIFY_OK; | 1234 | return NOTIFY_OK; |
1218 | } | 1235 | } |
1219 | return NOTIFY_DONE; | 1236 | return NOTIFY_DONE; |
@@ -1311,6 +1328,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev) | |||
1311 | goto ecodec; | 1328 | goto ecodec; |
1312 | } | 1329 | } |
1313 | 1330 | ||
1331 | hdmi->notifier.notifier_call = sh_hdmi_notify; | ||
1332 | fb_register_client(&hdmi->notifier); | ||
1333 | |||
1314 | return 0; | 1334 | return 0; |
1315 | 1335 | ||
1316 | ecodec: | 1336 | ecodec: |
@@ -1341,6 +1361,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev) | |||
1341 | 1361 | ||
1342 | snd_soc_unregister_codec(&pdev->dev); | 1362 | snd_soc_unregister_codec(&pdev->dev); |
1343 | 1363 | ||
1364 | fb_unregister_client(&hdmi->notifier); | ||
1365 | |||
1344 | board_cfg->display_on = NULL; | 1366 | board_cfg->display_on = NULL; |
1345 | board_cfg->display_off = NULL; | 1367 | board_cfg->display_off = NULL; |
1346 | board_cfg->board_data = NULL; | 1368 | board_cfg->board_data = NULL; |
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index dee64c3b1e67..2ab704118c44 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c | |||
@@ -536,7 +536,7 @@ static int sstfb_set_par(struct fb_info *info) | |||
536 | fbiinit2 = sst_read(FBIINIT2); | 536 | fbiinit2 = sst_read(FBIINIT2); |
537 | fbiinit3 = sst_read(FBIINIT3); | 537 | fbiinit3 = sst_read(FBIINIT3); |
538 | 538 | ||
539 | /* everything is reset. we enable fbiinit2/3 remap : dac acces ok */ | 539 | /* everything is reset. we enable fbiinit2/3 remap : dac access ok */ |
540 | pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, | 540 | pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, |
541 | PCI_EN_INIT_WR | PCI_REMAP_DAC ); | 541 | PCI_EN_INIT_WR | PCI_REMAP_DAC ); |
542 | 542 | ||
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index 7617f12e4fd7..0e120d67eb65 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c | |||
@@ -215,6 +215,33 @@ static int vt8500lcd_pan_display(struct fb_var_screeninfo *var, | |||
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | /* | ||
219 | * vt8500lcd_blank(): | ||
220 | * Blank the display by setting all palette values to zero. Note, | ||
221 | * True Color modes do not really use the palette, so this will not | ||
222 | * blank the display in all modes. | ||
223 | */ | ||
224 | static int vt8500lcd_blank(int blank, struct fb_info *info) | ||
225 | { | ||
226 | int i; | ||
227 | |||
228 | switch (blank) { | ||
229 | case FB_BLANK_POWERDOWN: | ||
230 | case FB_BLANK_VSYNC_SUSPEND: | ||
231 | case FB_BLANK_HSYNC_SUSPEND: | ||
232 | case FB_BLANK_NORMAL: | ||
233 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR || | ||
234 | info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) | ||
235 | for (i = 0; i < 256; i++) | ||
236 | vt8500lcd_setcolreg(i, 0, 0, 0, 0, info); | ||
237 | case FB_BLANK_UNBLANK: | ||
238 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR || | ||
239 | info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) | ||
240 | fb_set_cmap(&info->cmap, info); | ||
241 | } | ||
242 | return 0; | ||
243 | } | ||
244 | |||
218 | static struct fb_ops vt8500lcd_ops = { | 245 | static struct fb_ops vt8500lcd_ops = { |
219 | .owner = THIS_MODULE, | 246 | .owner = THIS_MODULE, |
220 | .fb_set_par = vt8500lcd_set_par, | 247 | .fb_set_par = vt8500lcd_set_par, |
@@ -225,6 +252,7 @@ static struct fb_ops vt8500lcd_ops = { | |||
225 | .fb_sync = wmt_ge_sync, | 252 | .fb_sync = wmt_ge_sync, |
226 | .fb_ioctl = vt8500lcd_ioctl, | 253 | .fb_ioctl = vt8500lcd_ioctl, |
227 | .fb_pan_display = vt8500lcd_pan_display, | 254 | .fb_pan_display = vt8500lcd_pan_display, |
255 | .fb_blank = vt8500lcd_blank, | ||
228 | }; | 256 | }; |
229 | 257 | ||
230 | static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id) | 258 | static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id) |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 1f51366417b9..f0c909625bd1 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
@@ -16,6 +16,17 @@ config W1_SLAVE_SMEM | |||
16 | Say Y here if you want to connect 1-wire | 16 | Say Y here if you want to connect 1-wire |
17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. | 17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. |
18 | 18 | ||
19 | config W1_SLAVE_DS2423 | ||
20 | tristate "Counter 1-wire device (DS2423)" | ||
21 | select CRC16 | ||
22 | help | ||
23 | If you enable this you can read the counter values available | ||
24 | in the DS2423 chipset from the w1_slave file under the | ||
25 | sys file system. | ||
26 | |||
27 | Say Y here if you want to use a 1-wire | ||
28 | counter family device (DS2423). | ||
29 | |||
19 | config W1_SLAVE_DS2431 | 30 | config W1_SLAVE_DS2431 |
20 | tristate "1kb EEPROM family support (DS2431)" | 31 | tristate "1kb EEPROM family support (DS2431)" |
21 | help | 32 | help |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index f1f51f19b129..3c76350a24f7 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o | 5 | obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o |
6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o | 6 | obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o |
7 | obj-$(CONFIG_W1_SLAVE_DS2423) += w1_ds2423.o | ||
7 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o | 8 | obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o |
8 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o | 9 | obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o |
9 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | 10 | obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o |
diff --git a/drivers/w1/slaves/w1_ds2423.c b/drivers/w1/slaves/w1_ds2423.c new file mode 100644 index 000000000000..7a7dbe5026f1 --- /dev/null +++ b/drivers/w1/slaves/w1_ds2423.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * w1_ds2423.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Mika Laitio <lamikr@pilppa.org> | ||
5 | * | ||
6 | * This driver will read and write the value of 4 counters to w1_slave file in | ||
7 | * sys filesystem. | ||
8 | * Inspired by the w1_therm and w1_ds2431 drivers. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the therms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/crc16.h> | ||
32 | |||
33 | #include "../w1.h" | ||
34 | #include "../w1_int.h" | ||
35 | #include "../w1_family.h" | ||
36 | |||
37 | #define CRC16_VALID 0xb001 | ||
38 | #define CRC16_INIT 0 | ||
39 | |||
40 | #define COUNTER_COUNT 4 | ||
41 | #define READ_BYTE_COUNT 42 | ||
42 | |||
43 | static ssize_t w1_counter_read(struct device *device, | ||
44 | struct device_attribute *attr, char *buf); | ||
45 | |||
46 | static struct device_attribute w1_counter_attr = | ||
47 | __ATTR(w1_slave, S_IRUGO, w1_counter_read, NULL); | ||
48 | |||
49 | static ssize_t w1_counter_read(struct device *device, | ||
50 | struct device_attribute *attr, char *out_buf) | ||
51 | { | ||
52 | struct w1_slave *sl = dev_to_w1_slave(device); | ||
53 | struct w1_master *dev = sl->master; | ||
54 | u8 rbuf[COUNTER_COUNT * READ_BYTE_COUNT]; | ||
55 | u8 wrbuf[3]; | ||
56 | int rom_addr; | ||
57 | int read_byte_count; | ||
58 | int result; | ||
59 | ssize_t c; | ||
60 | int ii; | ||
61 | int p; | ||
62 | int crc; | ||
63 | |||
64 | c = PAGE_SIZE; | ||
65 | rom_addr = (12 << 5) + 31; | ||
66 | wrbuf[0] = 0xA5; | ||
67 | wrbuf[1] = rom_addr & 0xFF; | ||
68 | wrbuf[2] = rom_addr >> 8; | ||
69 | mutex_lock(&dev->mutex); | ||
70 | if (!w1_reset_select_slave(sl)) { | ||
71 | w1_write_block(dev, wrbuf, 3); | ||
72 | read_byte_count = 0; | ||
73 | for (p = 0; p < 4; p++) { | ||
74 | /* | ||
75 | * 1 byte for first bytes in ram page read | ||
76 | * 4 bytes for counter | ||
77 | * 4 bytes for zero bits | ||
78 | * 2 bytes for crc | ||
79 | * 31 remaining bytes from the ram page | ||
80 | */ | ||
81 | read_byte_count += w1_read_block(dev, | ||
82 | rbuf + (p * READ_BYTE_COUNT), READ_BYTE_COUNT); | ||
83 | for (ii = 0; ii < READ_BYTE_COUNT; ++ii) | ||
84 | c -= snprintf(out_buf + PAGE_SIZE - c, | ||
85 | c, "%02x ", | ||
86 | rbuf[(p * READ_BYTE_COUNT) + ii]); | ||
87 | if (read_byte_count != (p + 1) * READ_BYTE_COUNT) { | ||
88 | dev_warn(device, | ||
89 | "w1_counter_read() returned %u bytes " | ||
90 | "instead of %d bytes wanted.\n", | ||
91 | read_byte_count, | ||
92 | READ_BYTE_COUNT); | ||
93 | c -= snprintf(out_buf + PAGE_SIZE - c, | ||
94 | c, "crc=NO\n"); | ||
95 | } else { | ||
96 | if (p == 0) { | ||
97 | crc = crc16(CRC16_INIT, wrbuf, 3); | ||
98 | crc = crc16(crc, rbuf, 11); | ||
99 | } else { | ||
100 | /* | ||
101 | * DS2423 calculates crc from all bytes | ||
102 | * read after the previous crc bytes. | ||
103 | */ | ||
104 | crc = crc16(CRC16_INIT, | ||
105 | (rbuf + 11) + | ||
106 | ((p - 1) * READ_BYTE_COUNT), | ||
107 | READ_BYTE_COUNT); | ||
108 | } | ||
109 | if (crc == CRC16_VALID) { | ||
110 | result = 0; | ||
111 | for (ii = 4; ii > 0; ii--) { | ||
112 | result <<= 8; | ||
113 | result |= rbuf[(p * | ||
114 | READ_BYTE_COUNT) + ii]; | ||
115 | } | ||
116 | c -= snprintf(out_buf + PAGE_SIZE - c, | ||
117 | c, "crc=YES c=%d\n", result); | ||
118 | } else { | ||
119 | c -= snprintf(out_buf + PAGE_SIZE - c, | ||
120 | c, "crc=NO\n"); | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | } else { | ||
125 | c -= snprintf(out_buf + PAGE_SIZE - c, c, "Connection error"); | ||
126 | } | ||
127 | mutex_unlock(&dev->mutex); | ||
128 | return PAGE_SIZE - c; | ||
129 | } | ||
130 | |||
131 | static int w1_f1d_add_slave(struct w1_slave *sl) | ||
132 | { | ||
133 | return device_create_file(&sl->dev, &w1_counter_attr); | ||
134 | } | ||
135 | |||
136 | static void w1_f1d_remove_slave(struct w1_slave *sl) | ||
137 | { | ||
138 | device_remove_file(&sl->dev, &w1_counter_attr); | ||
139 | } | ||
140 | |||
141 | static struct w1_family_ops w1_f1d_fops = { | ||
142 | .add_slave = w1_f1d_add_slave, | ||
143 | .remove_slave = w1_f1d_remove_slave, | ||
144 | }; | ||
145 | |||
146 | static struct w1_family w1_family_1d = { | ||
147 | .fid = W1_COUNTER_DS2423, | ||
148 | .fops = &w1_f1d_fops, | ||
149 | }; | ||
150 | |||
151 | static int __init w1_f1d_init(void) | ||
152 | { | ||
153 | return w1_register_family(&w1_family_1d); | ||
154 | } | ||
155 | |||
156 | static void __exit w1_f1d_exit(void) | ||
157 | { | ||
158 | w1_unregister_family(&w1_family_1d); | ||
159 | } | ||
160 | |||
161 | module_init(w1_f1d_init); | ||
162 | module_exit(w1_f1d_exit); | ||
163 | |||
164 | MODULE_LICENSE("GPL"); | ||
165 | MODULE_AUTHOR("Mika Laitio <lamikr@pilppa.org>"); | ||
166 | MODULE_DESCRIPTION("w1 family 1d driver for DS2423, 4 counters and 4kb ram"); | ||
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index 3ca1b9298f21..f3b636d7cafe 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define W1_FAMILY_SMEM_01 0x01 | 30 | #define W1_FAMILY_SMEM_01 0x01 |
31 | #define W1_FAMILY_SMEM_81 0x81 | 31 | #define W1_FAMILY_SMEM_81 0x81 |
32 | #define W1_THERM_DS18S20 0x10 | 32 | #define W1_THERM_DS18S20 0x10 |
33 | #define W1_COUNTER_DS2423 0x1D | ||
33 | #define W1_THERM_DS1822 0x22 | 34 | #define W1_THERM_DS1822 0x22 |
34 | #define W1_EEPROM_DS2433 0x23 | 35 | #define W1_EEPROM_DS2433 0x23 |
35 | #define W1_THERM_DS18B20 0x28 | 36 | #define W1_THERM_DS18B20 0x28 |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a5ad77ef4266..2e2400e7322e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -409,15 +409,26 @@ config ALIM7101_WDT | |||
409 | Most people will say N. | 409 | Most people will say N. |
410 | 410 | ||
411 | config F71808E_WDT | 411 | config F71808E_WDT |
412 | tristate "Fintek F71808E, F71882FG and F71889FG Watchdog" | 412 | tristate "Fintek F71808E, F71862FG, F71869, F71882FG and F71889FG Watchdog" |
413 | depends on X86 && EXPERIMENTAL | 413 | depends on X86 && EXPERIMENTAL |
414 | help | 414 | help |
415 | This is the driver for the hardware watchdog on the Fintek | 415 | This is the driver for the hardware watchdog on the Fintek |
416 | F71808E, F71882FG and F71889FG Super I/O controllers. | 416 | F71808E, F71862FG, F71869, F71882FG and F71889FG Super I/O controllers. |
417 | 417 | ||
418 | You can compile this driver directly into the kernel, or use | 418 | You can compile this driver directly into the kernel, or use |
419 | it as a module. The module will be called f71808e_wdt. | 419 | it as a module. The module will be called f71808e_wdt. |
420 | 420 | ||
421 | config SP5100_TCO | ||
422 | tristate "AMD/ATI SP5100 TCO Timer/Watchdog" | ||
423 | depends on X86 && PCI | ||
424 | ---help--- | ||
425 | Hardware watchdog driver for the AMD/ATI SP5100 chipset. The TCO | ||
426 | (Total Cost of Ownership) timer is a watchdog timer that will reboot | ||
427 | the machine after its expiration. The expiration time can be | ||
428 | configured with the "heartbeat" parameter. | ||
429 | |||
430 | To compile this driver as a module, choose M here: the | ||
431 | module will be called sp5100_tco. | ||
421 | 432 | ||
422 | config GEODE_WDT | 433 | config GEODE_WDT |
423 | tristate "AMD Geode CS5535/CS5536 Watchdog" | 434 | tristate "AMD Geode CS5535/CS5536 Watchdog" |
@@ -631,6 +642,24 @@ config PC87413_WDT | |||
631 | 642 | ||
632 | Most people will say N. | 643 | Most people will say N. |
633 | 644 | ||
645 | config NV_TCO | ||
646 | tristate "nVidia TCO Timer/Watchdog" | ||
647 | depends on X86 && PCI | ||
648 | ---help--- | ||
649 | Hardware driver for the TCO timer built into the nVidia Hub family | ||
650 | (such as the MCP51). The TCO (Total Cost of Ownership) timer is a | ||
651 | watchdog timer that will reboot the machine after its second | ||
652 | expiration. The expiration time can be configured with the | ||
653 | "heartbeat" parameter. | ||
654 | |||
655 | On some motherboards the driver may fail to reset the chipset's | ||
656 | NO_REBOOT flag which prevents the watchdog from rebooting the | ||
657 | machine. If this is the case you will get a kernel message like | ||
658 | "failed to reset NO_REBOOT flag, reboot disabled by hardware". | ||
659 | |||
660 | To compile this driver as a module, choose M here: the | ||
661 | module will be called nv_tco. | ||
662 | |||
634 | config RDC321X_WDT | 663 | config RDC321X_WDT |
635 | tristate "RDC R-321x SoC watchdog" | 664 | tristate "RDC R-321x SoC watchdog" |
636 | depends on X86_RDC321X | 665 | depends on X86_RDC321X |
@@ -722,14 +751,15 @@ config SMSC37B787_WDT | |||
722 | Most people will say N. | 751 | Most people will say N. |
723 | 752 | ||
724 | config W83627HF_WDT | 753 | config W83627HF_WDT |
725 | tristate "W83627HF Watchdog Timer" | 754 | tristate "W83627HF/W83627DHG Watchdog Timer" |
726 | depends on X86 | 755 | depends on X86 |
727 | ---help--- | 756 | ---help--- |
728 | This is the driver for the hardware watchdog on the W83627HF chipset | 757 | This is the driver for the hardware watchdog on the W83627HF chipset |
729 | as used in Advantech PC-9578 and Tyan S2721-533 motherboards | 758 | as used in Advantech PC-9578 and Tyan S2721-533 motherboards |
730 | (and likely others). This watchdog simply watches your kernel to | 759 | (and likely others). The driver also supports the W83627DHG chip. |
731 | make sure it doesn't freeze, and if it does, it reboots your computer | 760 | This watchdog simply watches your kernel to make sure it doesn't |
732 | after a certain amount of time. | 761 | freeze, and if it does, it reboots your computer after a certain |
762 | amount of time. | ||
733 | 763 | ||
734 | To compile this driver as a module, choose M here: the | 764 | To compile this driver as a module, choose M here: the |
735 | module will be called w83627hf_wdt. | 765 | module will be called w83627hf_wdt. |
@@ -832,10 +862,22 @@ config SBC_EPX_C3_WATCHDOG | |||
832 | 862 | ||
833 | # M68K Architecture | 863 | # M68K Architecture |
834 | 864 | ||
835 | # M68KNOMMU Architecture | 865 | config M548x_WATCHDOG |
866 | tristate "MCF548x watchdog support" | ||
867 | depends on M548x | ||
868 | help | ||
869 | To compile this driver as a module, choose M here: the | ||
870 | module will be called m548x_wdt. | ||
836 | 871 | ||
837 | # MIPS Architecture | 872 | # MIPS Architecture |
838 | 873 | ||
874 | config ATH79_WDT | ||
875 | tristate "Atheros AR71XX/AR724X/AR913X hardware watchdog" | ||
876 | depends on ATH79 | ||
877 | help | ||
878 | Hardware driver for the built-in watchdog timer on the Atheros | ||
879 | AR71XX/AR724X/AR913X SoCs. | ||
880 | |||
839 | config BCM47XX_WDT | 881 | config BCM47XX_WDT |
840 | tristate "Broadcom BCM47xx Watchdog Timer" | 882 | tristate "Broadcom BCM47xx Watchdog Timer" |
841 | depends on BCM47XX | 883 | depends on BCM47XX |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 4b0ef386229d..dd776651917c 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -68,6 +68,7 @@ obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o | |||
68 | obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o | 68 | obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o |
69 | obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o | 69 | obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o |
70 | obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o | 70 | obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o |
71 | obj-$(CONFIG_SP5100_TCO) += sp5100_tco.o | ||
71 | obj-$(CONFIG_GEODE_WDT) += geodewdt.o | 72 | obj-$(CONFIG_GEODE_WDT) += geodewdt.o |
72 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o | 73 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o |
73 | obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o | 74 | obj-$(CONFIG_SBC_FITPC2_WATCHDOG) += sbc_fitpc2_wdt.o |
@@ -86,6 +87,7 @@ obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o | |||
86 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o | 87 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o |
87 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o | 88 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o |
88 | obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o | 89 | obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o |
90 | obj-$(CONFIG_NV_TCO) += nv_tco.o | ||
89 | obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o | 91 | obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o |
90 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o | 92 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o |
91 | obj-$(CONFIG_SBC8360_WDT) += sbc8360.o | 93 | obj-$(CONFIG_SBC8360_WDT) += sbc8360.o |
@@ -104,10 +106,10 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o | |||
104 | # M32R Architecture | 106 | # M32R Architecture |
105 | 107 | ||
106 | # M68K Architecture | 108 | # M68K Architecture |
107 | 109 | obj-$(CONFIG_M548x_WATCHDOG) += m548x_wdt.o | |
108 | # M68KNOMMU Architecture | ||
109 | 110 | ||
110 | # MIPS Architecture | 111 | # MIPS Architecture |
112 | obj-$(CONFIG_ATH79_WDT) += ath79_wdt.o | ||
111 | obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o | 113 | obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o |
112 | obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o | 114 | obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o |
113 | obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o | 115 | obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o |
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index 1e9caea8ff8a..fa4d36033552 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c | |||
@@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this, | |||
301 | * want to register another driver on the same PCI id. | 301 | * want to register another driver on the same PCI id. |
302 | */ | 302 | */ |
303 | 303 | ||
304 | static struct pci_device_id ali_pci_tbl[] = { | 304 | static struct pci_device_id ali_pci_tbl[] __used = { |
305 | { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, | 305 | { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, |
306 | { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, | 306 | { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, |
307 | { 0, }, | 307 | { 0, }, |
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index d8d4da9a483d..4b7a2b4138ed 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c | |||
@@ -430,7 +430,7 @@ err_out: | |||
430 | module_init(alim7101_wdt_init); | 430 | module_init(alim7101_wdt_init); |
431 | module_exit(alim7101_wdt_unload); | 431 | module_exit(alim7101_wdt_unload); |
432 | 432 | ||
433 | static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { | 433 | static struct pci_device_id alim7101_pci_tbl[] __devinitdata __used = { |
434 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, | 434 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) }, |
435 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, | 435 | { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, |
436 | { } | 436 | { } |
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c new file mode 100644 index 000000000000..725c84bfdd76 --- /dev/null +++ b/drivers/watchdog/ath79_wdt.c | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | * Atheros AR71XX/AR724X/AR913X built-in hardware watchdog timer. | ||
3 | * | ||
4 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> | ||
5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||
6 | * | ||
7 | * This driver was based on: drivers/watchdog/ixp4xx_wdt.c | ||
8 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
9 | * Copyright 2004 (c) MontaVista, Software, Inc. | ||
10 | * | ||
11 | * which again was based on sa1100 driver, | ||
12 | * Copyright (C) 2000 Oleg Drokin <green@crimea.edu> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License version 2 as published | ||
16 | * by the Free Software Foundation. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/bitops.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/miscdevice.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/types.h> | ||
30 | #include <linux/watchdog.h> | ||
31 | #include <linux/clk.h> | ||
32 | #include <linux/err.h> | ||
33 | |||
34 | #include <asm/mach-ath79/ath79.h> | ||
35 | #include <asm/mach-ath79/ar71xx_regs.h> | ||
36 | |||
37 | #define DRIVER_NAME "ath79-wdt" | ||
38 | |||
39 | #define WDT_TIMEOUT 15 /* seconds */ | ||
40 | |||
41 | #define WDOG_CTRL_LAST_RESET BIT(31) | ||
42 | #define WDOG_CTRL_ACTION_MASK 3 | ||
43 | #define WDOG_CTRL_ACTION_NONE 0 /* no action */ | ||
44 | #define WDOG_CTRL_ACTION_GPI 1 /* general purpose interrupt */ | ||
45 | #define WDOG_CTRL_ACTION_NMI 2 /* NMI */ | ||
46 | #define WDOG_CTRL_ACTION_FCR 3 /* full chip reset */ | ||
47 | |||
48 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
49 | module_param(nowayout, int, 0); | ||
50 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | ||
51 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
52 | |||
53 | static int timeout = WDT_TIMEOUT; | ||
54 | module_param(timeout, int, 0); | ||
55 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds " | ||
56 | "(default=" __MODULE_STRING(WDT_TIMEOUT) "s)"); | ||
57 | |||
58 | static unsigned long wdt_flags; | ||
59 | |||
60 | #define WDT_FLAGS_BUSY 0 | ||
61 | #define WDT_FLAGS_EXPECT_CLOSE 1 | ||
62 | |||
63 | static struct clk *wdt_clk; | ||
64 | static unsigned long wdt_freq; | ||
65 | static int boot_status; | ||
66 | static int max_timeout; | ||
67 | |||
68 | static inline void ath79_wdt_keepalive(void) | ||
69 | { | ||
70 | ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout); | ||
71 | } | ||
72 | |||
73 | static inline void ath79_wdt_enable(void) | ||
74 | { | ||
75 | ath79_wdt_keepalive(); | ||
76 | ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR); | ||
77 | } | ||
78 | |||
79 | static inline void ath79_wdt_disable(void) | ||
80 | { | ||
81 | ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE); | ||
82 | } | ||
83 | |||
84 | static int ath79_wdt_set_timeout(int val) | ||
85 | { | ||
86 | if (val < 1 || val > max_timeout) | ||
87 | return -EINVAL; | ||
88 | |||
89 | timeout = val; | ||
90 | ath79_wdt_keepalive(); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int ath79_wdt_open(struct inode *inode, struct file *file) | ||
96 | { | ||
97 | if (test_and_set_bit(WDT_FLAGS_BUSY, &wdt_flags)) | ||
98 | return -EBUSY; | ||
99 | |||
100 | clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); | ||
101 | ath79_wdt_enable(); | ||
102 | |||
103 | return nonseekable_open(inode, file); | ||
104 | } | ||
105 | |||
106 | static int ath79_wdt_release(struct inode *inode, struct file *file) | ||
107 | { | ||
108 | if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags)) | ||
109 | ath79_wdt_disable(); | ||
110 | else { | ||
111 | pr_crit(DRIVER_NAME ": device closed unexpectedly, " | ||
112 | "watchdog timer will not stop!\n"); | ||
113 | ath79_wdt_keepalive(); | ||
114 | } | ||
115 | |||
116 | clear_bit(WDT_FLAGS_BUSY, &wdt_flags); | ||
117 | clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static ssize_t ath79_wdt_write(struct file *file, const char *data, | ||
123 | size_t len, loff_t *ppos) | ||
124 | { | ||
125 | if (len) { | ||
126 | if (!nowayout) { | ||
127 | size_t i; | ||
128 | |||
129 | clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); | ||
130 | |||
131 | for (i = 0; i != len; i++) { | ||
132 | char c; | ||
133 | |||
134 | if (get_user(c, data + i)) | ||
135 | return -EFAULT; | ||
136 | |||
137 | if (c == 'V') | ||
138 | set_bit(WDT_FLAGS_EXPECT_CLOSE, | ||
139 | &wdt_flags); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | ath79_wdt_keepalive(); | ||
144 | } | ||
145 | |||
146 | return len; | ||
147 | } | ||
148 | |||
149 | static const struct watchdog_info ath79_wdt_info = { | ||
150 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | | ||
151 | WDIOF_MAGICCLOSE | WDIOF_CARDRESET, | ||
152 | .firmware_version = 0, | ||
153 | .identity = "ATH79 watchdog", | ||
154 | }; | ||
155 | |||
156 | static long ath79_wdt_ioctl(struct file *file, unsigned int cmd, | ||
157 | unsigned long arg) | ||
158 | { | ||
159 | void __user *argp = (void __user *)arg; | ||
160 | int __user *p = argp; | ||
161 | int err; | ||
162 | int t; | ||
163 | |||
164 | switch (cmd) { | ||
165 | case WDIOC_GETSUPPORT: | ||
166 | err = copy_to_user(argp, &ath79_wdt_info, | ||
167 | sizeof(ath79_wdt_info)) ? -EFAULT : 0; | ||
168 | break; | ||
169 | |||
170 | case WDIOC_GETSTATUS: | ||
171 | err = put_user(0, p); | ||
172 | break; | ||
173 | |||
174 | case WDIOC_GETBOOTSTATUS: | ||
175 | err = put_user(boot_status, p); | ||
176 | break; | ||
177 | |||
178 | case WDIOC_KEEPALIVE: | ||
179 | ath79_wdt_keepalive(); | ||
180 | err = 0; | ||
181 | break; | ||
182 | |||
183 | case WDIOC_SETTIMEOUT: | ||
184 | err = get_user(t, p); | ||
185 | if (err) | ||
186 | break; | ||
187 | |||
188 | err = ath79_wdt_set_timeout(t); | ||
189 | if (err) | ||
190 | break; | ||
191 | |||
192 | /* fallthrough */ | ||
193 | case WDIOC_GETTIMEOUT: | ||
194 | err = put_user(timeout, p); | ||
195 | break; | ||
196 | |||
197 | default: | ||
198 | err = -ENOTTY; | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | return err; | ||
203 | } | ||
204 | |||
205 | static const struct file_operations ath79_wdt_fops = { | ||
206 | .owner = THIS_MODULE, | ||
207 | .llseek = no_llseek, | ||
208 | .write = ath79_wdt_write, | ||
209 | .unlocked_ioctl = ath79_wdt_ioctl, | ||
210 | .open = ath79_wdt_open, | ||
211 | .release = ath79_wdt_release, | ||
212 | }; | ||
213 | |||
214 | static struct miscdevice ath79_wdt_miscdev = { | ||
215 | .minor = WATCHDOG_MINOR, | ||
216 | .name = "watchdog", | ||
217 | .fops = &ath79_wdt_fops, | ||
218 | }; | ||
219 | |||
220 | static int __devinit ath79_wdt_probe(struct platform_device *pdev) | ||
221 | { | ||
222 | u32 ctrl; | ||
223 | int err; | ||
224 | |||
225 | wdt_clk = clk_get(&pdev->dev, "wdt"); | ||
226 | if (IS_ERR(wdt_clk)) | ||
227 | return PTR_ERR(wdt_clk); | ||
228 | |||
229 | err = clk_enable(wdt_clk); | ||
230 | if (err) | ||
231 | goto err_clk_put; | ||
232 | |||
233 | wdt_freq = clk_get_rate(wdt_clk); | ||
234 | if (!wdt_freq) { | ||
235 | err = -EINVAL; | ||
236 | goto err_clk_disable; | ||
237 | } | ||
238 | |||
239 | max_timeout = (0xfffffffful / wdt_freq); | ||
240 | if (timeout < 1 || timeout > max_timeout) { | ||
241 | timeout = max_timeout; | ||
242 | dev_info(&pdev->dev, | ||
243 | "timeout value must be 0 < timeout < %d, using %d\n", | ||
244 | max_timeout, timeout); | ||
245 | } | ||
246 | |||
247 | ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); | ||
248 | boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0; | ||
249 | |||
250 | err = misc_register(&ath79_wdt_miscdev); | ||
251 | if (err) { | ||
252 | dev_err(&pdev->dev, | ||
253 | "unable to register misc device, err=%d\n", err); | ||
254 | goto err_clk_disable; | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | |||
259 | err_clk_disable: | ||
260 | clk_disable(wdt_clk); | ||
261 | err_clk_put: | ||
262 | clk_put(wdt_clk); | ||
263 | return err; | ||
264 | } | ||
265 | |||
266 | static int __devexit ath79_wdt_remove(struct platform_device *pdev) | ||
267 | { | ||
268 | misc_deregister(&ath79_wdt_miscdev); | ||
269 | clk_disable(wdt_clk); | ||
270 | clk_put(wdt_clk); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static void ath97_wdt_shutdown(struct platform_device *pdev) | ||
275 | { | ||
276 | ath79_wdt_disable(); | ||
277 | } | ||
278 | |||
279 | static struct platform_driver ath79_wdt_driver = { | ||
280 | .remove = __devexit_p(ath79_wdt_remove), | ||
281 | .shutdown = ath97_wdt_shutdown, | ||
282 | .driver = { | ||
283 | .name = DRIVER_NAME, | ||
284 | .owner = THIS_MODULE, | ||
285 | }, | ||
286 | }; | ||
287 | |||
288 | static int __init ath79_wdt_init(void) | ||
289 | { | ||
290 | return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe); | ||
291 | } | ||
292 | module_init(ath79_wdt_init); | ||
293 | |||
294 | static void __exit ath79_wdt_exit(void) | ||
295 | { | ||
296 | platform_driver_unregister(&ath79_wdt_driver); | ||
297 | } | ||
298 | module_exit(ath79_wdt_exit); | ||
299 | |||
300 | MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X hardware watchdog driver"); | ||
301 | MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org"); | ||
302 | MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org"); | ||
303 | MODULE_LICENSE("GPL v2"); | ||
304 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
305 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index d11ffb091b0d..7e7ec9c35b6a 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c | |||
@@ -85,6 +85,22 @@ static unsigned int sec_to_period(unsigned int secs) | |||
85 | return 0; | 85 | return 0; |
86 | } | 86 | } |
87 | 87 | ||
88 | static void __booke_wdt_set(void *data) | ||
89 | { | ||
90 | u32 val; | ||
91 | |||
92 | val = mfspr(SPRN_TCR); | ||
93 | val &= ~WDTP_MASK; | ||
94 | val |= WDTP(booke_wdt_period); | ||
95 | |||
96 | mtspr(SPRN_TCR, val); | ||
97 | } | ||
98 | |||
99 | static void booke_wdt_set(void) | ||
100 | { | ||
101 | on_each_cpu(__booke_wdt_set, NULL, 0); | ||
102 | } | ||
103 | |||
88 | static void __booke_wdt_ping(void *data) | 104 | static void __booke_wdt_ping(void *data) |
89 | { | 105 | { |
90 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); | 106 | mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); |
@@ -181,8 +197,7 @@ static long booke_wdt_ioctl(struct file *file, | |||
181 | #else | 197 | #else |
182 | booke_wdt_period = tmp; | 198 | booke_wdt_period = tmp; |
183 | #endif | 199 | #endif |
184 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) | | 200 | booke_wdt_set(); |
185 | WDTP(booke_wdt_period)); | ||
186 | return 0; | 201 | return 0; |
187 | case WDIOC_GETTIMEOUT: | 202 | case WDIOC_GETTIMEOUT: |
188 | return put_user(booke_wdt_period, p); | 203 | return put_user(booke_wdt_period, p); |
@@ -193,8 +208,15 @@ static long booke_wdt_ioctl(struct file *file, | |||
193 | return 0; | 208 | return 0; |
194 | } | 209 | } |
195 | 210 | ||
211 | /* wdt_is_active stores wether or not the /dev/watchdog device is opened */ | ||
212 | static unsigned long wdt_is_active; | ||
213 | |||
196 | static int booke_wdt_open(struct inode *inode, struct file *file) | 214 | static int booke_wdt_open(struct inode *inode, struct file *file) |
197 | { | 215 | { |
216 | /* /dev/watchdog can only be opened once */ | ||
217 | if (test_and_set_bit(0, &wdt_is_active)) | ||
218 | return -EBUSY; | ||
219 | |||
198 | spin_lock(&booke_wdt_lock); | 220 | spin_lock(&booke_wdt_lock); |
199 | if (booke_wdt_enabled == 0) { | 221 | if (booke_wdt_enabled == 0) { |
200 | booke_wdt_enabled = 1; | 222 | booke_wdt_enabled = 1; |
@@ -210,8 +232,17 @@ static int booke_wdt_open(struct inode *inode, struct file *file) | |||
210 | 232 | ||
211 | static int booke_wdt_release(struct inode *inode, struct file *file) | 233 | static int booke_wdt_release(struct inode *inode, struct file *file) |
212 | { | 234 | { |
235 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | ||
236 | /* Normally, the watchdog is disabled when /dev/watchdog is closed, but | ||
237 | * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the | ||
238 | * watchdog should remain enabled. So we disable it only if | ||
239 | * CONFIG_WATCHDOG_NOWAYOUT is not defined. | ||
240 | */ | ||
213 | on_each_cpu(__booke_wdt_disable, NULL, 0); | 241 | on_each_cpu(__booke_wdt_disable, NULL, 0); |
214 | booke_wdt_enabled = 0; | 242 | booke_wdt_enabled = 0; |
243 | #endif | ||
244 | |||
245 | clear_bit(0, &wdt_is_active); | ||
215 | 246 | ||
216 | return 0; | 247 | return 0; |
217 | } | 248 | } |
diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 65e579635dba..d4d8d1fdccc4 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c | |||
@@ -42,18 +42,21 @@ | |||
42 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ | 42 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ |
43 | #define SIO_REG_DEVREV 0x22 /* Device revision */ | 43 | #define SIO_REG_DEVREV 0x22 /* Device revision */ |
44 | #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ | 44 | #define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ |
45 | #define SIO_REG_ROM_ADDR_SEL 0x27 /* ROM address select */ | ||
46 | #define SIO_REG_MFUNCT1 0x29 /* Multi function select 1 */ | ||
47 | #define SIO_REG_MFUNCT2 0x2a /* Multi function select 2 */ | ||
48 | #define SIO_REG_MFUNCT3 0x2b /* Multi function select 3 */ | ||
45 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ | 49 | #define SIO_REG_ENABLE 0x30 /* Logical device enable */ |
46 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | 50 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ |
47 | 51 | ||
48 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ | 52 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ |
49 | #define SIO_F71808_ID 0x0901 /* Chipset ID */ | 53 | #define SIO_F71808_ID 0x0901 /* Chipset ID */ |
50 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ | 54 | #define SIO_F71858_ID 0x0507 /* Chipset ID */ |
51 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ | 55 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ |
56 | #define SIO_F71869_ID 0x0814 /* Chipset ID */ | ||
52 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | 57 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
53 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ | 58 | #define SIO_F71889_ID 0x0723 /* Chipset ID */ |
54 | 59 | ||
55 | #define F71882FG_REG_START 0x01 | ||
56 | |||
57 | #define F71808FG_REG_WDO_CONF 0xf0 | 60 | #define F71808FG_REG_WDO_CONF 0xf0 |
58 | #define F71808FG_REG_WDT_CONF 0xf5 | 61 | #define F71808FG_REG_WDT_CONF 0xf5 |
59 | #define F71808FG_REG_WD_TIME 0xf6 | 62 | #define F71808FG_REG_WD_TIME 0xf6 |
@@ -70,13 +73,15 @@ | |||
70 | #define WATCHDOG_MAX_TIMEOUT (60 * 255) | 73 | #define WATCHDOG_MAX_TIMEOUT (60 * 255) |
71 | #define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for | 74 | #define WATCHDOG_PULSE_WIDTH 125 /* 125 ms, default pulse width for |
72 | watchdog signal */ | 75 | watchdog signal */ |
76 | #define WATCHDOG_F71862FG_PIN 63 /* default watchdog reset output | ||
77 | pin number 63 */ | ||
73 | 78 | ||
74 | static unsigned short force_id; | 79 | static unsigned short force_id; |
75 | module_param(force_id, ushort, 0); | 80 | module_param(force_id, ushort, 0); |
76 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 81 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
77 | 82 | ||
78 | static const int max_timeout = WATCHDOG_MAX_TIMEOUT; | 83 | static const int max_timeout = WATCHDOG_MAX_TIMEOUT; |
79 | static int timeout = 60; /* default timeout in seconds */ | 84 | static int timeout = WATCHDOG_TIMEOUT; /* default timeout in seconds */ |
80 | module_param(timeout, int, 0); | 85 | module_param(timeout, int, 0); |
81 | MODULE_PARM_DESC(timeout, | 86 | MODULE_PARM_DESC(timeout, |
82 | "Watchdog timeout in seconds. 1<= timeout <=" | 87 | "Watchdog timeout in seconds. 1<= timeout <=" |
@@ -89,6 +94,12 @@ MODULE_PARM_DESC(pulse_width, | |||
89 | "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" | 94 | "Watchdog signal pulse width. 0(=level), 1 ms, 25 ms, 125 ms or 5000 ms" |
90 | " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); | 95 | " (default=" __MODULE_STRING(WATCHDOG_PULSE_WIDTH) ")"); |
91 | 96 | ||
97 | static unsigned int f71862fg_pin = WATCHDOG_F71862FG_PIN; | ||
98 | module_param(f71862fg_pin, uint, 0); | ||
99 | MODULE_PARM_DESC(f71862fg_pin, | ||
100 | "Watchdog f71862fg reset output pin configuration. Choose pin 56 or 63" | ||
101 | " (default=" __MODULE_STRING(WATCHDOG_F71862FG_PIN)")"); | ||
102 | |||
92 | static int nowayout = WATCHDOG_NOWAYOUT; | 103 | static int nowayout = WATCHDOG_NOWAYOUT; |
93 | module_param(nowayout, bool, 0444); | 104 | module_param(nowayout, bool, 0444); |
94 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | 105 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); |
@@ -98,12 +109,13 @@ module_param(start_withtimeout, uint, 0); | |||
98 | MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" | 109 | MODULE_PARM_DESC(start_withtimeout, "Start watchdog timer on module load with" |
99 | " given initial timeout. Zero (default) disables this feature."); | 110 | " given initial timeout. Zero (default) disables this feature."); |
100 | 111 | ||
101 | enum chips { f71808fg, f71858fg, f71862fg, f71882fg, f71889fg }; | 112 | enum chips { f71808fg, f71858fg, f71862fg, f71869, f71882fg, f71889fg }; |
102 | 113 | ||
103 | static const char *f71808e_names[] = { | 114 | static const char *f71808e_names[] = { |
104 | "f71808fg", | 115 | "f71808fg", |
105 | "f71858fg", | 116 | "f71858fg", |
106 | "f71862fg", | 117 | "f71862fg", |
118 | "f71869", | ||
107 | "f71882fg", | 119 | "f71882fg", |
108 | "f71889fg", | 120 | "f71889fg", |
109 | }; | 121 | }; |
@@ -282,6 +294,28 @@ exit_unlock: | |||
282 | return err; | 294 | return err; |
283 | } | 295 | } |
284 | 296 | ||
297 | static int f71862fg_pin_configure(unsigned short ioaddr) | ||
298 | { | ||
299 | /* When ioaddr is non-zero the calling function has to take care of | ||
300 | mutex handling and superio preparation! */ | ||
301 | |||
302 | if (f71862fg_pin == 63) { | ||
303 | if (ioaddr) { | ||
304 | /* SPI must be disabled first to use this pin! */ | ||
305 | superio_clear_bit(ioaddr, SIO_REG_ROM_ADDR_SEL, 6); | ||
306 | superio_set_bit(ioaddr, SIO_REG_MFUNCT3, 4); | ||
307 | } | ||
308 | } else if (f71862fg_pin == 56) { | ||
309 | if (ioaddr) | ||
310 | superio_set_bit(ioaddr, SIO_REG_MFUNCT1, 1); | ||
311 | } else { | ||
312 | printk(KERN_ERR DRVNAME ": Invalid argument f71862fg_pin=%d\n", | ||
313 | f71862fg_pin); | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | return 0; | ||
317 | } | ||
318 | |||
285 | static int watchdog_start(void) | 319 | static int watchdog_start(void) |
286 | { | 320 | { |
287 | /* Make sure we don't die as soon as the watchdog is enabled below */ | 321 | /* Make sure we don't die as soon as the watchdog is enabled below */ |
@@ -299,19 +333,30 @@ static int watchdog_start(void) | |||
299 | switch (watchdog.type) { | 333 | switch (watchdog.type) { |
300 | case f71808fg: | 334 | case f71808fg: |
301 | /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ | 335 | /* Set pin 21 to GPIO23/WDTRST#, then to WDTRST# */ |
302 | superio_clear_bit(watchdog.sioaddr, 0x2a, 3); | 336 | superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT2, 3); |
303 | superio_clear_bit(watchdog.sioaddr, 0x2b, 3); | 337 | superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT3, 3); |
338 | break; | ||
339 | |||
340 | case f71862fg: | ||
341 | err = f71862fg_pin_configure(watchdog.sioaddr); | ||
342 | if (err) | ||
343 | goto exit_superio; | ||
344 | break; | ||
345 | |||
346 | case f71869: | ||
347 | /* GPIO14 --> WDTRST# */ | ||
348 | superio_clear_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 4); | ||
304 | break; | 349 | break; |
305 | 350 | ||
306 | case f71882fg: | 351 | case f71882fg: |
307 | /* Set pin 56 to WDTRST# */ | 352 | /* Set pin 56 to WDTRST# */ |
308 | superio_set_bit(watchdog.sioaddr, 0x29, 1); | 353 | superio_set_bit(watchdog.sioaddr, SIO_REG_MFUNCT1, 1); |
309 | break; | 354 | break; |
310 | 355 | ||
311 | case f71889fg: | 356 | case f71889fg: |
312 | /* set pin 40 to WDTRST# */ | 357 | /* set pin 40 to WDTRST# */ |
313 | superio_outb(watchdog.sioaddr, 0x2b, | 358 | superio_outb(watchdog.sioaddr, SIO_REG_MFUNCT3, |
314 | superio_inb(watchdog.sioaddr, 0x2b) & 0xcf); | 359 | superio_inb(watchdog.sioaddr, SIO_REG_MFUNCT3) & 0xcf); |
315 | break; | 360 | break; |
316 | 361 | ||
317 | default: | 362 | default: |
@@ -711,16 +756,19 @@ static int __init f71808e_find(int sioaddr) | |||
711 | case SIO_F71808_ID: | 756 | case SIO_F71808_ID: |
712 | watchdog.type = f71808fg; | 757 | watchdog.type = f71808fg; |
713 | break; | 758 | break; |
759 | case SIO_F71862_ID: | ||
760 | watchdog.type = f71862fg; | ||
761 | err = f71862fg_pin_configure(0); /* validate module parameter */ | ||
762 | break; | ||
763 | case SIO_F71869_ID: | ||
764 | watchdog.type = f71869; | ||
765 | break; | ||
714 | case SIO_F71882_ID: | 766 | case SIO_F71882_ID: |
715 | watchdog.type = f71882fg; | 767 | watchdog.type = f71882fg; |
716 | break; | 768 | break; |
717 | case SIO_F71889_ID: | 769 | case SIO_F71889_ID: |
718 | watchdog.type = f71889fg; | 770 | watchdog.type = f71889fg; |
719 | break; | 771 | break; |
720 | case SIO_F71862_ID: | ||
721 | /* These have a watchdog, though it isn't implemented (yet). */ | ||
722 | err = -ENOSYS; | ||
723 | goto exit; | ||
724 | case SIO_F71858_ID: | 772 | case SIO_F71858_ID: |
725 | /* Confirmed (by datasheet) not to have a watchdog. */ | 773 | /* Confirmed (by datasheet) not to have a watchdog. */ |
726 | err = -ENODEV; | 774 | err = -ENODEV; |
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index b8838d2c67a6..2c6c2b4ad8bf 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * intel TCO Watchdog Driver | 2 | * intel TCO Watchdog Driver |
3 | * | 3 | * |
4 | * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>. | 4 | * (c) Copyright 2006-2010 Wim Van Sebroeck <wim@iguana.be>. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
@@ -26,13 +26,15 @@ | |||
26 | * document number 301473-002, 301474-026: 82801F (ICH6) | 26 | * document number 301473-002, 301474-026: 82801F (ICH6) |
27 | * document number 313082-001, 313075-006: 631xESB, 632xESB | 27 | * document number 313082-001, 313075-006: 631xESB, 632xESB |
28 | * document number 307013-003, 307014-024: 82801G (ICH7) | 28 | * document number 307013-003, 307014-024: 82801G (ICH7) |
29 | * document number 322896-001, 322897-001: NM10 | ||
29 | * document number 313056-003, 313057-017: 82801H (ICH8) | 30 | * document number 313056-003, 313057-017: 82801H (ICH8) |
30 | * document number 316972-004, 316973-012: 82801I (ICH9) | 31 | * document number 316972-004, 316973-012: 82801I (ICH9) |
31 | * document number 319973-002, 319974-002: 82801J (ICH10) | 32 | * document number 319973-002, 319974-002: 82801J (ICH10) |
32 | * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) | 33 | * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) |
33 | * document number 320066-003, 320257-008: EP80597 (IICH) | 34 | * document number 320066-003, 320257-008: EP80597 (IICH) |
34 | * document number TBD : Cougar Point (CPT) | 35 | * document number 324645-001, 324646-001: Cougar Point (CPT) |
35 | * document number TBD : Patsburg (PBG) | 36 | * document number TBD : Patsburg (PBG) |
37 | * document number TBD : DH89xxCC | ||
36 | */ | 38 | */ |
37 | 39 | ||
38 | /* | 40 | /* |
@@ -85,6 +87,7 @@ enum iTCO_chipsets { | |||
85 | TCO_ICH7DH, /* ICH7DH */ | 87 | TCO_ICH7DH, /* ICH7DH */ |
86 | TCO_ICH7M, /* ICH7-M & ICH7-U */ | 88 | TCO_ICH7M, /* ICH7-M & ICH7-U */ |
87 | TCO_ICH7MDH, /* ICH7-M DH */ | 89 | TCO_ICH7MDH, /* ICH7-M DH */ |
90 | TCO_NM10, /* NM10 */ | ||
88 | TCO_ICH8, /* ICH8 & ICH8R */ | 91 | TCO_ICH8, /* ICH8 & ICH8R */ |
89 | TCO_ICH8DH, /* ICH8DH */ | 92 | TCO_ICH8DH, /* ICH8DH */ |
90 | TCO_ICH8DO, /* ICH8DO */ | 93 | TCO_ICH8DO, /* ICH8DO */ |
@@ -149,6 +152,7 @@ enum iTCO_chipsets { | |||
149 | TCO_CPT31, /* Cougar Point */ | 152 | TCO_CPT31, /* Cougar Point */ |
150 | TCO_PBG1, /* Patsburg */ | 153 | TCO_PBG1, /* Patsburg */ |
151 | TCO_PBG2, /* Patsburg */ | 154 | TCO_PBG2, /* Patsburg */ |
155 | TCO_DH89XXCC, /* DH89xxCC */ | ||
152 | }; | 156 | }; |
153 | 157 | ||
154 | static struct { | 158 | static struct { |
@@ -174,6 +178,7 @@ static struct { | |||
174 | {"ICH7DH", 2}, | 178 | {"ICH7DH", 2}, |
175 | {"ICH7-M or ICH7-U", 2}, | 179 | {"ICH7-M or ICH7-U", 2}, |
176 | {"ICH7-M DH", 2}, | 180 | {"ICH7-M DH", 2}, |
181 | {"NM10", 2}, | ||
177 | {"ICH8 or ICH8R", 2}, | 182 | {"ICH8 or ICH8R", 2}, |
178 | {"ICH8DH", 2}, | 183 | {"ICH8DH", 2}, |
179 | {"ICH8DO", 2}, | 184 | {"ICH8DO", 2}, |
@@ -238,6 +243,7 @@ static struct { | |||
238 | {"Cougar Point", 2}, | 243 | {"Cougar Point", 2}, |
239 | {"Patsburg", 2}, | 244 | {"Patsburg", 2}, |
240 | {"Patsburg", 2}, | 245 | {"Patsburg", 2}, |
246 | {"DH89xxCC", 2}, | ||
241 | {NULL, 0} | 247 | {NULL, 0} |
242 | }; | 248 | }; |
243 | 249 | ||
@@ -291,6 +297,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { | |||
291 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, | 297 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, |
292 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, | 298 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, |
293 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, | 299 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, |
300 | { ITCO_PCI_DEVICE(0x27bc, TCO_NM10)}, | ||
294 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, | 301 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, |
295 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, | 302 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, |
296 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, | 303 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, |
@@ -355,6 +362,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { | |||
355 | { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, | 362 | { ITCO_PCI_DEVICE(0x1c5f, TCO_CPT31)}, |
356 | { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)}, | 363 | { ITCO_PCI_DEVICE(0x1d40, TCO_PBG1)}, |
357 | { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)}, | 364 | { ITCO_PCI_DEVICE(0x1d41, TCO_PBG2)}, |
365 | { ITCO_PCI_DEVICE(0x2310, TCO_DH89XXCC)}, | ||
358 | { 0, }, /* End of list */ | 366 | { 0, }, /* End of list */ |
359 | }; | 367 | }; |
360 | MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); | 368 | MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); |
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index 2852bb2e3fd9..811471903e8a 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/watchdog.h> | 21 | #include <linux/watchdog.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <mach/timex.h> | 24 | #include <mach/hardware.h> |
25 | #include <mach/regs-timer.h> | 25 | #include <mach/regs-timer.h> |
26 | 26 | ||
27 | #define WDT_DEFAULT_TIME 5 /* seconds */ | 27 | #define WDT_DEFAULT_TIME 5 /* seconds */ |
diff --git a/drivers/watchdog/m548x_wdt.c b/drivers/watchdog/m548x_wdt.c new file mode 100644 index 000000000000..cabbcfe1c847 --- /dev/null +++ b/drivers/watchdog/m548x_wdt.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * drivers/watchdog/m548x_wdt.c | ||
3 | * | ||
4 | * Watchdog driver for ColdFire MCF548x processors | ||
5 | * Copyright 2010 (c) Philippe De Muyter <phdm@macqel.be> | ||
6 | * | ||
7 | * Adapted from the IXP4xx watchdog driver, which carries these notices: | ||
8 | * | ||
9 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
10 | * | ||
11 | * Copyright 2004 (c) MontaVista, Software, Inc. | ||
12 | * Based on sa1100 driver, Copyright (C) 2000 Oleg Drokin <green@crimea.edu> | ||
13 | * | ||
14 | * This file is licensed under the terms of the GNU General Public | ||
15 | * License version 2. This program is licensed "as is" without any | ||
16 | * warranty of any kind, whether express or implied. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/miscdevice.h> | ||
25 | #include <linux/watchdog.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/bitops.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | |||
31 | #include <asm/coldfire.h> | ||
32 | #include <asm/m548xsim.h> | ||
33 | #include <asm/m548xgpt.h> | ||
34 | |||
35 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
36 | static unsigned int heartbeat = 30; /* (secs) Default is 0.5 minute */ | ||
37 | static unsigned long wdt_status; | ||
38 | |||
39 | #define WDT_IN_USE 0 | ||
40 | #define WDT_OK_TO_CLOSE 1 | ||
41 | |||
42 | static void wdt_enable(void) | ||
43 | { | ||
44 | unsigned int gms0; | ||
45 | |||
46 | /* preserve GPIO usage, if any */ | ||
47 | gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); | ||
48 | if (gms0 & MCF_GPT_GMS_TMS_GPIO) | ||
49 | gms0 &= (MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_GPIO_MASK | ||
50 | | MCF_GPT_GMS_OD); | ||
51 | else | ||
52 | gms0 = MCF_GPT_GMS_TMS_GPIO | MCF_GPT_GMS_OD; | ||
53 | __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); | ||
54 | __raw_writel(MCF_GPT_GCIR_PRE(heartbeat*(MCF_BUSCLK/0xffff)) | | ||
55 | MCF_GPT_GCIR_CNT(0xffff), MCF_MBAR + MCF_GPT_GCIR0); | ||
56 | gms0 |= MCF_GPT_GMS_OCPW(0xA5) | MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE; | ||
57 | __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); | ||
58 | } | ||
59 | |||
60 | static void wdt_disable(void) | ||
61 | { | ||
62 | unsigned int gms0; | ||
63 | |||
64 | /* disable watchdog */ | ||
65 | gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); | ||
66 | gms0 &= ~(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE); | ||
67 | __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); | ||
68 | } | ||
69 | |||
70 | static void wdt_keepalive(void) | ||
71 | { | ||
72 | unsigned int gms0; | ||
73 | |||
74 | gms0 = __raw_readl(MCF_MBAR + MCF_GPT_GMS0); | ||
75 | gms0 |= MCF_GPT_GMS_OCPW(0xA5); | ||
76 | __raw_writel(gms0, MCF_MBAR + MCF_GPT_GMS0); | ||
77 | } | ||
78 | |||
79 | static int m548x_wdt_open(struct inode *inode, struct file *file) | ||
80 | { | ||
81 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
82 | return -EBUSY; | ||
83 | |||
84 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
85 | wdt_enable(); | ||
86 | return nonseekable_open(inode, file); | ||
87 | } | ||
88 | |||
89 | static ssize_t m548x_wdt_write(struct file *file, const char *data, | ||
90 | size_t len, loff_t *ppos) | ||
91 | { | ||
92 | if (len) { | ||
93 | if (!nowayout) { | ||
94 | size_t i; | ||
95 | |||
96 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
97 | |||
98 | for (i = 0; i != len; i++) { | ||
99 | char c; | ||
100 | |||
101 | if (get_user(c, data + i)) | ||
102 | return -EFAULT; | ||
103 | if (c == 'V') | ||
104 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
105 | } | ||
106 | } | ||
107 | wdt_keepalive(); | ||
108 | } | ||
109 | return len; | ||
110 | } | ||
111 | |||
112 | static const struct watchdog_info ident = { | ||
113 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | ||
114 | WDIOF_KEEPALIVEPING, | ||
115 | .identity = "Coldfire M548x Watchdog", | ||
116 | }; | ||
117 | |||
118 | static long m548x_wdt_ioctl(struct file *file, unsigned int cmd, | ||
119 | unsigned long arg) | ||
120 | { | ||
121 | int ret = -ENOTTY; | ||
122 | int time; | ||
123 | |||
124 | switch (cmd) { | ||
125 | case WDIOC_GETSUPPORT: | ||
126 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
127 | sizeof(ident)) ? -EFAULT : 0; | ||
128 | break; | ||
129 | |||
130 | case WDIOC_GETSTATUS: | ||
131 | ret = put_user(0, (int *)arg); | ||
132 | break; | ||
133 | |||
134 | case WDIOC_GETBOOTSTATUS: | ||
135 | ret = put_user(0, (int *)arg); | ||
136 | break; | ||
137 | |||
138 | case WDIOC_KEEPALIVE: | ||
139 | wdt_keepalive(); | ||
140 | ret = 0; | ||
141 | break; | ||
142 | |||
143 | case WDIOC_SETTIMEOUT: | ||
144 | ret = get_user(time, (int *)arg); | ||
145 | if (ret) | ||
146 | break; | ||
147 | |||
148 | if (time <= 0 || time > 30) { | ||
149 | ret = -EINVAL; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | heartbeat = time; | ||
154 | wdt_enable(); | ||
155 | /* Fall through */ | ||
156 | |||
157 | case WDIOC_GETTIMEOUT: | ||
158 | ret = put_user(heartbeat, (int *)arg); | ||
159 | break; | ||
160 | } | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static int m548x_wdt_release(struct inode *inode, struct file *file) | ||
165 | { | ||
166 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
167 | wdt_disable(); | ||
168 | else { | ||
169 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | ||
170 | "timer will not stop\n"); | ||
171 | wdt_keepalive(); | ||
172 | } | ||
173 | clear_bit(WDT_IN_USE, &wdt_status); | ||
174 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | |||
180 | static const struct file_operations m548x_wdt_fops = { | ||
181 | .owner = THIS_MODULE, | ||
182 | .llseek = no_llseek, | ||
183 | .write = m548x_wdt_write, | ||
184 | .unlocked_ioctl = m548x_wdt_ioctl, | ||
185 | .open = m548x_wdt_open, | ||
186 | .release = m548x_wdt_release, | ||
187 | }; | ||
188 | |||
189 | static struct miscdevice m548x_wdt_miscdev = { | ||
190 | .minor = WATCHDOG_MINOR, | ||
191 | .name = "watchdog", | ||
192 | .fops = &m548x_wdt_fops, | ||
193 | }; | ||
194 | |||
195 | static int __init m548x_wdt_init(void) | ||
196 | { | ||
197 | if (!request_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4, | ||
198 | "Coldfire M548x Watchdog")) { | ||
199 | printk(KERN_WARNING | ||
200 | "Coldfire M548x Watchdog : I/O region busy\n"); | ||
201 | return -EBUSY; | ||
202 | } | ||
203 | printk(KERN_INFO "ColdFire watchdog driver is loaded.\n"); | ||
204 | |||
205 | return misc_register(&m548x_wdt_miscdev); | ||
206 | } | ||
207 | |||
208 | static void __exit m548x_wdt_exit(void) | ||
209 | { | ||
210 | misc_deregister(&m548x_wdt_miscdev); | ||
211 | release_mem_region(MCF_MBAR + MCF_GPT_GCIR0, 4); | ||
212 | } | ||
213 | |||
214 | module_init(m548x_wdt_init); | ||
215 | module_exit(m548x_wdt_exit); | ||
216 | |||
217 | MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>"); | ||
218 | MODULE_DESCRIPTION("Coldfire M548x Watchdog"); | ||
219 | |||
220 | module_param(heartbeat, int, 0); | ||
221 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default 30s)"); | ||
222 | |||
223 | module_param(nowayout, int, 0); | ||
224 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
225 | |||
226 | MODULE_LICENSE("GPL"); | ||
227 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c new file mode 100644 index 000000000000..1a50aa7079bf --- /dev/null +++ b/drivers/watchdog/nv_tco.c | |||
@@ -0,0 +1,512 @@ | |||
1 | /* | ||
2 | * nv_tco 0.01: TCO timer driver for NV chipsets | ||
3 | * | ||
4 | * (c) Copyright 2005 Google Inc., All Rights Reserved. | ||
5 | * | ||
6 | * Based off i8xx_tco.c: | ||
7 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights | ||
8 | * Reserved. | ||
9 | * http://www.kernelconcepts.de | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | * | ||
16 | * TCO timer driver for NV chipsets | ||
17 | * based on softdog.c by Alan Cox <alan@redhat.com> | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * Includes, defines, variables, module parameters, ... | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/miscdevice.h> | ||
28 | #include <linux/watchdog.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/fs.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/ioport.h> | ||
33 | #include <linux/jiffies.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/uaccess.h> | ||
36 | #include <linux/io.h> | ||
37 | |||
38 | #include "nv_tco.h" | ||
39 | |||
40 | /* Module and version information */ | ||
41 | #define TCO_VERSION "0.01" | ||
42 | #define TCO_MODULE_NAME "NV_TCO" | ||
43 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION | ||
44 | #define PFX TCO_MODULE_NAME ": " | ||
45 | |||
46 | /* internal variables */ | ||
47 | static unsigned int tcobase; | ||
48 | static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ | ||
49 | static unsigned long timer_alive; | ||
50 | static char tco_expect_close; | ||
51 | static struct pci_dev *tco_pci; | ||
52 | |||
53 | /* the watchdog platform device */ | ||
54 | static struct platform_device *nv_tco_platform_device; | ||
55 | |||
56 | /* module parameters */ | ||
57 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2<heartbeat<39) */ | ||
58 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | ||
59 | module_param(heartbeat, int, 0); | ||
60 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, " | ||
61 | "default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | ||
62 | |||
63 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
64 | module_param(nowayout, int, 0); | ||
65 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started" | ||
66 | " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
67 | |||
68 | /* | ||
69 | * Some TCO specific functions | ||
70 | */ | ||
71 | static inline unsigned char seconds_to_ticks(int seconds) | ||
72 | { | ||
73 | /* the internal timer is stored as ticks which decrement | ||
74 | * every 0.6 seconds */ | ||
75 | return (seconds * 10) / 6; | ||
76 | } | ||
77 | |||
78 | static void tco_timer_start(void) | ||
79 | { | ||
80 | u32 val; | ||
81 | unsigned long flags; | ||
82 | |||
83 | spin_lock_irqsave(&tco_lock, flags); | ||
84 | val = inl(TCO_CNT(tcobase)); | ||
85 | val &= ~TCO_CNT_TCOHALT; | ||
86 | outl(val, TCO_CNT(tcobase)); | ||
87 | spin_unlock_irqrestore(&tco_lock, flags); | ||
88 | } | ||
89 | |||
90 | static void tco_timer_stop(void) | ||
91 | { | ||
92 | u32 val; | ||
93 | unsigned long flags; | ||
94 | |||
95 | spin_lock_irqsave(&tco_lock, flags); | ||
96 | val = inl(TCO_CNT(tcobase)); | ||
97 | val |= TCO_CNT_TCOHALT; | ||
98 | outl(val, TCO_CNT(tcobase)); | ||
99 | spin_unlock_irqrestore(&tco_lock, flags); | ||
100 | } | ||
101 | |||
102 | static void tco_timer_keepalive(void) | ||
103 | { | ||
104 | unsigned long flags; | ||
105 | |||
106 | spin_lock_irqsave(&tco_lock, flags); | ||
107 | outb(0x01, TCO_RLD(tcobase)); | ||
108 | spin_unlock_irqrestore(&tco_lock, flags); | ||
109 | } | ||
110 | |||
111 | static int tco_timer_set_heartbeat(int t) | ||
112 | { | ||
113 | int ret = 0; | ||
114 | unsigned char tmrval; | ||
115 | unsigned long flags; | ||
116 | u8 val; | ||
117 | |||
118 | /* | ||
119 | * note seconds_to_ticks(t) > t, so if t > 0x3f, so is | ||
120 | * tmrval=seconds_to_ticks(t). Check that the count in seconds isn't | ||
121 | * out of range on it's own (to avoid overflow in tmrval). | ||
122 | */ | ||
123 | if (t < 0 || t > 0x3f) | ||
124 | return -EINVAL; | ||
125 | tmrval = seconds_to_ticks(t); | ||
126 | |||
127 | /* "Values of 0h-3h are ignored and should not be attempted" */ | ||
128 | if (tmrval > 0x3f || tmrval < 0x04) | ||
129 | return -EINVAL; | ||
130 | |||
131 | /* Write new heartbeat to watchdog */ | ||
132 | spin_lock_irqsave(&tco_lock, flags); | ||
133 | val = inb(TCO_TMR(tcobase)); | ||
134 | val &= 0xc0; | ||
135 | val |= tmrval; | ||
136 | outb(val, TCO_TMR(tcobase)); | ||
137 | val = inb(TCO_TMR(tcobase)); | ||
138 | |||
139 | if ((val & 0x3f) != tmrval) | ||
140 | ret = -EINVAL; | ||
141 | spin_unlock_irqrestore(&tco_lock, flags); | ||
142 | |||
143 | if (ret) | ||
144 | return ret; | ||
145 | |||
146 | heartbeat = t; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /* | ||
151 | * /dev/watchdog handling | ||
152 | */ | ||
153 | |||
154 | static int nv_tco_open(struct inode *inode, struct file *file) | ||
155 | { | ||
156 | /* /dev/watchdog can only be opened once */ | ||
157 | if (test_and_set_bit(0, &timer_alive)) | ||
158 | return -EBUSY; | ||
159 | |||
160 | /* Reload and activate timer */ | ||
161 | tco_timer_keepalive(); | ||
162 | tco_timer_start(); | ||
163 | return nonseekable_open(inode, file); | ||
164 | } | ||
165 | |||
166 | static int nv_tco_release(struct inode *inode, struct file *file) | ||
167 | { | ||
168 | /* Shut off the timer */ | ||
169 | if (tco_expect_close == 42) { | ||
170 | tco_timer_stop(); | ||
171 | } else { | ||
172 | printk(KERN_CRIT PFX "Unexpected close, not stopping " | ||
173 | "watchdog!\n"); | ||
174 | tco_timer_keepalive(); | ||
175 | } | ||
176 | clear_bit(0, &timer_alive); | ||
177 | tco_expect_close = 0; | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static ssize_t nv_tco_write(struct file *file, const char __user *data, | ||
182 | size_t len, loff_t *ppos) | ||
183 | { | ||
184 | /* See if we got the magic character 'V' and reload the timer */ | ||
185 | if (len) { | ||
186 | if (!nowayout) { | ||
187 | size_t i; | ||
188 | |||
189 | /* | ||
190 | * note: just in case someone wrote the magic character | ||
191 | * five months ago... | ||
192 | */ | ||
193 | tco_expect_close = 0; | ||
194 | |||
195 | /* | ||
196 | * scan to see whether or not we got the magic | ||
197 | * character | ||
198 | */ | ||
199 | for (i = 0; i != len; i++) { | ||
200 | char c; | ||
201 | if (get_user(c, data + i)) | ||
202 | return -EFAULT; | ||
203 | if (c == 'V') | ||
204 | tco_expect_close = 42; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | /* someone wrote to us, we should reload the timer */ | ||
209 | tco_timer_keepalive(); | ||
210 | } | ||
211 | return len; | ||
212 | } | ||
213 | |||
214 | static long nv_tco_ioctl(struct file *file, unsigned int cmd, | ||
215 | unsigned long arg) | ||
216 | { | ||
217 | int new_options, retval = -EINVAL; | ||
218 | int new_heartbeat; | ||
219 | void __user *argp = (void __user *)arg; | ||
220 | int __user *p = argp; | ||
221 | static const struct watchdog_info ident = { | ||
222 | .options = WDIOF_SETTIMEOUT | | ||
223 | WDIOF_KEEPALIVEPING | | ||
224 | WDIOF_MAGICCLOSE, | ||
225 | .firmware_version = 0, | ||
226 | .identity = TCO_MODULE_NAME, | ||
227 | }; | ||
228 | |||
229 | switch (cmd) { | ||
230 | case WDIOC_GETSUPPORT: | ||
231 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
232 | case WDIOC_GETSTATUS: | ||
233 | case WDIOC_GETBOOTSTATUS: | ||
234 | return put_user(0, p); | ||
235 | case WDIOC_SETOPTIONS: | ||
236 | if (get_user(new_options, p)) | ||
237 | return -EFAULT; | ||
238 | if (new_options & WDIOS_DISABLECARD) { | ||
239 | tco_timer_stop(); | ||
240 | retval = 0; | ||
241 | } | ||
242 | if (new_options & WDIOS_ENABLECARD) { | ||
243 | tco_timer_keepalive(); | ||
244 | tco_timer_start(); | ||
245 | retval = 0; | ||
246 | } | ||
247 | return retval; | ||
248 | case WDIOC_KEEPALIVE: | ||
249 | tco_timer_keepalive(); | ||
250 | return 0; | ||
251 | case WDIOC_SETTIMEOUT: | ||
252 | if (get_user(new_heartbeat, p)) | ||
253 | return -EFAULT; | ||
254 | if (tco_timer_set_heartbeat(new_heartbeat)) | ||
255 | return -EINVAL; | ||
256 | tco_timer_keepalive(); | ||
257 | /* Fall through */ | ||
258 | case WDIOC_GETTIMEOUT: | ||
259 | return put_user(heartbeat, p); | ||
260 | default: | ||
261 | return -ENOTTY; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Kernel Interfaces | ||
267 | */ | ||
268 | |||
269 | static const struct file_operations nv_tco_fops = { | ||
270 | .owner = THIS_MODULE, | ||
271 | .llseek = no_llseek, | ||
272 | .write = nv_tco_write, | ||
273 | .unlocked_ioctl = nv_tco_ioctl, | ||
274 | .open = nv_tco_open, | ||
275 | .release = nv_tco_release, | ||
276 | }; | ||
277 | |||
278 | static struct miscdevice nv_tco_miscdev = { | ||
279 | .minor = WATCHDOG_MINOR, | ||
280 | .name = "watchdog", | ||
281 | .fops = &nv_tco_fops, | ||
282 | }; | ||
283 | |||
284 | /* | ||
285 | * Data for PCI driver interface | ||
286 | * | ||
287 | * This data only exists for exporting the supported | ||
288 | * PCI ids via MODULE_DEVICE_TABLE. We do not actually | ||
289 | * register a pci_driver, because someone else might one day | ||
290 | * want to register another driver on the same PCI id. | ||
291 | */ | ||
292 | static struct pci_device_id tco_pci_tbl[] = { | ||
293 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS, | ||
294 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
295 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS, | ||
296 | PCI_ANY_ID, PCI_ANY_ID, }, | ||
297 | { 0, }, /* End of list */ | ||
298 | }; | ||
299 | MODULE_DEVICE_TABLE(pci, tco_pci_tbl); | ||
300 | |||
301 | /* | ||
302 | * Init & exit routines | ||
303 | */ | ||
304 | |||
305 | static unsigned char __init nv_tco_getdevice(void) | ||
306 | { | ||
307 | struct pci_dev *dev = NULL; | ||
308 | u32 val; | ||
309 | |||
310 | /* Find the PCI device */ | ||
311 | for_each_pci_dev(dev) { | ||
312 | if (pci_match_id(tco_pci_tbl, dev) != NULL) { | ||
313 | tco_pci = dev; | ||
314 | break; | ||
315 | } | ||
316 | } | ||
317 | |||
318 | if (!tco_pci) | ||
319 | return 0; | ||
320 | |||
321 | /* Find the base io port */ | ||
322 | pci_read_config_dword(tco_pci, 0x64, &val); | ||
323 | val &= 0xffff; | ||
324 | if (val == 0x0001 || val == 0x0000) { | ||
325 | /* Something is wrong here, bar isn't setup */ | ||
326 | printk(KERN_ERR PFX "failed to get tcobase address\n"); | ||
327 | return 0; | ||
328 | } | ||
329 | val &= 0xff00; | ||
330 | tcobase = val + 0x40; | ||
331 | |||
332 | if (!request_region(tcobase, 0x10, "NV TCO")) { | ||
333 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
334 | tcobase); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /* Set a reasonable heartbeat before we stop the timer */ | ||
339 | tco_timer_set_heartbeat(30); | ||
340 | |||
341 | /* | ||
342 | * Stop the TCO before we change anything so we don't race with | ||
343 | * a zeroed timer. | ||
344 | */ | ||
345 | tco_timer_keepalive(); | ||
346 | tco_timer_stop(); | ||
347 | |||
348 | /* Disable SMI caused by TCO */ | ||
349 | if (!request_region(MCP51_SMI_EN(tcobase), 4, "NV TCO")) { | ||
350 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
351 | MCP51_SMI_EN(tcobase)); | ||
352 | goto out; | ||
353 | } | ||
354 | val = inl(MCP51_SMI_EN(tcobase)); | ||
355 | val &= ~MCP51_SMI_EN_TCO; | ||
356 | outl(val, MCP51_SMI_EN(tcobase)); | ||
357 | val = inl(MCP51_SMI_EN(tcobase)); | ||
358 | release_region(MCP51_SMI_EN(tcobase), 4); | ||
359 | if (val & MCP51_SMI_EN_TCO) { | ||
360 | printk(KERN_ERR PFX "Could not disable SMI caused by TCO\n"); | ||
361 | goto out; | ||
362 | } | ||
363 | |||
364 | /* Check chipset's NO_REBOOT bit */ | ||
365 | pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val); | ||
366 | val |= MCP51_SMBUS_SETUP_B_TCO_REBOOT; | ||
367 | pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val); | ||
368 | pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val); | ||
369 | if (!(val & MCP51_SMBUS_SETUP_B_TCO_REBOOT)) { | ||
370 | printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot " | ||
371 | "disabled by hardware\n"); | ||
372 | goto out; | ||
373 | } | ||
374 | |||
375 | return 1; | ||
376 | out: | ||
377 | release_region(tcobase, 0x10); | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int __devinit nv_tco_init(struct platform_device *dev) | ||
382 | { | ||
383 | int ret; | ||
384 | |||
385 | /* Check whether or not the hardware watchdog is there */ | ||
386 | if (!nv_tco_getdevice()) | ||
387 | return -ENODEV; | ||
388 | |||
389 | /* Check to see if last reboot was due to watchdog timeout */ | ||
390 | printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n", | ||
391 | inl(TCO_STS(tcobase)) & TCO_STS_TCO2TO_STS ? "" : "not "); | ||
392 | |||
393 | /* Clear out the old status */ | ||
394 | outl(TCO_STS_RESET, TCO_STS(tcobase)); | ||
395 | |||
396 | /* | ||
397 | * Check that the heartbeat value is within it's range. | ||
398 | * If not, reset to the default. | ||
399 | */ | ||
400 | if (tco_timer_set_heartbeat(heartbeat)) { | ||
401 | heartbeat = WATCHDOG_HEARTBEAT; | ||
402 | tco_timer_set_heartbeat(heartbeat); | ||
403 | printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39, " | ||
404 | "using %d\n", heartbeat); | ||
405 | } | ||
406 | |||
407 | ret = misc_register(&nv_tco_miscdev); | ||
408 | if (ret != 0) { | ||
409 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d " | ||
410 | "(err=%d)\n", WATCHDOG_MINOR, ret); | ||
411 | goto unreg_region; | ||
412 | } | ||
413 | |||
414 | clear_bit(0, &timer_alive); | ||
415 | |||
416 | tco_timer_stop(); | ||
417 | |||
418 | printk(KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec " | ||
419 | "(nowayout=%d)\n", tcobase, heartbeat, nowayout); | ||
420 | |||
421 | return 0; | ||
422 | |||
423 | unreg_region: | ||
424 | release_region(tcobase, 0x10); | ||
425 | return ret; | ||
426 | } | ||
427 | |||
428 | static void __devexit nv_tco_cleanup(void) | ||
429 | { | ||
430 | u32 val; | ||
431 | |||
432 | /* Stop the timer before we leave */ | ||
433 | if (!nowayout) | ||
434 | tco_timer_stop(); | ||
435 | |||
436 | /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ | ||
437 | pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val); | ||
438 | val &= ~MCP51_SMBUS_SETUP_B_TCO_REBOOT; | ||
439 | pci_write_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, val); | ||
440 | pci_read_config_dword(tco_pci, MCP51_SMBUS_SETUP_B, &val); | ||
441 | if (val & MCP51_SMBUS_SETUP_B_TCO_REBOOT) { | ||
442 | printk(KERN_CRIT PFX "Couldn't unset REBOOT bit. Machine may " | ||
443 | "soon reset\n"); | ||
444 | } | ||
445 | |||
446 | /* Deregister */ | ||
447 | misc_deregister(&nv_tco_miscdev); | ||
448 | release_region(tcobase, 0x10); | ||
449 | } | ||
450 | |||
451 | static int __devexit nv_tco_remove(struct platform_device *dev) | ||
452 | { | ||
453 | if (tcobase) | ||
454 | nv_tco_cleanup(); | ||
455 | |||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static void nv_tco_shutdown(struct platform_device *dev) | ||
460 | { | ||
461 | tco_timer_stop(); | ||
462 | } | ||
463 | |||
464 | static struct platform_driver nv_tco_driver = { | ||
465 | .probe = nv_tco_init, | ||
466 | .remove = __devexit_p(nv_tco_remove), | ||
467 | .shutdown = nv_tco_shutdown, | ||
468 | .driver = { | ||
469 | .owner = THIS_MODULE, | ||
470 | .name = TCO_MODULE_NAME, | ||
471 | }, | ||
472 | }; | ||
473 | |||
474 | static int __init nv_tco_init_module(void) | ||
475 | { | ||
476 | int err; | ||
477 | |||
478 | printk(KERN_INFO PFX "NV TCO WatchDog Timer Driver v%s\n", | ||
479 | TCO_VERSION); | ||
480 | |||
481 | err = platform_driver_register(&nv_tco_driver); | ||
482 | if (err) | ||
483 | return err; | ||
484 | |||
485 | nv_tco_platform_device = platform_device_register_simple( | ||
486 | TCO_MODULE_NAME, -1, NULL, 0); | ||
487 | if (IS_ERR(nv_tco_platform_device)) { | ||
488 | err = PTR_ERR(nv_tco_platform_device); | ||
489 | goto unreg_platform_driver; | ||
490 | } | ||
491 | |||
492 | return 0; | ||
493 | |||
494 | unreg_platform_driver: | ||
495 | platform_driver_unregister(&nv_tco_driver); | ||
496 | return err; | ||
497 | } | ||
498 | |||
499 | static void __exit nv_tco_cleanup_module(void) | ||
500 | { | ||
501 | platform_device_unregister(nv_tco_platform_device); | ||
502 | platform_driver_unregister(&nv_tco_driver); | ||
503 | printk(KERN_INFO PFX "NV TCO Watchdog Module Unloaded.\n"); | ||
504 | } | ||
505 | |||
506 | module_init(nv_tco_init_module); | ||
507 | module_exit(nv_tco_cleanup_module); | ||
508 | |||
509 | MODULE_AUTHOR("Mike Waychison"); | ||
510 | MODULE_DESCRIPTION("TCO timer driver for NV chipsets"); | ||
511 | MODULE_LICENSE("GPL"); | ||
512 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/nv_tco.h b/drivers/watchdog/nv_tco.h new file mode 100644 index 000000000000..c2d1d04e055b --- /dev/null +++ b/drivers/watchdog/nv_tco.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * nv_tco: TCO timer driver for nVidia chipsets. | ||
3 | * | ||
4 | * (c) Copyright 2005 Google Inc., All Rights Reserved. | ||
5 | * | ||
6 | * Supported Chipsets: | ||
7 | * - MCP51/MCP55 | ||
8 | * | ||
9 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights | ||
10 | * Reserved. | ||
11 | * http://www.kernelconcepts.de | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version | ||
16 | * 2 of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * Neither kernel concepts nor Nils Faerber admit liability nor provide | ||
19 | * warranty for any of this software. This material is provided | ||
20 | * "AS-IS" and at no charge. | ||
21 | * | ||
22 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de> | ||
23 | * developed for | ||
24 | * Jentro AG, Haar/Munich (Germany) | ||
25 | * | ||
26 | * TCO timer driver for NV chipsets | ||
27 | * based on softdog.c by Alan Cox <alan@redhat.com> | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Some address definitions for the TCO | ||
32 | */ | ||
33 | |||
34 | #define TCO_RLD(base) ((base) + 0x00) /* TCO Timer Reload and Current Value */ | ||
35 | #define TCO_TMR(base) ((base) + 0x01) /* TCO Timer Initial Value */ | ||
36 | |||
37 | #define TCO_STS(base) ((base) + 0x04) /* TCO Status Register */ | ||
38 | /* | ||
39 | * TCO Boot Status bit: set on TCO reset, reset by software or standby | ||
40 | * power-good (survives reboots), unfortunately this bit is never | ||
41 | * set. | ||
42 | */ | ||
43 | # define TCO_STS_BOOT_STS (1 << 9) | ||
44 | /* | ||
45 | * first and 2nd timeout status bits, these also survive a warm boot, | ||
46 | * and they work, so we use them. | ||
47 | */ | ||
48 | # define TCO_STS_TCO_INT_STS (1 << 1) | ||
49 | # define TCO_STS_TCO2TO_STS (1 << 10) | ||
50 | # define TCO_STS_RESET (TCO_STS_BOOT_STS | TCO_STS_TCO2TO_STS | \ | ||
51 | TCO_STS_TCO_INT_STS) | ||
52 | |||
53 | #define TCO_CNT(base) ((base) + 0x08) /* TCO Control Register */ | ||
54 | # define TCO_CNT_TCOHALT (1 << 12) | ||
55 | |||
56 | #define MCP51_SMBUS_SETUP_B 0xe8 | ||
57 | # define MCP51_SMBUS_SETUP_B_TCO_REBOOT (1 << 25) | ||
58 | |||
59 | /* | ||
60 | * The SMI_EN register is at the base io address + 0x04, | ||
61 | * while TCOBASE is + 0x40. | ||
62 | */ | ||
63 | #define MCP51_SMI_EN(base) ((base) - 0x40 + 0x04) | ||
64 | # define MCP51_SMI_EN_TCO ((1 << 4) | (1 << 5)) | ||
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c new file mode 100644 index 000000000000..808372883e88 --- /dev/null +++ b/drivers/watchdog/sp5100_tco.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * sp5100_tco : TCO timer driver for sp5100 chipsets | ||
3 | * | ||
4 | * (c) Copyright 2009 Google Inc., All Rights Reserved. | ||
5 | * | ||
6 | * Based on i8xx_tco.c: | ||
7 | * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights | ||
8 | * Reserved. | ||
9 | * http://www.kernelconcepts.de | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | * | ||
16 | * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide" | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * Includes, defines, variables, module parameters, ... | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/miscdevice.h> | ||
27 | #include <linux/watchdog.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/fs.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/uaccess.h> | ||
34 | #include <linux/io.h> | ||
35 | |||
36 | #include "sp5100_tco.h" | ||
37 | |||
38 | /* Module and version information */ | ||
39 | #define TCO_VERSION "0.01" | ||
40 | #define TCO_MODULE_NAME "SP5100 TCO timer" | ||
41 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION | ||
42 | #define PFX TCO_MODULE_NAME ": " | ||
43 | |||
44 | /* internal variables */ | ||
45 | static void __iomem *tcobase; | ||
46 | static unsigned int pm_iobase; | ||
47 | static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ | ||
48 | static unsigned long timer_alive; | ||
49 | static char tco_expect_close; | ||
50 | static struct pci_dev *sp5100_tco_pci; | ||
51 | |||
52 | /* the watchdog platform device */ | ||
53 | static struct platform_device *sp5100_tco_platform_device; | ||
54 | |||
55 | /* module parameters */ | ||
56 | |||
57 | #define WATCHDOG_HEARTBEAT 60 /* 60 sec default heartbeat. */ | ||
58 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | ||
59 | module_param(heartbeat, int, 0); | ||
60 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default=" | ||
61 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | ||
62 | |||
63 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
64 | module_param(nowayout, int, 0); | ||
65 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started" | ||
66 | " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
67 | |||
68 | /* | ||
69 | * Some TCO specific functions | ||
70 | */ | ||
71 | static void tco_timer_start(void) | ||
72 | { | ||
73 | u32 val; | ||
74 | unsigned long flags; | ||
75 | |||
76 | spin_lock_irqsave(&tco_lock, flags); | ||
77 | val = readl(SP5100_WDT_CONTROL(tcobase)); | ||
78 | val |= SP5100_WDT_START_STOP_BIT; | ||
79 | writel(val, SP5100_WDT_CONTROL(tcobase)); | ||
80 | spin_unlock_irqrestore(&tco_lock, flags); | ||
81 | } | ||
82 | |||
83 | static void tco_timer_stop(void) | ||
84 | { | ||
85 | u32 val; | ||
86 | unsigned long flags; | ||
87 | |||
88 | spin_lock_irqsave(&tco_lock, flags); | ||
89 | val = readl(SP5100_WDT_CONTROL(tcobase)); | ||
90 | val &= ~SP5100_WDT_START_STOP_BIT; | ||
91 | writel(val, SP5100_WDT_CONTROL(tcobase)); | ||
92 | spin_unlock_irqrestore(&tco_lock, flags); | ||
93 | } | ||
94 | |||
95 | static void tco_timer_keepalive(void) | ||
96 | { | ||
97 | u32 val; | ||
98 | unsigned long flags; | ||
99 | |||
100 | spin_lock_irqsave(&tco_lock, flags); | ||
101 | val = readl(SP5100_WDT_CONTROL(tcobase)); | ||
102 | val |= SP5100_WDT_TRIGGER_BIT; | ||
103 | writel(val, SP5100_WDT_CONTROL(tcobase)); | ||
104 | spin_unlock_irqrestore(&tco_lock, flags); | ||
105 | } | ||
106 | |||
107 | static int tco_timer_set_heartbeat(int t) | ||
108 | { | ||
109 | unsigned long flags; | ||
110 | |||
111 | if (t < 0 || t > 0xffff) | ||
112 | return -EINVAL; | ||
113 | |||
114 | /* Write new heartbeat to watchdog */ | ||
115 | spin_lock_irqsave(&tco_lock, flags); | ||
116 | writel(t, SP5100_WDT_COUNT(tcobase)); | ||
117 | spin_unlock_irqrestore(&tco_lock, flags); | ||
118 | |||
119 | heartbeat = t; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * /dev/watchdog handling | ||
125 | */ | ||
126 | |||
127 | static int sp5100_tco_open(struct inode *inode, struct file *file) | ||
128 | { | ||
129 | /* /dev/watchdog can only be opened once */ | ||
130 | if (test_and_set_bit(0, &timer_alive)) | ||
131 | return -EBUSY; | ||
132 | |||
133 | /* Reload and activate timer */ | ||
134 | tco_timer_start(); | ||
135 | tco_timer_keepalive(); | ||
136 | return nonseekable_open(inode, file); | ||
137 | } | ||
138 | |||
139 | static int sp5100_tco_release(struct inode *inode, struct file *file) | ||
140 | { | ||
141 | /* Shut off the timer. */ | ||
142 | if (tco_expect_close == 42) { | ||
143 | tco_timer_stop(); | ||
144 | } else { | ||
145 | printk(KERN_CRIT PFX | ||
146 | "Unexpected close, not stopping watchdog!\n"); | ||
147 | tco_timer_keepalive(); | ||
148 | } | ||
149 | clear_bit(0, &timer_alive); | ||
150 | tco_expect_close = 0; | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static ssize_t sp5100_tco_write(struct file *file, const char __user *data, | ||
155 | size_t len, loff_t *ppos) | ||
156 | { | ||
157 | /* See if we got the magic character 'V' and reload the timer */ | ||
158 | if (len) { | ||
159 | if (!nowayout) { | ||
160 | size_t i; | ||
161 | |||
162 | /* note: just in case someone wrote the magic character | ||
163 | * five months ago... */ | ||
164 | tco_expect_close = 0; | ||
165 | |||
166 | /* scan to see whether or not we got the magic character | ||
167 | */ | ||
168 | for (i = 0; i != len; i++) { | ||
169 | char c; | ||
170 | if (get_user(c, data + i)) | ||
171 | return -EFAULT; | ||
172 | if (c == 'V') | ||
173 | tco_expect_close = 42; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* someone wrote to us, we should reload the timer */ | ||
178 | tco_timer_keepalive(); | ||
179 | } | ||
180 | return len; | ||
181 | } | ||
182 | |||
183 | static long sp5100_tco_ioctl(struct file *file, unsigned int cmd, | ||
184 | unsigned long arg) | ||
185 | { | ||
186 | int new_options, retval = -EINVAL; | ||
187 | int new_heartbeat; | ||
188 | void __user *argp = (void __user *)arg; | ||
189 | int __user *p = argp; | ||
190 | static const struct watchdog_info ident = { | ||
191 | .options = WDIOF_SETTIMEOUT | | ||
192 | WDIOF_KEEPALIVEPING | | ||
193 | WDIOF_MAGICCLOSE, | ||
194 | .firmware_version = 0, | ||
195 | .identity = TCO_MODULE_NAME, | ||
196 | }; | ||
197 | |||
198 | switch (cmd) { | ||
199 | case WDIOC_GETSUPPORT: | ||
200 | return copy_to_user(argp, &ident, | ||
201 | sizeof(ident)) ? -EFAULT : 0; | ||
202 | case WDIOC_GETSTATUS: | ||
203 | case WDIOC_GETBOOTSTATUS: | ||
204 | return put_user(0, p); | ||
205 | case WDIOC_SETOPTIONS: | ||
206 | if (get_user(new_options, p)) | ||
207 | return -EFAULT; | ||
208 | if (new_options & WDIOS_DISABLECARD) { | ||
209 | tco_timer_stop(); | ||
210 | retval = 0; | ||
211 | } | ||
212 | if (new_options & WDIOS_ENABLECARD) { | ||
213 | tco_timer_start(); | ||
214 | tco_timer_keepalive(); | ||
215 | retval = 0; | ||
216 | } | ||
217 | return retval; | ||
218 | case WDIOC_KEEPALIVE: | ||
219 | tco_timer_keepalive(); | ||
220 | return 0; | ||
221 | case WDIOC_SETTIMEOUT: | ||
222 | if (get_user(new_heartbeat, p)) | ||
223 | return -EFAULT; | ||
224 | if (tco_timer_set_heartbeat(new_heartbeat)) | ||
225 | return -EINVAL; | ||
226 | tco_timer_keepalive(); | ||
227 | /* Fall through */ | ||
228 | case WDIOC_GETTIMEOUT: | ||
229 | return put_user(heartbeat, p); | ||
230 | default: | ||
231 | return -ENOTTY; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * Kernel Interfaces | ||
237 | */ | ||
238 | |||
239 | static const struct file_operations sp5100_tco_fops = { | ||
240 | .owner = THIS_MODULE, | ||
241 | .llseek = no_llseek, | ||
242 | .write = sp5100_tco_write, | ||
243 | .unlocked_ioctl = sp5100_tco_ioctl, | ||
244 | .open = sp5100_tco_open, | ||
245 | .release = sp5100_tco_release, | ||
246 | }; | ||
247 | |||
248 | static struct miscdevice sp5100_tco_miscdev = { | ||
249 | .minor = WATCHDOG_MINOR, | ||
250 | .name = "watchdog", | ||
251 | .fops = &sp5100_tco_fops, | ||
252 | }; | ||
253 | |||
254 | /* | ||
255 | * Data for PCI driver interface | ||
256 | * | ||
257 | * This data only exists for exporting the supported | ||
258 | * PCI ids via MODULE_DEVICE_TABLE. We do not actually | ||
259 | * register a pci_driver, because someone else might | ||
260 | * want to register another driver on the same PCI id. | ||
261 | */ | ||
262 | static struct pci_device_id sp5100_tco_pci_tbl[] = { | ||
263 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, | ||
264 | PCI_ANY_ID, }, | ||
265 | { 0, }, /* End of list */ | ||
266 | }; | ||
267 | MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl); | ||
268 | |||
269 | /* | ||
270 | * Init & exit routines | ||
271 | */ | ||
272 | |||
273 | static unsigned char __devinit sp5100_tco_setupdevice(void) | ||
274 | { | ||
275 | struct pci_dev *dev = NULL; | ||
276 | u32 val; | ||
277 | |||
278 | /* Match the PCI device */ | ||
279 | for_each_pci_dev(dev) { | ||
280 | if (pci_match_id(sp5100_tco_pci_tbl, dev) != NULL) { | ||
281 | sp5100_tco_pci = dev; | ||
282 | break; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | if (!sp5100_tco_pci) | ||
287 | return 0; | ||
288 | |||
289 | /* Request the IO ports used by this driver */ | ||
290 | pm_iobase = SP5100_IO_PM_INDEX_REG; | ||
291 | if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) { | ||
292 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
293 | pm_iobase); | ||
294 | goto exit; | ||
295 | } | ||
296 | |||
297 | /* Find the watchdog base address. */ | ||
298 | outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG); | ||
299 | val = inb(SP5100_IO_PM_DATA_REG); | ||
300 | outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG); | ||
301 | val = val << 8 | inb(SP5100_IO_PM_DATA_REG); | ||
302 | outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG); | ||
303 | val = val << 8 | inb(SP5100_IO_PM_DATA_REG); | ||
304 | outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG); | ||
305 | /* Low three bits of BASE0 are reserved. */ | ||
306 | val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8); | ||
307 | |||
308 | tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); | ||
309 | if (tcobase == 0) { | ||
310 | printk(KERN_ERR PFX "failed to get tcobase address\n"); | ||
311 | goto unreg_region; | ||
312 | } | ||
313 | |||
314 | /* Enable watchdog decode bit */ | ||
315 | pci_read_config_dword(sp5100_tco_pci, | ||
316 | SP5100_PCI_WATCHDOG_MISC_REG, | ||
317 | &val); | ||
318 | |||
319 | val |= SP5100_PCI_WATCHDOG_DECODE_EN; | ||
320 | |||
321 | pci_write_config_dword(sp5100_tco_pci, | ||
322 | SP5100_PCI_WATCHDOG_MISC_REG, | ||
323 | val); | ||
324 | |||
325 | /* Enable Watchdog timer and set the resolution to 1 sec. */ | ||
326 | outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG); | ||
327 | val = inb(SP5100_IO_PM_DATA_REG); | ||
328 | val |= SP5100_PM_WATCHDOG_SECOND_RES; | ||
329 | val &= ~SP5100_PM_WATCHDOG_DISABLE; | ||
330 | outb(val, SP5100_IO_PM_DATA_REG); | ||
331 | |||
332 | /* Check that the watchdog action is set to reset the system. */ | ||
333 | val = readl(SP5100_WDT_CONTROL(tcobase)); | ||
334 | val &= ~SP5100_PM_WATCHDOG_ACTION_RESET; | ||
335 | writel(val, SP5100_WDT_CONTROL(tcobase)); | ||
336 | |||
337 | /* Set a reasonable heartbeat before we stop the timer */ | ||
338 | tco_timer_set_heartbeat(heartbeat); | ||
339 | |||
340 | /* | ||
341 | * Stop the TCO before we change anything so we don't race with | ||
342 | * a zeroed timer. | ||
343 | */ | ||
344 | tco_timer_stop(); | ||
345 | |||
346 | /* Done */ | ||
347 | return 1; | ||
348 | |||
349 | iounmap(tcobase); | ||
350 | unreg_region: | ||
351 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); | ||
352 | exit: | ||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static int __devinit sp5100_tco_init(struct platform_device *dev) | ||
357 | { | ||
358 | int ret; | ||
359 | u32 val; | ||
360 | |||
361 | /* Check whether or not the hardware watchdog is there. If found, then | ||
362 | * set it up. | ||
363 | */ | ||
364 | if (!sp5100_tco_setupdevice()) | ||
365 | return -ENODEV; | ||
366 | |||
367 | /* Check to see if last reboot was due to watchdog timeout */ | ||
368 | printk(KERN_INFO PFX "Watchdog reboot %sdetected.\n", | ||
369 | readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ? | ||
370 | "" : "not "); | ||
371 | |||
372 | /* Clear out the old status */ | ||
373 | val = readl(SP5100_WDT_CONTROL(tcobase)); | ||
374 | val &= ~SP5100_PM_WATCHDOG_FIRED; | ||
375 | writel(val, SP5100_WDT_CONTROL(tcobase)); | ||
376 | |||
377 | /* | ||
378 | * Check that the heartbeat value is within it's range. | ||
379 | * If not, reset to the default. | ||
380 | */ | ||
381 | if (tco_timer_set_heartbeat(heartbeat)) { | ||
382 | heartbeat = WATCHDOG_HEARTBEAT; | ||
383 | tco_timer_set_heartbeat(heartbeat); | ||
384 | } | ||
385 | |||
386 | ret = misc_register(&sp5100_tco_miscdev); | ||
387 | if (ret != 0) { | ||
388 | printk(KERN_ERR PFX "cannot register miscdev on minor=" | ||
389 | "%d (err=%d)\n", | ||
390 | WATCHDOG_MINOR, ret); | ||
391 | goto exit; | ||
392 | } | ||
393 | |||
394 | clear_bit(0, &timer_alive); | ||
395 | |||
396 | printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec" | ||
397 | " (nowayout=%d)\n", | ||
398 | tcobase, heartbeat, nowayout); | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | exit: | ||
403 | iounmap(tcobase); | ||
404 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | static void __devexit sp5100_tco_cleanup(void) | ||
409 | { | ||
410 | /* Stop the timer before we leave */ | ||
411 | if (!nowayout) | ||
412 | tco_timer_stop(); | ||
413 | |||
414 | /* Deregister */ | ||
415 | misc_deregister(&sp5100_tco_miscdev); | ||
416 | iounmap(tcobase); | ||
417 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); | ||
418 | } | ||
419 | |||
420 | static int __devexit sp5100_tco_remove(struct platform_device *dev) | ||
421 | { | ||
422 | if (tcobase) | ||
423 | sp5100_tco_cleanup(); | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static void sp5100_tco_shutdown(struct platform_device *dev) | ||
428 | { | ||
429 | tco_timer_stop(); | ||
430 | } | ||
431 | |||
432 | static struct platform_driver sp5100_tco_driver = { | ||
433 | .probe = sp5100_tco_init, | ||
434 | .remove = __devexit_p(sp5100_tco_remove), | ||
435 | .shutdown = sp5100_tco_shutdown, | ||
436 | .driver = { | ||
437 | .owner = THIS_MODULE, | ||
438 | .name = TCO_MODULE_NAME, | ||
439 | }, | ||
440 | }; | ||
441 | |||
442 | static int __init sp5100_tco_init_module(void) | ||
443 | { | ||
444 | int err; | ||
445 | |||
446 | printk(KERN_INFO PFX "SP5100 TCO WatchDog Timer Driver v%s\n", | ||
447 | TCO_VERSION); | ||
448 | |||
449 | err = platform_driver_register(&sp5100_tco_driver); | ||
450 | if (err) | ||
451 | return err; | ||
452 | |||
453 | sp5100_tco_platform_device = platform_device_register_simple( | ||
454 | TCO_MODULE_NAME, -1, NULL, 0); | ||
455 | if (IS_ERR(sp5100_tco_platform_device)) { | ||
456 | err = PTR_ERR(sp5100_tco_platform_device); | ||
457 | goto unreg_platform_driver; | ||
458 | } | ||
459 | |||
460 | return 0; | ||
461 | |||
462 | unreg_platform_driver: | ||
463 | platform_driver_unregister(&sp5100_tco_driver); | ||
464 | return err; | ||
465 | } | ||
466 | |||
467 | static void __exit sp5100_tco_cleanup_module(void) | ||
468 | { | ||
469 | platform_device_unregister(sp5100_tco_platform_device); | ||
470 | platform_driver_unregister(&sp5100_tco_driver); | ||
471 | printk(KERN_INFO PFX "SP5100 TCO Watchdog Module Unloaded.\n"); | ||
472 | } | ||
473 | |||
474 | module_init(sp5100_tco_init_module); | ||
475 | module_exit(sp5100_tco_cleanup_module); | ||
476 | |||
477 | MODULE_AUTHOR("Priyanka Gupta"); | ||
478 | MODULE_DESCRIPTION("TCO timer driver for SP5100 chipset"); | ||
479 | MODULE_LICENSE("GPL"); | ||
480 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/sp5100_tco.h b/drivers/watchdog/sp5100_tco.h new file mode 100644 index 000000000000..a5a16cc90a34 --- /dev/null +++ b/drivers/watchdog/sp5100_tco.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * sp5100_tco: TCO timer driver for sp5100 chipsets. | ||
3 | * | ||
4 | * (c) Copyright 2009 Google Inc., All Rights Reserved. | ||
5 | * | ||
6 | * TCO timer driver for sp5100 chipsets | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Some address definitions for the Watchdog | ||
11 | */ | ||
12 | |||
13 | #define SP5100_WDT_MEM_MAP_SIZE 0x08 | ||
14 | #define SP5100_WDT_CONTROL(base) ((base) + 0x00) /* Watchdog Control */ | ||
15 | #define SP5100_WDT_COUNT(base) ((base) + 0x04) /* Watchdog Count */ | ||
16 | |||
17 | #define SP5100_WDT_START_STOP_BIT 1 | ||
18 | #define SP5100_WDT_TRIGGER_BIT (1 << 7) | ||
19 | |||
20 | #define SP5100_PCI_WATCHDOG_MISC_REG 0x41 | ||
21 | #define SP5100_PCI_WATCHDOG_DECODE_EN (1 << 3) | ||
22 | |||
23 | #define SP5100_PM_IOPORTS_SIZE 0x02 | ||
24 | |||
25 | /* These two IO registers are hardcoded and there doesn't seem to be a way to | ||
26 | * read them from a register. | ||
27 | */ | ||
28 | #define SP5100_IO_PM_INDEX_REG 0xCD6 | ||
29 | #define SP5100_IO_PM_DATA_REG 0xCD7 | ||
30 | |||
31 | #define SP5100_PM_WATCHDOG_CONTROL 0x69 | ||
32 | #define SP5100_PM_WATCHDOG_BASE0 0x6C | ||
33 | #define SP5100_PM_WATCHDOG_BASE1 0x6D | ||
34 | #define SP5100_PM_WATCHDOG_BASE2 0x6E | ||
35 | #define SP5100_PM_WATCHDOG_BASE3 0x6F | ||
36 | |||
37 | #define SP5100_PM_WATCHDOG_FIRED (1 << 1) | ||
38 | #define SP5100_PM_WATCHDOG_ACTION_RESET (1 << 2) | ||
39 | |||
40 | #define SP5100_PM_WATCHDOG_DISABLE 1 | ||
41 | #define SP5100_PM_WATCHDOG_SECOND_RES (3 << 1) | ||
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 0f5288df0091..e5c91d4404ed 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c | |||
@@ -42,7 +42,7 @@ | |||
42 | 42 | ||
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #define WATCHDOG_NAME "w83627hf/thf/hg WDT" | 45 | #define WATCHDOG_NAME "w83627hf/thf/hg/dhg WDT" |
46 | #define PFX WATCHDOG_NAME ": " | 46 | #define PFX WATCHDOG_NAME ": " |
47 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ | 47 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ |
48 | 48 | ||
@@ -89,7 +89,7 @@ static void w83627hf_select_wd_register(void) | |||
89 | c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ | 89 | c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */ |
90 | outb_p(0x2b, WDT_EFER); | 90 | outb_p(0x2b, WDT_EFER); |
91 | outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ | 91 | outb_p(c, WDT_EFDR); /* set GPIO3 to WDT0 */ |
92 | } else if (c == 0x88) { /* W83627EHF */ | 92 | } else if (c == 0x88 || c == 0xa0) { /* W83627EHF / W83627DHG */ |
93 | outb_p(0x2d, WDT_EFER); /* select GPIO5 */ | 93 | outb_p(0x2d, WDT_EFER); /* select GPIO5 */ |
94 | c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ | 94 | c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */ |
95 | outb_p(0x2d, WDT_EFER); | 95 | outb_p(0x2d, WDT_EFER); |
@@ -129,6 +129,8 @@ static void w83627hf_init(void) | |||
129 | t = inb_p(WDT_EFDR); /* read CRF5 */ | 129 | t = inb_p(WDT_EFDR); /* read CRF5 */ |
130 | t &= ~0x0C; /* set second mode & disable keyboard | 130 | t &= ~0x0C; /* set second mode & disable keyboard |
131 | turning off watchdog */ | 131 | turning off watchdog */ |
132 | t |= 0x02; /* enable the WDTO# output low pulse | ||
133 | to the KBRST# pin (PIN60) */ | ||
132 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ | 134 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ |
133 | 135 | ||
134 | outb_p(0xF7, WDT_EFER); /* Select CRF7 */ | 136 | outb_p(0xF7, WDT_EFER); /* Select CRF7 */ |
@@ -321,7 +323,7 @@ static int __init wdt_init(void) | |||
321 | { | 323 | { |
322 | int ret; | 324 | int ret; |
323 | 325 | ||
324 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG Super I/O chip initialising.\n"); | 326 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF/HG/DHG Super I/O chip initialising.\n"); |
325 | 327 | ||
326 | if (wdt_set_heartbeat(timeout)) { | 328 | if (wdt_set_heartbeat(timeout)) { |
327 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | 329 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); |