diff options
Diffstat (limited to 'drivers')
84 files changed, 2746 insertions, 2695 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b0a71ecee682..e4804fb05e23 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
| @@ -401,11 +401,13 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
| 401 | * driver reported one, then use it. Exit in any case. | 401 | * driver reported one, then use it. Exit in any case. |
| 402 | */ | 402 | */ |
| 403 | if (gsi < 0) { | 403 | if (gsi < 0) { |
| 404 | u32 dev_gsi; | ||
| 404 | dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); | 405 | dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); |
| 405 | /* Interrupt Line values above 0xF are forbidden */ | 406 | /* Interrupt Line values above 0xF are forbidden */ |
| 406 | if (dev->irq > 0 && (dev->irq <= 0xF)) { | 407 | if (dev->irq > 0 && (dev->irq <= 0xF) && |
| 407 | printk(" - using IRQ %d\n", dev->irq); | 408 | (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { |
| 408 | acpi_register_gsi(&dev->dev, dev->irq, | 409 | printk(" - using ISA IRQ %d\n", dev->irq); |
| 410 | acpi_register_gsi(&dev->dev, dev_gsi, | ||
| 409 | ACPI_LEVEL_SENSITIVE, | 411 | ACPI_LEVEL_SENSITIVE, |
| 410 | ACPI_ACTIVE_LOW); | 412 | ACPI_ACTIVE_LOW); |
| 411 | return 0; | 413 | return 0; |
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 8ad4ffea6920..6e6b6a11b3ce 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c | |||
| @@ -80,20 +80,6 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) | |||
| 80 | } | 80 | } |
| 81 | EXPORT_SYMBOL_GPL(iommu_detach_device); | 81 | EXPORT_SYMBOL_GPL(iommu_detach_device); |
| 82 | 82 | ||
| 83 | int iommu_map_range(struct iommu_domain *domain, unsigned long iova, | ||
| 84 | phys_addr_t paddr, size_t size, int prot) | ||
| 85 | { | ||
| 86 | return iommu_ops->map(domain, iova, paddr, size, prot); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(iommu_map_range); | ||
| 89 | |||
| 90 | void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, | ||
| 91 | size_t size) | ||
| 92 | { | ||
| 93 | iommu_ops->unmap(domain, iova, size); | ||
| 94 | } | ||
| 95 | EXPORT_SYMBOL_GPL(iommu_unmap_range); | ||
| 96 | |||
| 97 | phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, | 83 | phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, |
| 98 | unsigned long iova) | 84 | unsigned long iova) |
| 99 | { | 85 | { |
| @@ -107,3 +93,32 @@ int iommu_domain_has_cap(struct iommu_domain *domain, | |||
| 107 | return iommu_ops->domain_has_cap(domain, cap); | 93 | return iommu_ops->domain_has_cap(domain, cap); |
| 108 | } | 94 | } |
| 109 | EXPORT_SYMBOL_GPL(iommu_domain_has_cap); | 95 | EXPORT_SYMBOL_GPL(iommu_domain_has_cap); |
| 96 | |||
| 97 | int iommu_map(struct iommu_domain *domain, unsigned long iova, | ||
| 98 | phys_addr_t paddr, int gfp_order, int prot) | ||
| 99 | { | ||
| 100 | unsigned long invalid_mask; | ||
| 101 | size_t size; | ||
| 102 | |||
| 103 | size = 0x1000UL << gfp_order; | ||
| 104 | invalid_mask = size - 1; | ||
| 105 | |||
| 106 | BUG_ON((iova | paddr) & invalid_mask); | ||
| 107 | |||
| 108 | return iommu_ops->map(domain, iova, paddr, gfp_order, prot); | ||
| 109 | } | ||
| 110 | EXPORT_SYMBOL_GPL(iommu_map); | ||
| 111 | |||
| 112 | int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) | ||
| 113 | { | ||
| 114 | unsigned long invalid_mask; | ||
| 115 | size_t size; | ||
| 116 | |||
| 117 | size = 0x1000UL << gfp_order; | ||
| 118 | invalid_mask = size - 1; | ||
| 119 | |||
| 120 | BUG_ON(iova & invalid_mask); | ||
| 121 | |||
| 122 | return iommu_ops->unmap(domain, iova, gfp_order); | ||
| 123 | } | ||
| 124 | EXPORT_SYMBOL_GPL(iommu_unmap); | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4b4b565c835f..765bcf0df3bb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); | |||
| 187 | * released. | 187 | * released. |
| 188 | */ | 188 | */ |
| 189 | int platform_device_add_resources(struct platform_device *pdev, | 189 | int platform_device_add_resources(struct platform_device *pdev, |
| 190 | struct resource *res, unsigned int num) | 190 | const struct resource *res, unsigned int num) |
| 191 | { | 191 | { |
| 192 | struct resource *r; | 192 | struct resource *r; |
| 193 | 193 | ||
| @@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); | |||
| 367 | */ | 367 | */ |
| 368 | struct platform_device *platform_device_register_simple(const char *name, | 368 | struct platform_device *platform_device_register_simple(const char *name, |
| 369 | int id, | 369 | int id, |
| 370 | struct resource *res, | 370 | const struct resource *res, |
| 371 | unsigned int num) | 371 | unsigned int num) |
| 372 | { | 372 | { |
| 373 | struct platform_device *pdev; | 373 | struct platform_device *pdev; |
| @@ -1254,6 +1254,26 @@ static int __init early_platform_driver_probe_id(char *class_str, | |||
| 1254 | } | 1254 | } |
| 1255 | 1255 | ||
| 1256 | if (match) { | 1256 | if (match) { |
| 1257 | /* | ||
| 1258 | * Set up a sensible init_name to enable | ||
| 1259 | * dev_name() and others to be used before the | ||
| 1260 | * rest of the driver core is initialized. | ||
| 1261 | */ | ||
| 1262 | if (!match->dev.init_name && slab_is_available()) { | ||
| 1263 | if (match->id != -1) | ||
| 1264 | match->dev.init_name = | ||
| 1265 | kasprintf(GFP_KERNEL, "%s.%d", | ||
| 1266 | match->name, | ||
| 1267 | match->id); | ||
| 1268 | else | ||
| 1269 | match->dev.init_name = | ||
| 1270 | kasprintf(GFP_KERNEL, "%s", | ||
| 1271 | match->name); | ||
| 1272 | |||
| 1273 | if (!match->dev.init_name) | ||
| 1274 | return -ENOMEM; | ||
| 1275 | } | ||
| 1276 | |||
| 1257 | if (epdrv->pdrv->probe(match)) | 1277 | if (epdrv->pdrv->probe(match)) |
| 1258 | pr_warning("%s: unable to probe %s early.\n", | 1278 | pr_warning("%s: unable to probe %s early.\n", |
| 1259 | class_str, match->name); | 1279 | class_str, match->name); |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 0182a22c423a..832798aa14f6 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #include <linux/blkdev.h> | 66 | #include <linux/blkdev.h> |
| 67 | #include <linux/elevator.h> | 67 | #include <linux/elevator.h> |
| 68 | #include <linux/interrupt.h> | 68 | #include <linux/interrupt.h> |
| 69 | #include <linux/platform_device.h> | ||
| 69 | 70 | ||
| 70 | #include <asm/setup.h> | 71 | #include <asm/setup.h> |
| 71 | #include <asm/uaccess.h> | 72 | #include <asm/uaccess.h> |
| @@ -1696,34 +1697,18 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) | |||
| 1696 | return get_disk(unit[drive].gendisk); | 1697 | return get_disk(unit[drive].gendisk); |
| 1697 | } | 1698 | } |
| 1698 | 1699 | ||
| 1699 | static int __init amiga_floppy_init(void) | 1700 | static int __init amiga_floppy_probe(struct platform_device *pdev) |
| 1700 | { | 1701 | { |
| 1701 | int i, ret; | 1702 | int i, ret; |
| 1702 | 1703 | ||
| 1703 | if (!MACH_IS_AMIGA) | ||
| 1704 | return -ENODEV; | ||
| 1705 | |||
| 1706 | if (!AMIGAHW_PRESENT(AMI_FLOPPY)) | ||
| 1707 | return -ENODEV; | ||
| 1708 | |||
| 1709 | if (register_blkdev(FLOPPY_MAJOR,"fd")) | 1704 | if (register_blkdev(FLOPPY_MAJOR,"fd")) |
| 1710 | return -EBUSY; | 1705 | return -EBUSY; |
| 1711 | 1706 | ||
| 1712 | /* | ||
| 1713 | * We request DSKPTR, DSKLEN and DSKDATA only, because the other | ||
| 1714 | * floppy registers are too spreaded over the custom register space | ||
| 1715 | */ | ||
| 1716 | ret = -EBUSY; | ||
| 1717 | if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { | ||
| 1718 | printk("fd: cannot get floppy registers\n"); | ||
| 1719 | goto out_blkdev; | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | ret = -ENOMEM; | 1707 | ret = -ENOMEM; |
| 1723 | if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == | 1708 | if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == |
| 1724 | NULL) { | 1709 | NULL) { |
| 1725 | printk("fd: cannot get chip mem buffer\n"); | 1710 | printk("fd: cannot get chip mem buffer\n"); |
| 1726 | goto out_memregion; | 1711 | goto out_blkdev; |
| 1727 | } | 1712 | } |
| 1728 | 1713 | ||
| 1729 | ret = -EBUSY; | 1714 | ret = -EBUSY; |
| @@ -1792,18 +1777,13 @@ out_irq2: | |||
| 1792 | free_irq(IRQ_AMIGA_DSKBLK, NULL); | 1777 | free_irq(IRQ_AMIGA_DSKBLK, NULL); |
| 1793 | out_irq: | 1778 | out_irq: |
| 1794 | amiga_chip_free(raw_buf); | 1779 | amiga_chip_free(raw_buf); |
| 1795 | out_memregion: | ||
| 1796 | release_mem_region(CUSTOM_PHYSADDR+0x20, 8); | ||
| 1797 | out_blkdev: | 1780 | out_blkdev: |
| 1798 | unregister_blkdev(FLOPPY_MAJOR,"fd"); | 1781 | unregister_blkdev(FLOPPY_MAJOR,"fd"); |
| 1799 | return ret; | 1782 | return ret; |
| 1800 | } | 1783 | } |
| 1801 | 1784 | ||
| 1802 | module_init(amiga_floppy_init); | ||
| 1803 | #ifdef MODULE | ||
| 1804 | |||
| 1805 | #if 0 /* not safe to unload */ | 1785 | #if 0 /* not safe to unload */ |
| 1806 | void cleanup_module(void) | 1786 | static int __exit amiga_floppy_remove(struct platform_device *pdev) |
| 1807 | { | 1787 | { |
| 1808 | int i; | 1788 | int i; |
| 1809 | 1789 | ||
| @@ -1820,12 +1800,25 @@ void cleanup_module(void) | |||
| 1820 | custom.dmacon = DMAF_DISK; /* disable DMA */ | 1800 | custom.dmacon = DMAF_DISK; /* disable DMA */ |
| 1821 | amiga_chip_free(raw_buf); | 1801 | amiga_chip_free(raw_buf); |
| 1822 | blk_cleanup_queue(floppy_queue); | 1802 | blk_cleanup_queue(floppy_queue); |
| 1823 | release_mem_region(CUSTOM_PHYSADDR+0x20, 8); | ||
| 1824 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 1803 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
| 1825 | } | 1804 | } |
| 1826 | #endif | 1805 | #endif |
| 1827 | 1806 | ||
| 1828 | #else | 1807 | static struct platform_driver amiga_floppy_driver = { |
| 1808 | .driver = { | ||
| 1809 | .name = "amiga-floppy", | ||
| 1810 | .owner = THIS_MODULE, | ||
| 1811 | }, | ||
| 1812 | }; | ||
| 1813 | |||
| 1814 | static int __init amiga_floppy_init(void) | ||
| 1815 | { | ||
| 1816 | return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | module_init(amiga_floppy_init); | ||
| 1820 | |||
| 1821 | #ifndef MODULE | ||
| 1829 | static int __init amiga_floppy_setup (char *str) | 1822 | static int __init amiga_floppy_setup (char *str) |
| 1830 | { | 1823 | { |
| 1831 | int n; | 1824 | int n; |
| @@ -1840,3 +1833,5 @@ static int __init amiga_floppy_setup (char *str) | |||
| 1840 | 1833 | ||
| 1841 | __setup("floppy=", amiga_floppy_setup); | 1834 | __setup("floppy=", amiga_floppy_setup); |
| 1842 | #endif | 1835 | #endif |
| 1836 | |||
| 1837 | MODULE_ALIAS("platform:amiga-floppy"); | ||
diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 034e6dfc878c..81c78b3ce2df 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c | |||
| @@ -164,12 +164,12 @@ unsigned long read_timer(void) | |||
| 164 | unsigned long t, flags; | 164 | unsigned long t, flags; |
| 165 | int i; | 165 | int i; |
| 166 | 166 | ||
| 167 | spin_lock_irqsave(&i8253_lock, flags); | 167 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 168 | t = jiffies * 11932; | 168 | t = jiffies * 11932; |
| 169 | outb_p(0, 0x43); | 169 | outb_p(0, 0x43); |
| 170 | i = inb_p(0x40); | 170 | i = inb_p(0x40); |
| 171 | i |= inb(0x40) << 8; | 171 | i |= inb(0x40) << 8; |
| 172 | spin_unlock_irqrestore(&i8253_lock, flags); | 172 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 173 | return(t - i); | 173 | return(t - i); |
| 174 | } | 174 | } |
| 175 | #endif | 175 | #endif |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 8dfd24721a82..78a62ebe75c7 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
| @@ -627,7 +627,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | |||
| 627 | char data; | 627 | char data; |
| 628 | int char_count; | 628 | int char_count; |
| 629 | int save_cnt; | 629 | int save_cnt; |
| 630 | int len; | ||
| 631 | 630 | ||
| 632 | /* determine the channel and change to that context */ | 631 | /* determine the channel and change to that context */ |
| 633 | channel = (u_short) (base_addr[CyLICR] >> 2); | 632 | channel = (u_short) (base_addr[CyLICR] >> 2); |
| @@ -1528,7 +1527,6 @@ static int | |||
| 1528 | cy_ioctl(struct tty_struct *tty, struct file *file, | 1527 | cy_ioctl(struct tty_struct *tty, struct file *file, |
| 1529 | unsigned int cmd, unsigned long arg) | 1528 | unsigned int cmd, unsigned long arg) |
| 1530 | { | 1529 | { |
| 1531 | unsigned long val; | ||
| 1532 | struct cyclades_port *info = tty->driver_data; | 1530 | struct cyclades_port *info = tty->driver_data; |
| 1533 | int ret_val = 0; | 1531 | int ret_val = 0; |
| 1534 | void __user *argp = (void __user *)arg; | 1532 | void __user *argp = (void __user *)arg; |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 59de2525d303..d4e8b213a462 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
| @@ -289,7 +289,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = { | |||
| 289 | 289 | ||
| 290 | static void sysrq_ftrace_dump(int key, struct tty_struct *tty) | 290 | static void sysrq_ftrace_dump(int key, struct tty_struct *tty) |
| 291 | { | 291 | { |
| 292 | ftrace_dump(); | 292 | ftrace_dump(DUMP_ALL); |
| 293 | } | 293 | } |
| 294 | static struct sysrq_key_op sysrq_ftrace_dump_op = { | 294 | static struct sysrq_key_op sysrq_ftrace_dump_op = { |
| 295 | .handler = sysrq_ftrace_dump, | 295 | .handler = sysrq_ftrace_dump, |
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 744f748cc84b..f6677cb19789 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
| @@ -150,13 +150,12 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | |||
| 150 | 150 | ||
| 151 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | 151 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) |
| 152 | { | 152 | { |
| 153 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 154 | int ret; | 153 | int ret; |
| 155 | 154 | ||
| 156 | /* enable clock */ | 155 | /* enable clock */ |
| 157 | ret = clk_enable(p->clk); | 156 | ret = clk_enable(p->clk); |
| 158 | if (ret) { | 157 | if (ret) { |
| 159 | pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); | 158 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
| 160 | return ret; | 159 | return ret; |
| 161 | } | 160 | } |
| 162 | 161 | ||
| @@ -279,7 +278,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, | |||
| 279 | delay = 1; | 278 | delay = 1; |
| 280 | 279 | ||
| 281 | if (!delay) | 280 | if (!delay) |
| 282 | pr_warning("sh_cmt: too long delay\n"); | 281 | dev_warn(&p->pdev->dev, "too long delay\n"); |
| 283 | 282 | ||
| 284 | } while (delay); | 283 | } while (delay); |
| 285 | } | 284 | } |
| @@ -289,7 +288,7 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) | |||
| 289 | unsigned long flags; | 288 | unsigned long flags; |
| 290 | 289 | ||
| 291 | if (delta > p->max_match_value) | 290 | if (delta > p->max_match_value) |
| 292 | pr_warning("sh_cmt: delta out of range\n"); | 291 | dev_warn(&p->pdev->dev, "delta out of range\n"); |
| 293 | 292 | ||
| 294 | spin_lock_irqsave(&p->lock, flags); | 293 | spin_lock_irqsave(&p->lock, flags); |
| 295 | p->next_match_value = delta; | 294 | p->next_match_value = delta; |
| @@ -451,7 +450,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, | |||
| 451 | cs->resume = sh_cmt_clocksource_resume; | 450 | cs->resume = sh_cmt_clocksource_resume; |
| 452 | cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); | 451 | cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); |
| 453 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; | 452 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; |
| 454 | pr_info("sh_cmt: %s used as clock source\n", cs->name); | 453 | dev_info(&p->pdev->dev, "used as clock source\n"); |
| 455 | clocksource_register(cs); | 454 | clocksource_register(cs); |
| 456 | return 0; | 455 | return 0; |
| 457 | } | 456 | } |
| @@ -497,13 +496,11 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode, | |||
| 497 | 496 | ||
| 498 | switch (mode) { | 497 | switch (mode) { |
| 499 | case CLOCK_EVT_MODE_PERIODIC: | 498 | case CLOCK_EVT_MODE_PERIODIC: |
| 500 | pr_info("sh_cmt: %s used for periodic clock events\n", | 499 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
| 501 | ced->name); | ||
| 502 | sh_cmt_clock_event_start(p, 1); | 500 | sh_cmt_clock_event_start(p, 1); |
| 503 | break; | 501 | break; |
| 504 | case CLOCK_EVT_MODE_ONESHOT: | 502 | case CLOCK_EVT_MODE_ONESHOT: |
| 505 | pr_info("sh_cmt: %s used for oneshot clock events\n", | 503 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); |
| 506 | ced->name); | ||
| 507 | sh_cmt_clock_event_start(p, 0); | 504 | sh_cmt_clock_event_start(p, 0); |
| 508 | break; | 505 | break; |
| 509 | case CLOCK_EVT_MODE_SHUTDOWN: | 506 | case CLOCK_EVT_MODE_SHUTDOWN: |
| @@ -544,7 +541,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, | |||
| 544 | ced->set_next_event = sh_cmt_clock_event_next; | 541 | ced->set_next_event = sh_cmt_clock_event_next; |
| 545 | ced->set_mode = sh_cmt_clock_event_mode; | 542 | ced->set_mode = sh_cmt_clock_event_mode; |
| 546 | 543 | ||
| 547 | pr_info("sh_cmt: %s used for clock events\n", ced->name); | 544 | dev_info(&p->pdev->dev, "used for clock events\n"); |
| 548 | clockevents_register_device(ced); | 545 | clockevents_register_device(ced); |
| 549 | } | 546 | } |
| 550 | 547 | ||
| @@ -601,22 +598,27 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
| 601 | /* map memory, let mapbase point to our channel */ | 598 | /* map memory, let mapbase point to our channel */ |
| 602 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | 599 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); |
| 603 | if (p->mapbase == NULL) { | 600 | if (p->mapbase == NULL) { |
| 604 | pr_err("sh_cmt: failed to remap I/O memory\n"); | 601 | dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); |
| 605 | goto err0; | 602 | goto err0; |
| 606 | } | 603 | } |
| 607 | 604 | ||
| 608 | /* request irq using setup_irq() (too early for request_irq()) */ | 605 | /* request irq using setup_irq() (too early for request_irq()) */ |
| 609 | p->irqaction.name = cfg->name; | 606 | p->irqaction.name = dev_name(&p->pdev->dev); |
| 610 | p->irqaction.handler = sh_cmt_interrupt; | 607 | p->irqaction.handler = sh_cmt_interrupt; |
| 611 | p->irqaction.dev_id = p; | 608 | p->irqaction.dev_id = p; |
| 612 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | 609 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ |
| 610 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
| 613 | 611 | ||
| 614 | /* get hold of clock */ | 612 | /* get hold of clock */ |
| 615 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | 613 | p->clk = clk_get(&p->pdev->dev, "cmt_fck"); |
| 616 | if (IS_ERR(p->clk)) { | 614 | if (IS_ERR(p->clk)) { |
| 617 | pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); | 615 | dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); |
| 618 | ret = PTR_ERR(p->clk); | 616 | p->clk = clk_get(&p->pdev->dev, cfg->clk); |
| 619 | goto err1; | 617 | if (IS_ERR(p->clk)) { |
| 618 | dev_err(&p->pdev->dev, "cannot get clock\n"); | ||
| 619 | ret = PTR_ERR(p->clk); | ||
| 620 | goto err1; | ||
| 621 | } | ||
| 620 | } | 622 | } |
| 621 | 623 | ||
| 622 | if (resource_size(res) == 6) { | 624 | if (resource_size(res) == 6) { |
| @@ -629,17 +631,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
| 629 | p->clear_bits = ~0xc000; | 631 | p->clear_bits = ~0xc000; |
| 630 | } | 632 | } |
| 631 | 633 | ||
| 632 | ret = sh_cmt_register(p, cfg->name, | 634 | ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), |
| 633 | cfg->clockevent_rating, | 635 | cfg->clockevent_rating, |
| 634 | cfg->clocksource_rating); | 636 | cfg->clocksource_rating); |
| 635 | if (ret) { | 637 | if (ret) { |
| 636 | pr_err("sh_cmt: registration failed\n"); | 638 | dev_err(&p->pdev->dev, "registration failed\n"); |
| 637 | goto err1; | 639 | goto err1; |
| 638 | } | 640 | } |
| 639 | 641 | ||
| 640 | ret = setup_irq(irq, &p->irqaction); | 642 | ret = setup_irq(irq, &p->irqaction); |
| 641 | if (ret) { | 643 | if (ret) { |
| 642 | pr_err("sh_cmt: failed to request irq %d\n", irq); | 644 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); |
| 643 | goto err1; | 645 | goto err1; |
| 644 | } | 646 | } |
| 645 | 647 | ||
| @@ -654,11 +656,10 @@ err0: | |||
| 654 | static int __devinit sh_cmt_probe(struct platform_device *pdev) | 656 | static int __devinit sh_cmt_probe(struct platform_device *pdev) |
| 655 | { | 657 | { |
| 656 | struct sh_cmt_priv *p = platform_get_drvdata(pdev); | 658 | struct sh_cmt_priv *p = platform_get_drvdata(pdev); |
| 657 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 658 | int ret; | 659 | int ret; |
| 659 | 660 | ||
| 660 | if (p) { | 661 | if (p) { |
| 661 | pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name); | 662 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
| 662 | return 0; | 663 | return 0; |
| 663 | } | 664 | } |
| 664 | 665 | ||
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 5fb78bfd73bb..ef7a5be8a09f 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
| @@ -119,13 +119,12 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) | |||
| 119 | 119 | ||
| 120 | static int sh_mtu2_enable(struct sh_mtu2_priv *p) | 120 | static int sh_mtu2_enable(struct sh_mtu2_priv *p) |
| 121 | { | 121 | { |
| 122 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 123 | int ret; | 122 | int ret; |
| 124 | 123 | ||
| 125 | /* enable clock */ | 124 | /* enable clock */ |
| 126 | ret = clk_enable(p->clk); | 125 | ret = clk_enable(p->clk); |
| 127 | if (ret) { | 126 | if (ret) { |
| 128 | pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk); | 127 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
| 129 | return ret; | 128 | return ret; |
| 130 | } | 129 | } |
| 131 | 130 | ||
| @@ -194,8 +193,7 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, | |||
| 194 | 193 | ||
| 195 | switch (mode) { | 194 | switch (mode) { |
| 196 | case CLOCK_EVT_MODE_PERIODIC: | 195 | case CLOCK_EVT_MODE_PERIODIC: |
| 197 | pr_info("sh_mtu2: %s used for periodic clock events\n", | 196 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
| 198 | ced->name); | ||
| 199 | sh_mtu2_enable(p); | 197 | sh_mtu2_enable(p); |
| 200 | break; | 198 | break; |
| 201 | case CLOCK_EVT_MODE_UNUSED: | 199 | case CLOCK_EVT_MODE_UNUSED: |
| @@ -222,13 +220,13 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, | |||
| 222 | ced->cpumask = cpumask_of(0); | 220 | ced->cpumask = cpumask_of(0); |
| 223 | ced->set_mode = sh_mtu2_clock_event_mode; | 221 | ced->set_mode = sh_mtu2_clock_event_mode; |
| 224 | 222 | ||
| 225 | pr_info("sh_mtu2: %s used for clock events\n", ced->name); | 223 | dev_info(&p->pdev->dev, "used for clock events\n"); |
| 226 | clockevents_register_device(ced); | 224 | clockevents_register_device(ced); |
| 227 | 225 | ||
| 228 | ret = setup_irq(p->irqaction.irq, &p->irqaction); | 226 | ret = setup_irq(p->irqaction.irq, &p->irqaction); |
| 229 | if (ret) { | 227 | if (ret) { |
| 230 | pr_err("sh_mtu2: failed to request irq %d\n", | 228 | dev_err(&p->pdev->dev, "failed to request irq %d\n", |
| 231 | p->irqaction.irq); | 229 | p->irqaction.irq); |
| 232 | return; | 230 | return; |
| 233 | } | 231 | } |
| 234 | } | 232 | } |
| @@ -274,26 +272,32 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | |||
| 274 | /* map memory, let mapbase point to our channel */ | 272 | /* map memory, let mapbase point to our channel */ |
| 275 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | 273 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); |
| 276 | if (p->mapbase == NULL) { | 274 | if (p->mapbase == NULL) { |
| 277 | pr_err("sh_mtu2: failed to remap I/O memory\n"); | 275 | dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); |
| 278 | goto err0; | 276 | goto err0; |
| 279 | } | 277 | } |
| 280 | 278 | ||
| 281 | /* setup data for setup_irq() (too early for request_irq()) */ | 279 | /* setup data for setup_irq() (too early for request_irq()) */ |
| 282 | p->irqaction.name = cfg->name; | 280 | p->irqaction.name = dev_name(&p->pdev->dev); |
| 283 | p->irqaction.handler = sh_mtu2_interrupt; | 281 | p->irqaction.handler = sh_mtu2_interrupt; |
| 284 | p->irqaction.dev_id = p; | 282 | p->irqaction.dev_id = p; |
| 285 | p->irqaction.irq = irq; | 283 | p->irqaction.irq = irq; |
| 286 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | 284 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ |
| 285 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
| 287 | 286 | ||
| 288 | /* get hold of clock */ | 287 | /* get hold of clock */ |
| 289 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | 288 | p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); |
| 290 | if (IS_ERR(p->clk)) { | 289 | if (IS_ERR(p->clk)) { |
| 291 | pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk); | 290 | dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); |
| 292 | ret = PTR_ERR(p->clk); | 291 | p->clk = clk_get(&p->pdev->dev, cfg->clk); |
| 293 | goto err1; | 292 | if (IS_ERR(p->clk)) { |
| 293 | dev_err(&p->pdev->dev, "cannot get clock\n"); | ||
| 294 | ret = PTR_ERR(p->clk); | ||
| 295 | goto err1; | ||
| 296 | } | ||
| 294 | } | 297 | } |
| 295 | 298 | ||
| 296 | return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating); | 299 | return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), |
| 300 | cfg->clockevent_rating); | ||
| 297 | err1: | 301 | err1: |
| 298 | iounmap(p->mapbase); | 302 | iounmap(p->mapbase); |
| 299 | err0: | 303 | err0: |
| @@ -303,11 +307,10 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | |||
| 303 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) | 307 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) |
| 304 | { | 308 | { |
| 305 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); | 309 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); |
| 306 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 307 | int ret; | 310 | int ret; |
| 308 | 311 | ||
| 309 | if (p) { | 312 | if (p) { |
| 310 | pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name); | 313 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
| 311 | return 0; | 314 | return 0; |
| 312 | } | 315 | } |
| 313 | 316 | ||
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index fc9ff1e5b770..8e44e14ec4c2 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
| @@ -107,13 +107,12 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) | |||
| 107 | 107 | ||
| 108 | static int sh_tmu_enable(struct sh_tmu_priv *p) | 108 | static int sh_tmu_enable(struct sh_tmu_priv *p) |
| 109 | { | 109 | { |
| 110 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 111 | int ret; | 110 | int ret; |
| 112 | 111 | ||
| 113 | /* enable clock */ | 112 | /* enable clock */ |
| 114 | ret = clk_enable(p->clk); | 113 | ret = clk_enable(p->clk); |
| 115 | if (ret) { | 114 | if (ret) { |
| 116 | pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk); | 115 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
| 117 | return ret; | 116 | return ret; |
| 118 | } | 117 | } |
| 119 | 118 | ||
| @@ -229,7 +228,7 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, | |||
| 229 | cs->disable = sh_tmu_clocksource_disable; | 228 | cs->disable = sh_tmu_clocksource_disable; |
| 230 | cs->mask = CLOCKSOURCE_MASK(32); | 229 | cs->mask = CLOCKSOURCE_MASK(32); |
| 231 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; | 230 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; |
| 232 | pr_info("sh_tmu: %s used as clock source\n", cs->name); | 231 | dev_info(&p->pdev->dev, "used as clock source\n"); |
| 233 | clocksource_register(cs); | 232 | clocksource_register(cs); |
| 234 | return 0; | 233 | return 0; |
| 235 | } | 234 | } |
| @@ -277,13 +276,11 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode, | |||
| 277 | 276 | ||
| 278 | switch (mode) { | 277 | switch (mode) { |
| 279 | case CLOCK_EVT_MODE_PERIODIC: | 278 | case CLOCK_EVT_MODE_PERIODIC: |
| 280 | pr_info("sh_tmu: %s used for periodic clock events\n", | 279 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
| 281 | ced->name); | ||
| 282 | sh_tmu_clock_event_start(p, 1); | 280 | sh_tmu_clock_event_start(p, 1); |
| 283 | break; | 281 | break; |
| 284 | case CLOCK_EVT_MODE_ONESHOT: | 282 | case CLOCK_EVT_MODE_ONESHOT: |
| 285 | pr_info("sh_tmu: %s used for oneshot clock events\n", | 283 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); |
| 286 | ced->name); | ||
| 287 | sh_tmu_clock_event_start(p, 0); | 284 | sh_tmu_clock_event_start(p, 0); |
| 288 | break; | 285 | break; |
| 289 | case CLOCK_EVT_MODE_UNUSED: | 286 | case CLOCK_EVT_MODE_UNUSED: |
| @@ -324,13 +321,13 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, | |||
| 324 | ced->set_next_event = sh_tmu_clock_event_next; | 321 | ced->set_next_event = sh_tmu_clock_event_next; |
| 325 | ced->set_mode = sh_tmu_clock_event_mode; | 322 | ced->set_mode = sh_tmu_clock_event_mode; |
| 326 | 323 | ||
| 327 | pr_info("sh_tmu: %s used for clock events\n", ced->name); | 324 | dev_info(&p->pdev->dev, "used for clock events\n"); |
| 328 | clockevents_register_device(ced); | 325 | clockevents_register_device(ced); |
| 329 | 326 | ||
| 330 | ret = setup_irq(p->irqaction.irq, &p->irqaction); | 327 | ret = setup_irq(p->irqaction.irq, &p->irqaction); |
| 331 | if (ret) { | 328 | if (ret) { |
| 332 | pr_err("sh_tmu: failed to request irq %d\n", | 329 | dev_err(&p->pdev->dev, "failed to request irq %d\n", |
| 333 | p->irqaction.irq); | 330 | p->irqaction.irq); |
| 334 | return; | 331 | return; |
| 335 | } | 332 | } |
| 336 | } | 333 | } |
| @@ -379,26 +376,31 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) | |||
| 379 | /* map memory, let mapbase point to our channel */ | 376 | /* map memory, let mapbase point to our channel */ |
| 380 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | 377 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); |
| 381 | if (p->mapbase == NULL) { | 378 | if (p->mapbase == NULL) { |
| 382 | pr_err("sh_tmu: failed to remap I/O memory\n"); | 379 | dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); |
| 383 | goto err0; | 380 | goto err0; |
| 384 | } | 381 | } |
| 385 | 382 | ||
| 386 | /* setup data for setup_irq() (too early for request_irq()) */ | 383 | /* setup data for setup_irq() (too early for request_irq()) */ |
| 387 | p->irqaction.name = cfg->name; | 384 | p->irqaction.name = dev_name(&p->pdev->dev); |
| 388 | p->irqaction.handler = sh_tmu_interrupt; | 385 | p->irqaction.handler = sh_tmu_interrupt; |
| 389 | p->irqaction.dev_id = p; | 386 | p->irqaction.dev_id = p; |
| 390 | p->irqaction.irq = irq; | 387 | p->irqaction.irq = irq; |
| 391 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | 388 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ |
| 389 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
| 392 | 390 | ||
| 393 | /* get hold of clock */ | 391 | /* get hold of clock */ |
| 394 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | 392 | p->clk = clk_get(&p->pdev->dev, "tmu_fck"); |
| 395 | if (IS_ERR(p->clk)) { | 393 | if (IS_ERR(p->clk)) { |
| 396 | pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk); | 394 | dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); |
| 397 | ret = PTR_ERR(p->clk); | 395 | p->clk = clk_get(&p->pdev->dev, cfg->clk); |
| 398 | goto err1; | 396 | if (IS_ERR(p->clk)) { |
| 397 | dev_err(&p->pdev->dev, "cannot get clock\n"); | ||
| 398 | ret = PTR_ERR(p->clk); | ||
| 399 | goto err1; | ||
| 400 | } | ||
| 399 | } | 401 | } |
| 400 | 402 | ||
| 401 | return sh_tmu_register(p, cfg->name, | 403 | return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), |
| 402 | cfg->clockevent_rating, | 404 | cfg->clockevent_rating, |
| 403 | cfg->clocksource_rating); | 405 | cfg->clocksource_rating); |
| 404 | err1: | 406 | err1: |
| @@ -410,11 +412,10 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) | |||
| 410 | static int __devinit sh_tmu_probe(struct platform_device *pdev) | 412 | static int __devinit sh_tmu_probe(struct platform_device *pdev) |
| 411 | { | 413 | { |
| 412 | struct sh_tmu_priv *p = platform_get_drvdata(pdev); | 414 | struct sh_tmu_priv *p = platform_get_drvdata(pdev); |
| 413 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 414 | int ret; | 415 | int ret; |
| 415 | 416 | ||
| 416 | if (p) { | 417 | if (p) { |
| 417 | pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name); | 418 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
| 418 | return 0; | 419 | return 0; |
| 419 | } | 420 | } |
| 420 | 421 | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 75d293eeb3ee..063b2184caf5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -662,32 +662,20 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) | |||
| 662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); | 662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | #define define_one_ro(_name) \ | 665 | cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); |
| 666 | static struct freq_attr _name = \ | 666 | cpufreq_freq_attr_ro(cpuinfo_min_freq); |
| 667 | __ATTR(_name, 0444, show_##_name, NULL) | 667 | cpufreq_freq_attr_ro(cpuinfo_max_freq); |
| 668 | 668 | cpufreq_freq_attr_ro(cpuinfo_transition_latency); | |
| 669 | #define define_one_ro0400(_name) \ | 669 | cpufreq_freq_attr_ro(scaling_available_governors); |
| 670 | static struct freq_attr _name = \ | 670 | cpufreq_freq_attr_ro(scaling_driver); |
| 671 | __ATTR(_name, 0400, show_##_name, NULL) | 671 | cpufreq_freq_attr_ro(scaling_cur_freq); |
| 672 | 672 | cpufreq_freq_attr_ro(bios_limit); | |
| 673 | #define define_one_rw(_name) \ | 673 | cpufreq_freq_attr_ro(related_cpus); |
| 674 | static struct freq_attr _name = \ | 674 | cpufreq_freq_attr_ro(affected_cpus); |
| 675 | __ATTR(_name, 0644, show_##_name, store_##_name) | 675 | cpufreq_freq_attr_rw(scaling_min_freq); |
| 676 | 676 | cpufreq_freq_attr_rw(scaling_max_freq); | |
| 677 | define_one_ro0400(cpuinfo_cur_freq); | 677 | cpufreq_freq_attr_rw(scaling_governor); |
| 678 | define_one_ro(cpuinfo_min_freq); | 678 | cpufreq_freq_attr_rw(scaling_setspeed); |
| 679 | define_one_ro(cpuinfo_max_freq); | ||
| 680 | define_one_ro(cpuinfo_transition_latency); | ||
| 681 | define_one_ro(scaling_available_governors); | ||
| 682 | define_one_ro(scaling_driver); | ||
| 683 | define_one_ro(scaling_cur_freq); | ||
| 684 | define_one_ro(bios_limit); | ||
| 685 | define_one_ro(related_cpus); | ||
| 686 | define_one_ro(affected_cpus); | ||
| 687 | define_one_rw(scaling_min_freq); | ||
| 688 | define_one_rw(scaling_max_freq); | ||
| 689 | define_one_rw(scaling_governor); | ||
| 690 | define_one_rw(scaling_setspeed); | ||
| 691 | 679 | ||
| 692 | static struct attribute *default_attrs[] = { | 680 | static struct attribute *default_attrs[] = { |
| 693 | &cpuinfo_min_freq.attr, | 681 | &cpuinfo_min_freq.attr, |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 3a147874a465..526bfbf69611 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
| @@ -178,12 +178,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, | |||
| 178 | return sprintf(buf, "%u\n", min_sampling_rate); | 178 | return sprintf(buf, "%u\n", min_sampling_rate); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | #define define_one_ro(_name) \ | 181 | define_one_global_ro(sampling_rate_max); |
| 182 | static struct global_attr _name = \ | 182 | define_one_global_ro(sampling_rate_min); |
| 183 | __ATTR(_name, 0444, show_##_name, NULL) | ||
| 184 | |||
| 185 | define_one_ro(sampling_rate_max); | ||
| 186 | define_one_ro(sampling_rate_min); | ||
| 187 | 183 | ||
| 188 | /* cpufreq_conservative Governor Tunables */ | 184 | /* cpufreq_conservative Governor Tunables */ |
| 189 | #define show_one(file_name, object) \ | 185 | #define show_one(file_name, object) \ |
| @@ -221,12 +217,8 @@ show_one_old(freq_step); | |||
| 221 | show_one_old(sampling_rate_min); | 217 | show_one_old(sampling_rate_min); |
| 222 | show_one_old(sampling_rate_max); | 218 | show_one_old(sampling_rate_max); |
| 223 | 219 | ||
| 224 | #define define_one_ro_old(object, _name) \ | 220 | cpufreq_freq_attr_ro_old(sampling_rate_min); |
| 225 | static struct freq_attr object = \ | 221 | cpufreq_freq_attr_ro_old(sampling_rate_max); |
| 226 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
| 227 | |||
| 228 | define_one_ro_old(sampling_rate_min_old, sampling_rate_min); | ||
| 229 | define_one_ro_old(sampling_rate_max_old, sampling_rate_max); | ||
| 230 | 222 | ||
| 231 | /*** delete after deprecation time ***/ | 223 | /*** delete after deprecation time ***/ |
| 232 | 224 | ||
| @@ -364,16 +356,12 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b, | |||
| 364 | return count; | 356 | return count; |
| 365 | } | 357 | } |
| 366 | 358 | ||
| 367 | #define define_one_rw(_name) \ | 359 | define_one_global_rw(sampling_rate); |
| 368 | static struct global_attr _name = \ | 360 | define_one_global_rw(sampling_down_factor); |
| 369 | __ATTR(_name, 0644, show_##_name, store_##_name) | 361 | define_one_global_rw(up_threshold); |
| 370 | 362 | define_one_global_rw(down_threshold); | |
| 371 | define_one_rw(sampling_rate); | 363 | define_one_global_rw(ignore_nice_load); |
| 372 | define_one_rw(sampling_down_factor); | 364 | define_one_global_rw(freq_step); |
| 373 | define_one_rw(up_threshold); | ||
| 374 | define_one_rw(down_threshold); | ||
| 375 | define_one_rw(ignore_nice_load); | ||
| 376 | define_one_rw(freq_step); | ||
| 377 | 365 | ||
| 378 | static struct attribute *dbs_attributes[] = { | 366 | static struct attribute *dbs_attributes[] = { |
| 379 | &sampling_rate_max.attr, | 367 | &sampling_rate_max.attr, |
| @@ -409,16 +397,12 @@ write_one_old(down_threshold); | |||
| 409 | write_one_old(ignore_nice_load); | 397 | write_one_old(ignore_nice_load); |
| 410 | write_one_old(freq_step); | 398 | write_one_old(freq_step); |
| 411 | 399 | ||
| 412 | #define define_one_rw_old(object, _name) \ | 400 | cpufreq_freq_attr_rw_old(sampling_rate); |
| 413 | static struct freq_attr object = \ | 401 | cpufreq_freq_attr_rw_old(sampling_down_factor); |
| 414 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | 402 | cpufreq_freq_attr_rw_old(up_threshold); |
| 415 | 403 | cpufreq_freq_attr_rw_old(down_threshold); | |
| 416 | define_one_rw_old(sampling_rate_old, sampling_rate); | 404 | cpufreq_freq_attr_rw_old(ignore_nice_load); |
| 417 | define_one_rw_old(sampling_down_factor_old, sampling_down_factor); | 405 | cpufreq_freq_attr_rw_old(freq_step); |
| 418 | define_one_rw_old(up_threshold_old, up_threshold); | ||
| 419 | define_one_rw_old(down_threshold_old, down_threshold); | ||
| 420 | define_one_rw_old(ignore_nice_load_old, ignore_nice_load); | ||
| 421 | define_one_rw_old(freq_step_old, freq_step); | ||
| 422 | 406 | ||
| 423 | static struct attribute *dbs_attributes_old[] = { | 407 | static struct attribute *dbs_attributes_old[] = { |
| 424 | &sampling_rate_max_old.attr, | 408 | &sampling_rate_max_old.attr, |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc93cf2..e1314212d8d4 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
| @@ -73,6 +73,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; | |||
| 73 | 73 | ||
| 74 | struct cpu_dbs_info_s { | 74 | struct cpu_dbs_info_s { |
| 75 | cputime64_t prev_cpu_idle; | 75 | cputime64_t prev_cpu_idle; |
| 76 | cputime64_t prev_cpu_iowait; | ||
| 76 | cputime64_t prev_cpu_wall; | 77 | cputime64_t prev_cpu_wall; |
| 77 | cputime64_t prev_cpu_nice; | 78 | cputime64_t prev_cpu_nice; |
| 78 | struct cpufreq_policy *cur_policy; | 79 | struct cpufreq_policy *cur_policy; |
| @@ -108,6 +109,7 @@ static struct dbs_tuners { | |||
| 108 | unsigned int down_differential; | 109 | unsigned int down_differential; |
| 109 | unsigned int ignore_nice; | 110 | unsigned int ignore_nice; |
| 110 | unsigned int powersave_bias; | 111 | unsigned int powersave_bias; |
| 112 | unsigned int io_is_busy; | ||
| 111 | } dbs_tuners_ins = { | 113 | } dbs_tuners_ins = { |
| 112 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 114 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
| 113 | .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, | 115 | .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, |
| @@ -148,6 +150,16 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | |||
| 148 | return idle_time; | 150 | return idle_time; |
| 149 | } | 151 | } |
| 150 | 152 | ||
| 153 | static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) | ||
| 154 | { | ||
| 155 | u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); | ||
| 156 | |||
| 157 | if (iowait_time == -1ULL) | ||
| 158 | return 0; | ||
| 159 | |||
| 160 | return iowait_time; | ||
| 161 | } | ||
| 162 | |||
| 151 | /* | 163 | /* |
| 152 | * Find right freq to be set now with powersave_bias on. | 164 | * Find right freq to be set now with powersave_bias on. |
| 153 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, | 165 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, |
| @@ -234,12 +246,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, | |||
| 234 | return sprintf(buf, "%u\n", min_sampling_rate); | 246 | return sprintf(buf, "%u\n", min_sampling_rate); |
| 235 | } | 247 | } |
| 236 | 248 | ||
| 237 | #define define_one_ro(_name) \ | 249 | define_one_global_ro(sampling_rate_max); |
| 238 | static struct global_attr _name = \ | 250 | define_one_global_ro(sampling_rate_min); |
| 239 | __ATTR(_name, 0444, show_##_name, NULL) | ||
| 240 | |||
| 241 | define_one_ro(sampling_rate_max); | ||
| 242 | define_one_ro(sampling_rate_min); | ||
| 243 | 251 | ||
| 244 | /* cpufreq_ondemand Governor Tunables */ | 252 | /* cpufreq_ondemand Governor Tunables */ |
| 245 | #define show_one(file_name, object) \ | 253 | #define show_one(file_name, object) \ |
| @@ -249,6 +257,7 @@ static ssize_t show_##file_name \ | |||
| 249 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ | 257 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ |
| 250 | } | 258 | } |
| 251 | show_one(sampling_rate, sampling_rate); | 259 | show_one(sampling_rate, sampling_rate); |
| 260 | show_one(io_is_busy, io_is_busy); | ||
| 252 | show_one(up_threshold, up_threshold); | 261 | show_one(up_threshold, up_threshold); |
| 253 | show_one(ignore_nice_load, ignore_nice); | 262 | show_one(ignore_nice_load, ignore_nice); |
| 254 | show_one(powersave_bias, powersave_bias); | 263 | show_one(powersave_bias, powersave_bias); |
| @@ -274,12 +283,8 @@ show_one_old(powersave_bias); | |||
| 274 | show_one_old(sampling_rate_min); | 283 | show_one_old(sampling_rate_min); |
| 275 | show_one_old(sampling_rate_max); | 284 | show_one_old(sampling_rate_max); |
| 276 | 285 | ||
| 277 | #define define_one_ro_old(object, _name) \ | 286 | cpufreq_freq_attr_ro_old(sampling_rate_min); |
| 278 | static struct freq_attr object = \ | 287 | cpufreq_freq_attr_ro_old(sampling_rate_max); |
| 279 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
| 280 | |||
| 281 | define_one_ro_old(sampling_rate_min_old, sampling_rate_min); | ||
| 282 | define_one_ro_old(sampling_rate_max_old, sampling_rate_max); | ||
| 283 | 288 | ||
| 284 | /*** delete after deprecation time ***/ | 289 | /*** delete after deprecation time ***/ |
| 285 | 290 | ||
| @@ -299,6 +304,23 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, | |||
| 299 | return count; | 304 | return count; |
| 300 | } | 305 | } |
| 301 | 306 | ||
| 307 | static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, | ||
| 308 | const char *buf, size_t count) | ||
| 309 | { | ||
| 310 | unsigned int input; | ||
| 311 | int ret; | ||
| 312 | |||
| 313 | ret = sscanf(buf, "%u", &input); | ||
| 314 | if (ret != 1) | ||
| 315 | return -EINVAL; | ||
| 316 | |||
| 317 | mutex_lock(&dbs_mutex); | ||
| 318 | dbs_tuners_ins.io_is_busy = !!input; | ||
| 319 | mutex_unlock(&dbs_mutex); | ||
| 320 | |||
| 321 | return count; | ||
| 322 | } | ||
| 323 | |||
| 302 | static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, | 324 | static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, |
| 303 | const char *buf, size_t count) | 325 | const char *buf, size_t count) |
| 304 | { | 326 | { |
| @@ -376,14 +398,11 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, | |||
| 376 | return count; | 398 | return count; |
| 377 | } | 399 | } |
| 378 | 400 | ||
| 379 | #define define_one_rw(_name) \ | 401 | define_one_global_rw(sampling_rate); |
| 380 | static struct global_attr _name = \ | 402 | define_one_global_rw(io_is_busy); |
| 381 | __ATTR(_name, 0644, show_##_name, store_##_name) | 403 | define_one_global_rw(up_threshold); |
| 382 | 404 | define_one_global_rw(ignore_nice_load); | |
| 383 | define_one_rw(sampling_rate); | 405 | define_one_global_rw(powersave_bias); |
| 384 | define_one_rw(up_threshold); | ||
| 385 | define_one_rw(ignore_nice_load); | ||
| 386 | define_one_rw(powersave_bias); | ||
| 387 | 406 | ||
| 388 | static struct attribute *dbs_attributes[] = { | 407 | static struct attribute *dbs_attributes[] = { |
| 389 | &sampling_rate_max.attr, | 408 | &sampling_rate_max.attr, |
| @@ -392,6 +411,7 @@ static struct attribute *dbs_attributes[] = { | |||
| 392 | &up_threshold.attr, | 411 | &up_threshold.attr, |
| 393 | &ignore_nice_load.attr, | 412 | &ignore_nice_load.attr, |
| 394 | &powersave_bias.attr, | 413 | &powersave_bias.attr, |
| 414 | &io_is_busy.attr, | ||
| 395 | NULL | 415 | NULL |
| 396 | }; | 416 | }; |
| 397 | 417 | ||
| @@ -415,14 +435,10 @@ write_one_old(up_threshold); | |||
| 415 | write_one_old(ignore_nice_load); | 435 | write_one_old(ignore_nice_load); |
| 416 | write_one_old(powersave_bias); | 436 | write_one_old(powersave_bias); |
| 417 | 437 | ||
| 418 | #define define_one_rw_old(object, _name) \ | 438 | cpufreq_freq_attr_rw_old(sampling_rate); |
| 419 | static struct freq_attr object = \ | 439 | cpufreq_freq_attr_rw_old(up_threshold); |
| 420 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | 440 | cpufreq_freq_attr_rw_old(ignore_nice_load); |
| 421 | 441 | cpufreq_freq_attr_rw_old(powersave_bias); | |
| 422 | define_one_rw_old(sampling_rate_old, sampling_rate); | ||
| 423 | define_one_rw_old(up_threshold_old, up_threshold); | ||
| 424 | define_one_rw_old(ignore_nice_load_old, ignore_nice_load); | ||
| 425 | define_one_rw_old(powersave_bias_old, powersave_bias); | ||
| 426 | 442 | ||
| 427 | static struct attribute *dbs_attributes_old[] = { | 443 | static struct attribute *dbs_attributes_old[] = { |
| 428 | &sampling_rate_max_old.attr, | 444 | &sampling_rate_max_old.attr, |
| @@ -470,14 +486,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 470 | 486 | ||
| 471 | for_each_cpu(j, policy->cpus) { | 487 | for_each_cpu(j, policy->cpus) { |
| 472 | struct cpu_dbs_info_s *j_dbs_info; | 488 | struct cpu_dbs_info_s *j_dbs_info; |
| 473 | cputime64_t cur_wall_time, cur_idle_time; | 489 | cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; |
| 474 | unsigned int idle_time, wall_time; | 490 | unsigned int idle_time, wall_time, iowait_time; |
| 475 | unsigned int load, load_freq; | 491 | unsigned int load, load_freq; |
| 476 | int freq_avg; | 492 | int freq_avg; |
| 477 | 493 | ||
| 478 | j_dbs_info = &per_cpu(od_cpu_dbs_info, j); | 494 | j_dbs_info = &per_cpu(od_cpu_dbs_info, j); |
| 479 | 495 | ||
| 480 | cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); | 496 | cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); |
| 497 | cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); | ||
| 481 | 498 | ||
| 482 | wall_time = (unsigned int) cputime64_sub(cur_wall_time, | 499 | wall_time = (unsigned int) cputime64_sub(cur_wall_time, |
| 483 | j_dbs_info->prev_cpu_wall); | 500 | j_dbs_info->prev_cpu_wall); |
| @@ -487,6 +504,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 487 | j_dbs_info->prev_cpu_idle); | 504 | j_dbs_info->prev_cpu_idle); |
| 488 | j_dbs_info->prev_cpu_idle = cur_idle_time; | 505 | j_dbs_info->prev_cpu_idle = cur_idle_time; |
| 489 | 506 | ||
| 507 | iowait_time = (unsigned int) cputime64_sub(cur_iowait_time, | ||
| 508 | j_dbs_info->prev_cpu_iowait); | ||
| 509 | j_dbs_info->prev_cpu_iowait = cur_iowait_time; | ||
| 510 | |||
| 490 | if (dbs_tuners_ins.ignore_nice) { | 511 | if (dbs_tuners_ins.ignore_nice) { |
| 491 | cputime64_t cur_nice; | 512 | cputime64_t cur_nice; |
| 492 | unsigned long cur_nice_jiffies; | 513 | unsigned long cur_nice_jiffies; |
| @@ -504,6 +525,16 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 504 | idle_time += jiffies_to_usecs(cur_nice_jiffies); | 525 | idle_time += jiffies_to_usecs(cur_nice_jiffies); |
| 505 | } | 526 | } |
| 506 | 527 | ||
| 528 | /* | ||
| 529 | * For the purpose of ondemand, waiting for disk IO is an | ||
| 530 | * indication that you're performance critical, and not that | ||
| 531 | * the system is actually idle. So subtract the iowait time | ||
| 532 | * from the cpu idle time. | ||
| 533 | */ | ||
| 534 | |||
| 535 | if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) | ||
| 536 | idle_time -= iowait_time; | ||
| 537 | |||
| 507 | if (unlikely(!wall_time || wall_time < idle_time)) | 538 | if (unlikely(!wall_time || wall_time < idle_time)) |
| 508 | continue; | 539 | continue; |
| 509 | 540 | ||
| @@ -617,6 +648,29 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | |||
| 617 | cancel_delayed_work_sync(&dbs_info->work); | 648 | cancel_delayed_work_sync(&dbs_info->work); |
| 618 | } | 649 | } |
| 619 | 650 | ||
| 651 | /* | ||
| 652 | * Not all CPUs want IO time to be accounted as busy; this dependson how | ||
| 653 | * efficient idling at a higher frequency/voltage is. | ||
| 654 | * Pavel Machek says this is not so for various generations of AMD and old | ||
| 655 | * Intel systems. | ||
| 656 | * Mike Chan (androidlcom) calis this is also not true for ARM. | ||
| 657 | * Because of this, whitelist specific known (series) of CPUs by default, and | ||
| 658 | * leave all others up to the user. | ||
| 659 | */ | ||
| 660 | static int should_io_be_busy(void) | ||
| 661 | { | ||
| 662 | #if defined(CONFIG_X86) | ||
| 663 | /* | ||
| 664 | * For Intel, Core 2 (model 15) andl later have an efficient idle. | ||
| 665 | */ | ||
| 666 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | ||
| 667 | boot_cpu_data.x86 == 6 && | ||
| 668 | boot_cpu_data.x86_model >= 15) | ||
| 669 | return 1; | ||
| 670 | #endif | ||
| 671 | return 0; | ||
| 672 | } | ||
| 673 | |||
| 620 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | 674 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, |
| 621 | unsigned int event) | 675 | unsigned int event) |
| 622 | { | 676 | { |
| @@ -679,6 +733,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 679 | dbs_tuners_ins.sampling_rate = | 733 | dbs_tuners_ins.sampling_rate = |
| 680 | max(min_sampling_rate, | 734 | max(min_sampling_rate, |
| 681 | latency * LATENCY_MULTIPLIER); | 735 | latency * LATENCY_MULTIPLIER); |
| 736 | dbs_tuners_ins.io_is_busy = should_io_be_busy(); | ||
| 682 | } | 737 | } |
| 683 | mutex_unlock(&dbs_mutex); | 738 | mutex_unlock(&dbs_mutex); |
| 684 | 739 | ||
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 6f25a20de99f..323afef77802 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
| @@ -26,8 +26,7 @@ | |||
| 26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
| 27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
| 29 | 29 | #include <linux/sh_dma.h> | |
| 30 | #include <asm/dmaengine.h> | ||
| 31 | 30 | ||
| 32 | #include "shdma.h" | 31 | #include "shdma.h" |
| 33 | 32 | ||
| @@ -45,7 +44,7 @@ enum sh_dmae_desc_status { | |||
| 45 | #define LOG2_DEFAULT_XFER_SIZE 2 | 44 | #define LOG2_DEFAULT_XFER_SIZE 2 |
| 46 | 45 | ||
| 47 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ | 46 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ |
| 48 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; | 47 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; |
| 49 | 48 | ||
| 50 | static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); | 49 | static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); |
| 51 | 50 | ||
| @@ -190,7 +189,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) | |||
| 190 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, | 189 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, |
| 191 | struct sh_dmae_device, common); | 190 | struct sh_dmae_device, common); |
| 192 | struct sh_dmae_pdata *pdata = shdev->pdata; | 191 | struct sh_dmae_pdata *pdata = shdev->pdata; |
| 193 | struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; | 192 | const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; |
| 194 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); | 193 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); |
| 195 | int shift = chan_pdata->dmars_bit; | 194 | int shift = chan_pdata->dmars_bit; |
| 196 | 195 | ||
| @@ -266,8 +265,8 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) | |||
| 266 | return NULL; | 265 | return NULL; |
| 267 | } | 266 | } |
| 268 | 267 | ||
| 269 | static struct sh_dmae_slave_config *sh_dmae_find_slave( | 268 | static const struct sh_dmae_slave_config *sh_dmae_find_slave( |
| 270 | struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id) | 269 | struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) |
| 271 | { | 270 | { |
| 272 | struct dma_device *dma_dev = sh_chan->common.device; | 271 | struct dma_device *dma_dev = sh_chan->common.device; |
| 273 | struct sh_dmae_device *shdev = container_of(dma_dev, | 272 | struct sh_dmae_device *shdev = container_of(dma_dev, |
| @@ -275,11 +274,11 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave( | |||
| 275 | struct sh_dmae_pdata *pdata = shdev->pdata; | 274 | struct sh_dmae_pdata *pdata = shdev->pdata; |
| 276 | int i; | 275 | int i; |
| 277 | 276 | ||
| 278 | if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER) | 277 | if (param->slave_id >= SH_DMA_SLAVE_NUMBER) |
| 279 | return NULL; | 278 | return NULL; |
| 280 | 279 | ||
| 281 | for (i = 0; i < pdata->slave_num; i++) | 280 | for (i = 0; i < pdata->slave_num; i++) |
| 282 | if (pdata->slave[i].slave_id == slave_id) | 281 | if (pdata->slave[i].slave_id == param->slave_id) |
| 283 | return pdata->slave + i; | 282 | return pdata->slave + i; |
| 284 | 283 | ||
| 285 | return NULL; | 284 | return NULL; |
| @@ -299,9 +298,9 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
| 299 | * never runs concurrently with itself or free_chan_resources. | 298 | * never runs concurrently with itself or free_chan_resources. |
| 300 | */ | 299 | */ |
| 301 | if (param) { | 300 | if (param) { |
| 302 | struct sh_dmae_slave_config *cfg; | 301 | const struct sh_dmae_slave_config *cfg; |
| 303 | 302 | ||
| 304 | cfg = sh_dmae_find_slave(sh_chan, param->slave_id); | 303 | cfg = sh_dmae_find_slave(sh_chan, param); |
| 305 | if (!cfg) { | 304 | if (!cfg) { |
| 306 | ret = -EINVAL; | 305 | ret = -EINVAL; |
| 307 | goto efindslave; | 306 | goto efindslave; |
| @@ -574,12 +573,14 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
| 574 | { | 573 | { |
| 575 | struct sh_dmae_slave *param; | 574 | struct sh_dmae_slave *param; |
| 576 | struct sh_dmae_chan *sh_chan; | 575 | struct sh_dmae_chan *sh_chan; |
| 576 | dma_addr_t slave_addr; | ||
| 577 | 577 | ||
| 578 | if (!chan) | 578 | if (!chan) |
| 579 | return NULL; | 579 | return NULL; |
| 580 | 580 | ||
| 581 | sh_chan = to_sh_chan(chan); | 581 | sh_chan = to_sh_chan(chan); |
| 582 | param = chan->private; | 582 | param = chan->private; |
| 583 | slave_addr = param->config->addr; | ||
| 583 | 584 | ||
| 584 | /* Someone calling slave DMA on a public channel? */ | 585 | /* Someone calling slave DMA on a public channel? */ |
| 585 | if (!param || !sg_len) { | 586 | if (!param || !sg_len) { |
| @@ -592,7 +593,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
| 592 | * if (param != NULL), this is a successfully requested slave channel, | 593 | * if (param != NULL), this is a successfully requested slave channel, |
| 593 | * therefore param->config != NULL too. | 594 | * therefore param->config != NULL too. |
| 594 | */ | 595 | */ |
| 595 | return sh_dmae_prep_sg(sh_chan, sgl, sg_len, ¶m->config->addr, | 596 | return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr, |
| 596 | direction, flags); | 597 | direction, flags); |
| 597 | } | 598 | } |
| 598 | 599 | ||
| @@ -873,7 +874,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, | |||
| 873 | int irq, unsigned long flags) | 874 | int irq, unsigned long flags) |
| 874 | { | 875 | { |
| 875 | int err; | 876 | int err; |
| 876 | struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; | 877 | const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; |
| 877 | struct platform_device *pdev = to_platform_device(shdev->common.dev); | 878 | struct platform_device *pdev = to_platform_device(shdev->common.dev); |
| 878 | struct sh_dmae_chan *new_sh_chan; | 879 | struct sh_dmae_chan *new_sh_chan; |
| 879 | 880 | ||
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 153609a1e96c..4021275a0a43 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
| 19 | 19 | ||
| 20 | #include <asm/dmaengine.h> | 20 | #define SH_DMAC_MAX_CHANNELS 6 |
| 21 | 21 | #define SH_DMA_SLAVE_NUMBER 256 | |
| 22 | #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ | 22 | #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ |
| 23 | 23 | ||
| 24 | struct device; | 24 | struct device; |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 9c6170cd9aac..87ab0568bb0e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
| @@ -564,7 +564,7 @@ config I2C_STU300 | |||
| 564 | 564 | ||
| 565 | config I2C_VERSATILE | 565 | config I2C_VERSATILE |
| 566 | tristate "ARM Versatile/Realview I2C bus support" | 566 | tristate "ARM Versatile/Realview I2C bus support" |
| 567 | depends on ARCH_VERSATILE || ARCH_REALVIEW | 567 | depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS |
| 568 | select I2C_ALGOBIT | 568 | select I2C_ALGOBIT |
| 569 | help | 569 | help |
| 570 | Say yes if you want to support the I2C serial bus on ARMs Versatile | 570 | Say yes if you want to support the I2C serial bus on ARMs Versatile |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 7e18bcf05a66..46239e47a260 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
| @@ -59,11 +59,11 @@ static unsigned int get_time_pit(void) | |||
| 59 | unsigned long flags; | 59 | unsigned long flags; |
| 60 | unsigned int count; | 60 | unsigned int count; |
| 61 | 61 | ||
| 62 | spin_lock_irqsave(&i8253_lock, flags); | 62 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 63 | outb_p(0x00, 0x43); | 63 | outb_p(0x00, 0x43); |
| 64 | count = inb_p(0x40); | 64 | count = inb_p(0x40); |
| 65 | count |= inb_p(0x40) << 8; | 65 | count |= inb_p(0x40) << 8; |
| 66 | spin_unlock_irqrestore(&i8253_lock, flags); | 66 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 67 | 67 | ||
| 68 | return count; | 68 | return count; |
| 69 | } | 69 | } |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c0b529c06aa..4afe0a3b4884 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
| @@ -146,11 +146,11 @@ static unsigned int get_time_pit(void) | |||
| 146 | unsigned long flags; | 146 | unsigned long flags; |
| 147 | unsigned int count; | 147 | unsigned int count; |
| 148 | 148 | ||
| 149 | spin_lock_irqsave(&i8253_lock, flags); | 149 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 150 | outb_p(0x00, 0x43); | 150 | outb_p(0x00, 0x43); |
| 151 | count = inb_p(0x40); | 151 | count = inb_p(0x40); |
| 152 | count |= inb_p(0x40) << 8; | 152 | count |= inb_p(0x40) << 8; |
| 153 | spin_unlock_irqrestore(&i8253_lock, flags); | 153 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 154 | 154 | ||
| 155 | return count; | 155 | return count; |
| 156 | } | 156 | } |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64c102355f53..a8293388d019 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -143,19 +143,6 @@ config KEYBOARD_BFIN | |||
| 143 | To compile this driver as a module, choose M here: the | 143 | To compile this driver as a module, choose M here: the |
| 144 | module will be called bf54x-keys. | 144 | module will be called bf54x-keys. |
| 145 | 145 | ||
| 146 | config KEYBOARD_CORGI | ||
| 147 | tristate "Corgi keyboard (deprecated)" | ||
| 148 | depends on PXA_SHARPSL | ||
| 149 | help | ||
| 150 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx | ||
| 151 | series of PDAs. | ||
| 152 | |||
| 153 | This driver is now deprecated, use generic GPIO based matrix | ||
| 154 | keyboard driver instead. | ||
| 155 | |||
| 156 | To compile this driver as a module, choose M here: the | ||
| 157 | module will be called corgikbd. | ||
| 158 | |||
| 159 | config KEYBOARD_LKKBD | 146 | config KEYBOARD_LKKBD |
| 160 | tristate "DECstation/VAXstation LK201/LK401 keyboard" | 147 | tristate "DECstation/VAXstation LK201/LK401 keyboard" |
| 161 | select SERIO | 148 | select SERIO |
| @@ -339,19 +326,6 @@ config KEYBOARD_PXA930_ROTARY | |||
| 339 | To compile this driver as a module, choose M here: the | 326 | To compile this driver as a module, choose M here: the |
| 340 | module will be called pxa930_rotary. | 327 | module will be called pxa930_rotary. |
| 341 | 328 | ||
| 342 | config KEYBOARD_SPITZ | ||
| 343 | tristate "Spitz keyboard (deprecated)" | ||
| 344 | depends on PXA_SHARPSL | ||
| 345 | help | ||
| 346 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | ||
| 347 | SL-C3000 and Sl-C3100 series of PDAs. | ||
| 348 | |||
| 349 | This driver is now deprecated, use generic GPIO based matrix | ||
| 350 | keyboard driver instead. | ||
| 351 | |||
| 352 | To compile this driver as a module, choose M here: the | ||
| 353 | module will be called spitzkbd. | ||
| 354 | |||
| 355 | config KEYBOARD_STOWAWAY | 329 | config KEYBOARD_STOWAWAY |
| 356 | tristate "Stowaway keyboard" | 330 | tristate "Stowaway keyboard" |
| 357 | select SERIO | 331 | select SERIO |
| @@ -414,28 +388,6 @@ config KEYBOARD_TWL4030 | |||
| 414 | To compile this driver as a module, choose M here: the | 388 | To compile this driver as a module, choose M here: the |
| 415 | module will be called twl4030_keypad. | 389 | module will be called twl4030_keypad. |
| 416 | 390 | ||
| 417 | config KEYBOARD_TOSA | ||
| 418 | tristate "Tosa keyboard (deprecated)" | ||
| 419 | depends on MACH_TOSA | ||
| 420 | help | ||
| 421 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | ||
| 422 | |||
| 423 | This driver is now deprecated, use generic GPIO based matrix | ||
| 424 | keyboard driver instead. | ||
| 425 | |||
| 426 | To compile this driver as a module, choose M here: the | ||
| 427 | module will be called tosakbd. | ||
| 428 | |||
| 429 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
| 430 | bool "Tosa keyboard: use extended keycodes" | ||
| 431 | depends on KEYBOARD_TOSA | ||
| 432 | help | ||
| 433 | Say Y here to enable the tosa keyboard driver to generate extended | ||
| 434 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | ||
| 435 | by either console keyboard driver or by Kdrive keybd driver. | ||
| 436 | |||
| 437 | Say Y only if you know, what you are doing! | ||
| 438 | |||
| 439 | config KEYBOARD_XTKBD | 391 | config KEYBOARD_XTKBD |
| 440 | tristate "XT keyboard" | 392 | tristate "XT keyboard" |
| 441 | select SERIO | 393 | select SERIO |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 706c6b5ed5f4..9a74127e4d17 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | |||
| 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
| 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
| 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
| 14 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | ||
| 15 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | 14 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o |
| 16 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 15 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
| 17 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 16 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
| @@ -33,10 +32,8 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | |||
| 33 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 32 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
| 34 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 33 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
| 35 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 34 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
| 36 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | ||
| 37 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 35 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
| 38 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 36 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
| 39 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | ||
| 40 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 37 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
| 41 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 38 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
| 42 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | 39 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c deleted file mode 100644 index 634af6a8e6b3..000000000000 --- a/drivers/input/keyboard/corgikbd.c +++ /dev/null | |||
| @@ -1,414 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Keyboard driver for Sharp Corgi models (SL-C7xx) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2004-2005 Richard Purdie | ||
| 5 | * | ||
| 6 | * Based on xtkbd.c/locomkbd.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.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/corgi.h> | ||
| 24 | #include <mach/pxa2xx-gpio.h> | ||
| 25 | #include <asm/hardware/scoop.h> | ||
| 26 | |||
| 27 | #define KB_ROWS 8 | ||
| 28 | #define KB_COLS 12 | ||
| 29 | #define KB_ROWMASK(r) (1 << (r)) | ||
| 30 | #define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) | ||
| 31 | /* zero code, 124 scancodes */ | ||
| 32 | #define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) | ||
| 33 | |||
| 34 | #define SCAN_INTERVAL (50) /* ms */ | ||
| 35 | #define HINGE_SCAN_INTERVAL (250) /* ms */ | ||
| 36 | |||
| 37 | #define CORGI_KEY_CALENDER KEY_F1 | ||
| 38 | #define CORGI_KEY_ADDRESS KEY_F2 | ||
| 39 | #define CORGI_KEY_FN KEY_F3 | ||
| 40 | #define CORGI_KEY_CANCEL KEY_F4 | ||
| 41 | #define CORGI_KEY_OFF KEY_SUSPEND | ||
| 42 | #define CORGI_KEY_EXOK KEY_F5 | ||
| 43 | #define CORGI_KEY_EXCANCEL KEY_F6 | ||
| 44 | #define CORGI_KEY_EXJOGDOWN KEY_F7 | ||
| 45 | #define CORGI_KEY_EXJOGUP KEY_F8 | ||
| 46 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL | ||
| 47 | #define CORGI_KEY_JAP2 KEY_LEFTALT | ||
| 48 | #define CORGI_KEY_MAIL KEY_F10 | ||
| 49 | #define CORGI_KEY_OK KEY_F11 | ||
| 50 | #define CORGI_KEY_MENU KEY_F12 | ||
| 51 | |||
| 52 | static unsigned char corgikbd_keycode[NR_SCANCODES] = { | ||
| 53 | 0, /* 0 */ | ||
| 54 | 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ | ||
| 55 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ | ||
| 56 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
| 57 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | ||
| 58 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ | ||
| 59 | CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ | ||
| 60 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ | ||
| 61 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ | ||
| 62 | }; | ||
| 63 | |||
| 64 | |||
| 65 | struct corgikbd { | ||
| 66 | unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; | ||
| 67 | struct input_dev *input; | ||
| 68 | |||
| 69 | spinlock_t lock; | ||
| 70 | struct timer_list timer; | ||
| 71 | struct timer_list htimer; | ||
| 72 | |||
| 73 | unsigned int suspended; | ||
| 74 | unsigned long suspend_jiffies; | ||
| 75 | }; | ||
| 76 | |||
| 77 | #define KB_DISCHARGE_DELAY 10 | ||
| 78 | #define KB_ACTIVATE_DELAY 10 | ||
| 79 | |||
| 80 | /* Helper functions for reading the keyboard matrix | ||
| 81 | * Note: We should really be using the generic gpio functions to alter | ||
| 82 | * GPDR but it requires a function call per GPIO bit which is | ||
| 83 | * excessive when we need to access 12 bits at once, multiple times. | ||
| 84 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
| 85 | * or similar. | ||
| 86 | */ | ||
| 87 | static inline void corgikbd_discharge_all(void) | ||
| 88 | { | ||
| 89 | /* STROBE All HiZ */ | ||
| 90 | GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; | ||
| 91 | GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline void corgikbd_activate_all(void) | ||
| 95 | { | ||
| 96 | /* STROBE ALL -> High */ | ||
| 97 | GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; | ||
| 98 | GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; | ||
| 99 | |||
| 100 | udelay(KB_DISCHARGE_DELAY); | ||
| 101 | |||
| 102 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
| 103 | GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; | ||
| 104 | GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void corgikbd_activate_col(int col) | ||
| 108 | { | ||
| 109 | /* STROBE col -> High, not col -> HiZ */ | ||
| 110 | GPSR2 = CORGI_GPIO_STROBE_BIT(col); | ||
| 111 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | ||
| 112 | } | ||
| 113 | |||
| 114 | static inline void corgikbd_reset_col(int col) | ||
| 115 | { | ||
| 116 | /* STROBE col -> Low */ | ||
| 117 | GPCR2 = CORGI_GPIO_STROBE_BIT(col); | ||
| 118 | /* STROBE col -> out, not col -> HiZ */ | ||
| 119 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | ||
| 120 | } | ||
| 121 | |||
| 122 | #define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) | ||
| 123 | |||
| 124 | /* | ||
| 125 | * The corgi keyboard only generates interrupts when a key is pressed. | ||
| 126 | * When a key is pressed, we enable a timer which then scans the | ||
| 127 | * keyboard to detect when the key is released. | ||
| 128 | */ | ||
| 129 | |||
| 130 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
| 131 | static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data) | ||
| 132 | { | ||
| 133 | unsigned int row, col, rowd; | ||
| 134 | unsigned long flags; | ||
| 135 | unsigned int num_pressed; | ||
| 136 | |||
| 137 | if (corgikbd_data->suspended) | ||
| 138 | return; | ||
| 139 | |||
| 140 | spin_lock_irqsave(&corgikbd_data->lock, flags); | ||
| 141 | |||
| 142 | num_pressed = 0; | ||
| 143 | for (col = 0; col < KB_COLS; col++) { | ||
| 144 | /* | ||
| 145 | * Discharge the output driver capacitatance | ||
| 146 | * in the keyboard matrix. (Yes it is significant..) | ||
| 147 | */ | ||
| 148 | |||
| 149 | corgikbd_discharge_all(); | ||
| 150 | udelay(KB_DISCHARGE_DELAY); | ||
| 151 | |||
| 152 | corgikbd_activate_col(col); | ||
| 153 | udelay(KB_ACTIVATE_DELAY); | ||
| 154 | |||
| 155 | rowd = GET_ROWS_STATUS(col); | ||
| 156 | for (row = 0; row < KB_ROWS; row++) { | ||
| 157 | unsigned int scancode, pressed; | ||
| 158 | |||
| 159 | scancode = SCANCODE(row, col); | ||
| 160 | pressed = rowd & KB_ROWMASK(row); | ||
| 161 | |||
| 162 | input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); | ||
| 163 | |||
| 164 | if (pressed) | ||
| 165 | num_pressed++; | ||
| 166 | |||
| 167 | if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) | ||
| 168 | && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { | ||
| 169 | input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); | ||
| 170 | corgikbd_data->suspend_jiffies=jiffies; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | corgikbd_reset_col(col); | ||
| 174 | } | ||
| 175 | |||
| 176 | corgikbd_activate_all(); | ||
| 177 | |||
| 178 | input_sync(corgikbd_data->input); | ||
| 179 | |||
| 180 | /* if any keys are pressed, enable the timer */ | ||
| 181 | if (num_pressed) | ||
| 182 | mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); | ||
| 183 | |||
| 184 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | ||
| 188 | * corgi keyboard interrupt handler. | ||
| 189 | */ | ||
| 190 | static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) | ||
| 191 | { | ||
| 192 | struct corgikbd *corgikbd_data = dev_id; | ||
| 193 | |||
| 194 | if (!timer_pending(&corgikbd_data->timer)) { | ||
| 195 | /** wait chattering delay **/ | ||
| 196 | udelay(20); | ||
| 197 | corgikbd_scankeyboard(corgikbd_data); | ||
| 198 | } | ||
| 199 | |||
| 200 | return IRQ_HANDLED; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * corgi timer checking for released keys | ||
| 205 | */ | ||
| 206 | static void corgikbd_timer_callback(unsigned long data) | ||
| 207 | { | ||
| 208 | struct corgikbd *corgikbd_data = (struct corgikbd *) data; | ||
| 209 | corgikbd_scankeyboard(corgikbd_data); | ||
| 210 | } | ||
| 211 | |||
| 212 | /* | ||
| 213 | * The hinge switches generate no interrupt so they need to be | ||
| 214 | * monitored by a timer. | ||
| 215 | * | ||
| 216 | * We debounce the switches and pass them to the input system. | ||
| 217 | * | ||
| 218 | * gprr == 0x00 - Keyboard with Landscape Screen | ||
| 219 | * 0x08 - No Keyboard with Portrait Screen | ||
| 220 | * 0x0c - Keyboard and Screen Closed | ||
| 221 | */ | ||
| 222 | |||
| 223 | #define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) | ||
| 224 | #define HINGE_STABLE_COUNT 2 | ||
| 225 | static int sharpsl_hinge_state; | ||
| 226 | static int hinge_count; | ||
| 227 | |||
| 228 | static void corgikbd_hinge_timer(unsigned long data) | ||
| 229 | { | ||
| 230 | struct corgikbd *corgikbd_data = (struct corgikbd *) data; | ||
| 231 | unsigned long gprr; | ||
| 232 | unsigned long flags; | ||
| 233 | |||
| 234 | gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); | ||
| 235 | gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); | ||
| 236 | if (gprr != sharpsl_hinge_state) { | ||
| 237 | hinge_count = 0; | ||
| 238 | sharpsl_hinge_state = gprr; | ||
| 239 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
| 240 | hinge_count++; | ||
| 241 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
| 242 | spin_lock_irqsave(&corgikbd_data->lock, flags); | ||
| 243 | |||
| 244 | input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); | ||
| 245 | input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); | ||
| 246 | input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); | ||
| 247 | input_sync(corgikbd_data->input); | ||
| 248 | |||
| 249 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 253 | } | ||
| 254 | |||
| 255 | #ifdef CONFIG_PM | ||
| 256 | static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) | ||
| 257 | { | ||
| 258 | int i; | ||
| 259 | struct corgikbd *corgikbd = platform_get_drvdata(dev); | ||
| 260 | |||
| 261 | corgikbd->suspended = 1; | ||
| 262 | /* strobe 0 is the power key so this can't be made an input for | ||
| 263 | powersaving therefore i = 1 */ | ||
| 264 | for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) | ||
| 265 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); | ||
| 266 | |||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int corgikbd_resume(struct platform_device *dev) | ||
| 271 | { | ||
| 272 | int i; | ||
| 273 | struct corgikbd *corgikbd = platform_get_drvdata(dev); | ||
| 274 | |||
| 275 | for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) | ||
| 276 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 277 | |||
| 278 | /* Upon resume, ignore the suspend key for a short while */ | ||
| 279 | corgikbd->suspend_jiffies=jiffies; | ||
| 280 | corgikbd->suspended = 0; | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | #else | ||
| 285 | #define corgikbd_suspend NULL | ||
| 286 | #define corgikbd_resume NULL | ||
| 287 | #endif | ||
| 288 | |||
| 289 | static int __devinit corgikbd_probe(struct platform_device *pdev) | ||
| 290 | { | ||
| 291 | struct corgikbd *corgikbd; | ||
| 292 | struct input_dev *input_dev; | ||
| 293 | int i, err = -ENOMEM; | ||
| 294 | |||
| 295 | corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); | ||
| 296 | input_dev = input_allocate_device(); | ||
| 297 | if (!corgikbd || !input_dev) | ||
| 298 | goto fail; | ||
| 299 | |||
| 300 | platform_set_drvdata(pdev, corgikbd); | ||
| 301 | |||
| 302 | corgikbd->input = input_dev; | ||
| 303 | spin_lock_init(&corgikbd->lock); | ||
| 304 | |||
| 305 | /* Init Keyboard rescan timer */ | ||
| 306 | init_timer(&corgikbd->timer); | ||
| 307 | corgikbd->timer.function = corgikbd_timer_callback; | ||
| 308 | corgikbd->timer.data = (unsigned long) corgikbd; | ||
| 309 | |||
| 310 | /* Init Hinge Timer */ | ||
| 311 | init_timer(&corgikbd->htimer); | ||
| 312 | corgikbd->htimer.function = corgikbd_hinge_timer; | ||
| 313 | corgikbd->htimer.data = (unsigned long) corgikbd; | ||
| 314 | |||
| 315 | corgikbd->suspend_jiffies=jiffies; | ||
| 316 | |||
| 317 | memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); | ||
| 318 | |||
| 319 | input_dev->name = "Corgi Keyboard"; | ||
| 320 | input_dev->phys = "corgikbd/input0"; | ||
| 321 | input_dev->id.bustype = BUS_HOST; | ||
| 322 | input_dev->id.vendor = 0x0001; | ||
| 323 | input_dev->id.product = 0x0001; | ||
| 324 | input_dev->id.version = 0x0100; | ||
| 325 | input_dev->dev.parent = &pdev->dev; | ||
| 326 | |||
| 327 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
| 328 | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); | ||
| 329 | input_dev->keycode = corgikbd->keycode; | ||
| 330 | input_dev->keycodesize = sizeof(unsigned char); | ||
| 331 | input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode); | ||
| 332 | |||
| 333 | for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) | ||
| 334 | set_bit(corgikbd->keycode[i], input_dev->keybit); | ||
| 335 | clear_bit(0, input_dev->keybit); | ||
| 336 | set_bit(SW_LID, input_dev->swbit); | ||
| 337 | set_bit(SW_TABLET_MODE, input_dev->swbit); | ||
| 338 | set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); | ||
| 339 | |||
| 340 | err = input_register_device(corgikbd->input); | ||
| 341 | if (err) | ||
| 342 | goto fail; | ||
| 343 | |||
| 344 | mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 345 | |||
| 346 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
| 347 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { | ||
| 348 | pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); | ||
| 349 | if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, | ||
| 350 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
| 351 | "corgikbd", corgikbd)) | ||
| 352 | printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); | ||
| 353 | } | ||
| 354 | |||
| 355 | /* Set Strobe lines as outputs - set high */ | ||
| 356 | for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) | ||
| 357 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 358 | |||
| 359 | /* Setup the headphone jack as an input */ | ||
| 360 | pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | |||
| 364 | fail: input_free_device(input_dev); | ||
| 365 | kfree(corgikbd); | ||
| 366 | return err; | ||
| 367 | } | ||
| 368 | |||
| 369 | static int __devexit corgikbd_remove(struct platform_device *pdev) | ||
| 370 | { | ||
| 371 | int i; | ||
| 372 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); | ||
| 373 | |||
| 374 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) | ||
| 375 | free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd); | ||
| 376 | |||
| 377 | del_timer_sync(&corgikbd->htimer); | ||
| 378 | del_timer_sync(&corgikbd->timer); | ||
| 379 | |||
| 380 | input_unregister_device(corgikbd->input); | ||
| 381 | |||
| 382 | kfree(corgikbd); | ||
| 383 | |||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static struct platform_driver corgikbd_driver = { | ||
| 388 | .probe = corgikbd_probe, | ||
| 389 | .remove = __devexit_p(corgikbd_remove), | ||
| 390 | .suspend = corgikbd_suspend, | ||
| 391 | .resume = corgikbd_resume, | ||
| 392 | .driver = { | ||
| 393 | .name = "corgi-keyboard", | ||
| 394 | .owner = THIS_MODULE, | ||
| 395 | }, | ||
| 396 | }; | ||
| 397 | |||
| 398 | static int __init corgikbd_init(void) | ||
| 399 | { | ||
| 400 | return platform_driver_register(&corgikbd_driver); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void __exit corgikbd_exit(void) | ||
| 404 | { | ||
| 405 | platform_driver_unregister(&corgikbd_driver); | ||
| 406 | } | ||
| 407 | |||
| 408 | module_init(corgikbd_init); | ||
| 409 | module_exit(corgikbd_exit); | ||
| 410 | |||
| 411 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 412 | MODULE_DESCRIPTION("Corgi Keyboard Driver"); | ||
| 413 | MODULE_LICENSE("GPL v2"); | ||
| 414 | MODULE_ALIAS("platform:corgi-keyboard"); | ||
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c deleted file mode 100644 index 13967422658c..000000000000 --- a/drivers/input/keyboard/spitzkbd.c +++ /dev/null | |||
| @@ -1,496 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Richard Purdie | ||
| 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.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/spitz.h> | ||
| 24 | #include <mach/pxa2xx-gpio.h> | ||
| 25 | |||
| 26 | #define KB_ROWS 7 | ||
| 27 | #define KB_COLS 11 | ||
| 28 | #define KB_ROWMASK(r) (1 << (r)) | ||
| 29 | #define SCANCODE(r,c) (((r)<<4) + (c) + 1) | ||
| 30 | #define NR_SCANCODES ((KB_ROWS<<4) + 1) | ||
| 31 | |||
| 32 | #define SCAN_INTERVAL (50) /* ms */ | ||
| 33 | #define HINGE_SCAN_INTERVAL (150) /* ms */ | ||
| 34 | |||
| 35 | #define SPITZ_KEY_CALENDER KEY_F1 | ||
| 36 | #define SPITZ_KEY_ADDRESS KEY_F2 | ||
| 37 | #define SPITZ_KEY_FN KEY_F3 | ||
| 38 | #define SPITZ_KEY_CANCEL KEY_F4 | ||
| 39 | #define SPITZ_KEY_EXOK KEY_F5 | ||
| 40 | #define SPITZ_KEY_EXCANCEL KEY_F6 | ||
| 41 | #define SPITZ_KEY_EXJOGDOWN KEY_F7 | ||
| 42 | #define SPITZ_KEY_EXJOGUP KEY_F8 | ||
| 43 | #define SPITZ_KEY_JAP1 KEY_LEFTALT | ||
| 44 | #define SPITZ_KEY_JAP2 KEY_RIGHTCTRL | ||
| 45 | #define SPITZ_KEY_SYNC KEY_F9 | ||
| 46 | #define SPITZ_KEY_MAIL KEY_F10 | ||
| 47 | #define SPITZ_KEY_OK KEY_F11 | ||
| 48 | #define SPITZ_KEY_MENU KEY_F12 | ||
| 49 | |||
| 50 | static unsigned char spitzkbd_keycode[NR_SCANCODES] = { | ||
| 51 | 0, /* 0 */ | ||
| 52 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ | ||
| 53 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ | ||
| 54 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
| 55 | SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | ||
| 56 | SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ | ||
| 57 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ | ||
| 58 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int spitz_strobes[] = { | ||
| 62 | SPITZ_GPIO_KEY_STROBE0, | ||
| 63 | SPITZ_GPIO_KEY_STROBE1, | ||
| 64 | SPITZ_GPIO_KEY_STROBE2, | ||
| 65 | SPITZ_GPIO_KEY_STROBE3, | ||
| 66 | SPITZ_GPIO_KEY_STROBE4, | ||
| 67 | SPITZ_GPIO_KEY_STROBE5, | ||
| 68 | SPITZ_GPIO_KEY_STROBE6, | ||
| 69 | SPITZ_GPIO_KEY_STROBE7, | ||
| 70 | SPITZ_GPIO_KEY_STROBE8, | ||
| 71 | SPITZ_GPIO_KEY_STROBE9, | ||
| 72 | SPITZ_GPIO_KEY_STROBE10, | ||
| 73 | }; | ||
| 74 | |||
| 75 | static int spitz_senses[] = { | ||
| 76 | SPITZ_GPIO_KEY_SENSE0, | ||
| 77 | SPITZ_GPIO_KEY_SENSE1, | ||
| 78 | SPITZ_GPIO_KEY_SENSE2, | ||
| 79 | SPITZ_GPIO_KEY_SENSE3, | ||
| 80 | SPITZ_GPIO_KEY_SENSE4, | ||
| 81 | SPITZ_GPIO_KEY_SENSE5, | ||
| 82 | SPITZ_GPIO_KEY_SENSE6, | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct spitzkbd { | ||
| 86 | unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; | ||
| 87 | struct input_dev *input; | ||
| 88 | char phys[32]; | ||
| 89 | |||
| 90 | spinlock_t lock; | ||
| 91 | struct timer_list timer; | ||
| 92 | struct timer_list htimer; | ||
| 93 | |||
| 94 | unsigned int suspended; | ||
| 95 | unsigned long suspend_jiffies; | ||
| 96 | }; | ||
| 97 | |||
| 98 | #define KB_DISCHARGE_DELAY 10 | ||
| 99 | #define KB_ACTIVATE_DELAY 10 | ||
| 100 | |||
| 101 | /* Helper functions for reading the keyboard matrix | ||
| 102 | * Note: We should really be using the generic gpio functions to alter | ||
| 103 | * GPDR but it requires a function call per GPIO bit which is | ||
| 104 | * excessive when we need to access 11 bits at once, multiple times. | ||
| 105 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
| 106 | * or similar. | ||
| 107 | */ | ||
| 108 | static inline void spitzkbd_discharge_all(void) | ||
| 109 | { | ||
| 110 | /* STROBE All HiZ */ | ||
| 111 | GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
| 112 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
| 113 | GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
| 114 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
| 115 | GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
| 116 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
| 117 | GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
| 118 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline void spitzkbd_activate_all(void) | ||
| 122 | { | ||
| 123 | /* STROBE ALL -> High */ | ||
| 124 | GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
| 125 | GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; | ||
| 126 | GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
| 127 | GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; | ||
| 128 | GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
| 129 | GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; | ||
| 130 | GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
| 131 | GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; | ||
| 132 | |||
| 133 | udelay(KB_DISCHARGE_DELAY); | ||
| 134 | |||
| 135 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
| 136 | GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; | ||
| 137 | GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; | ||
| 138 | GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; | ||
| 139 | GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; | ||
| 140 | } | ||
| 141 | |||
| 142 | static inline void spitzkbd_activate_col(int col) | ||
| 143 | { | ||
| 144 | int gpio = spitz_strobes[col]; | ||
| 145 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
| 146 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
| 147 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
| 148 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
| 149 | GPSR(gpio) = GPIO_bit(gpio); | ||
| 150 | GPDR(gpio) |= GPIO_bit(gpio); | ||
| 151 | } | ||
| 152 | |||
| 153 | static inline void spitzkbd_reset_col(int col) | ||
| 154 | { | ||
| 155 | int gpio = spitz_strobes[col]; | ||
| 156 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
| 157 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
| 158 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
| 159 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
| 160 | GPCR(gpio) = GPIO_bit(gpio); | ||
| 161 | GPDR(gpio) |= GPIO_bit(gpio); | ||
| 162 | } | ||
| 163 | |||
| 164 | static inline int spitzkbd_get_row_status(int col) | ||
| 165 | { | ||
| 166 | return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) | ||
| 167 | | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) | ||
| 168 | | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); | ||
| 169 | } | ||
| 170 | |||
| 171 | /* | ||
| 172 | * The spitz keyboard only generates interrupts when a key is pressed. | ||
| 173 | * When a key is pressed, we enable a timer which then scans the | ||
| 174 | * keyboard to detect when the key is released. | ||
| 175 | */ | ||
| 176 | |||
| 177 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
| 178 | static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data) | ||
| 179 | { | ||
| 180 | unsigned int row, col, rowd; | ||
| 181 | unsigned long flags; | ||
| 182 | unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); | ||
| 183 | |||
| 184 | if (spitzkbd_data->suspended) | ||
| 185 | return; | ||
| 186 | |||
| 187 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
| 188 | |||
| 189 | num_pressed = 0; | ||
| 190 | for (col = 0; col < KB_COLS; col++) { | ||
| 191 | /* | ||
| 192 | * Discharge the output driver capacitatance | ||
| 193 | * in the keyboard matrix. (Yes it is significant..) | ||
| 194 | */ | ||
| 195 | |||
| 196 | spitzkbd_discharge_all(); | ||
| 197 | udelay(KB_DISCHARGE_DELAY); | ||
| 198 | |||
| 199 | spitzkbd_activate_col(col); | ||
| 200 | udelay(KB_ACTIVATE_DELAY); | ||
| 201 | |||
| 202 | rowd = spitzkbd_get_row_status(col); | ||
| 203 | for (row = 0; row < KB_ROWS; row++) { | ||
| 204 | unsigned int scancode, pressed; | ||
| 205 | |||
| 206 | scancode = SCANCODE(row, col); | ||
| 207 | pressed = rowd & KB_ROWMASK(row); | ||
| 208 | |||
| 209 | input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); | ||
| 210 | |||
| 211 | if (pressed) | ||
| 212 | num_pressed++; | ||
| 213 | } | ||
| 214 | spitzkbd_reset_col(col); | ||
| 215 | } | ||
| 216 | |||
| 217 | spitzkbd_activate_all(); | ||
| 218 | |||
| 219 | input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); | ||
| 220 | input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey); | ||
| 221 | |||
| 222 | if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { | ||
| 223 | input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); | ||
| 224 | spitzkbd_data->suspend_jiffies = jiffies; | ||
| 225 | } | ||
| 226 | |||
| 227 | input_sync(spitzkbd_data->input); | ||
| 228 | |||
| 229 | /* if any keys are pressed, enable the timer */ | ||
| 230 | if (num_pressed) | ||
| 231 | mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); | ||
| 232 | |||
| 233 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * spitz keyboard interrupt handler. | ||
| 238 | */ | ||
| 239 | static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id) | ||
| 240 | { | ||
| 241 | struct spitzkbd *spitzkbd_data = dev_id; | ||
| 242 | |||
| 243 | if (!timer_pending(&spitzkbd_data->timer)) { | ||
| 244 | /** wait chattering delay **/ | ||
| 245 | udelay(20); | ||
| 246 | spitzkbd_scankeyboard(spitzkbd_data); | ||
| 247 | } | ||
| 248 | |||
| 249 | return IRQ_HANDLED; | ||
| 250 | } | ||
| 251 | |||
| 252 | /* | ||
| 253 | * spitz timer checking for released keys | ||
| 254 | */ | ||
| 255 | static void spitzkbd_timer_callback(unsigned long data) | ||
| 256 | { | ||
| 257 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
| 258 | |||
| 259 | spitzkbd_scankeyboard(spitzkbd_data); | ||
| 260 | } | ||
| 261 | |||
| 262 | /* | ||
| 263 | * The hinge switches generate an interrupt. | ||
| 264 | * We debounce the switches and pass them to the input system. | ||
| 265 | */ | ||
| 266 | |||
| 267 | static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id) | ||
| 268 | { | ||
| 269 | struct spitzkbd *spitzkbd_data = dev_id; | ||
| 270 | |||
| 271 | if (!timer_pending(&spitzkbd_data->htimer)) | ||
| 272 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 273 | |||
| 274 | return IRQ_HANDLED; | ||
| 275 | } | ||
| 276 | |||
| 277 | #define HINGE_STABLE_COUNT 2 | ||
| 278 | static int sharpsl_hinge_state; | ||
| 279 | static int hinge_count; | ||
| 280 | |||
| 281 | static void spitzkbd_hinge_timer(unsigned long data) | ||
| 282 | { | ||
| 283 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
| 284 | unsigned long state; | ||
| 285 | unsigned long flags; | ||
| 286 | |||
| 287 | state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); | ||
| 288 | state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); | ||
| 289 | if (state != sharpsl_hinge_state) { | ||
| 290 | hinge_count = 0; | ||
| 291 | sharpsl_hinge_state = state; | ||
| 292 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
| 293 | hinge_count++; | ||
| 294 | } | ||
| 295 | |||
| 296 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
| 297 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
| 298 | |||
| 299 | input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); | ||
| 300 | input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); | ||
| 301 | input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); | ||
| 302 | input_sync(spitzkbd_data->input); | ||
| 303 | |||
| 304 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
| 305 | } else { | ||
| 306 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | #ifdef CONFIG_PM | ||
| 311 | static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state) | ||
| 312 | { | ||
| 313 | int i; | ||
| 314 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
| 315 | spitzkbd->suspended = 1; | ||
| 316 | |||
| 317 | /* Set Strobe lines as inputs - *except* strobe line 0 leave this | ||
| 318 | enabled so we can detect a power button press for resume */ | ||
| 319 | for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) | ||
| 320 | pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int spitzkbd_resume(struct platform_device *dev) | ||
| 326 | { | ||
| 327 | int i; | ||
| 328 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
| 329 | |||
| 330 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
| 331 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 332 | |||
| 333 | /* Upon resume, ignore the suspend key for a short while */ | ||
| 334 | spitzkbd->suspend_jiffies = jiffies; | ||
| 335 | spitzkbd->suspended = 0; | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | #else | ||
| 340 | #define spitzkbd_suspend NULL | ||
| 341 | #define spitzkbd_resume NULL | ||
| 342 | #endif | ||
| 343 | |||
| 344 | static int __devinit spitzkbd_probe(struct platform_device *dev) | ||
| 345 | { | ||
| 346 | struct spitzkbd *spitzkbd; | ||
| 347 | struct input_dev *input_dev; | ||
| 348 | int i, err = -ENOMEM; | ||
| 349 | |||
| 350 | spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); | ||
| 351 | input_dev = input_allocate_device(); | ||
| 352 | if (!spitzkbd || !input_dev) | ||
| 353 | goto fail; | ||
| 354 | |||
| 355 | platform_set_drvdata(dev, spitzkbd); | ||
| 356 | strcpy(spitzkbd->phys, "spitzkbd/input0"); | ||
| 357 | |||
| 358 | spin_lock_init(&spitzkbd->lock); | ||
| 359 | |||
| 360 | /* Init Keyboard rescan timer */ | ||
| 361 | init_timer(&spitzkbd->timer); | ||
| 362 | spitzkbd->timer.function = spitzkbd_timer_callback; | ||
| 363 | spitzkbd->timer.data = (unsigned long) spitzkbd; | ||
| 364 | |||
| 365 | /* Init Hinge Timer */ | ||
| 366 | init_timer(&spitzkbd->htimer); | ||
| 367 | spitzkbd->htimer.function = spitzkbd_hinge_timer; | ||
| 368 | spitzkbd->htimer.data = (unsigned long) spitzkbd; | ||
| 369 | |||
| 370 | spitzkbd->suspend_jiffies = jiffies; | ||
| 371 | |||
| 372 | spitzkbd->input = input_dev; | ||
| 373 | |||
| 374 | input_dev->name = "Spitz Keyboard"; | ||
| 375 | input_dev->phys = spitzkbd->phys; | ||
| 376 | input_dev->dev.parent = &dev->dev; | ||
| 377 | |||
| 378 | input_dev->id.bustype = BUS_HOST; | ||
| 379 | input_dev->id.vendor = 0x0001; | ||
| 380 | input_dev->id.product = 0x0001; | ||
| 381 | input_dev->id.version = 0x0100; | ||
| 382 | |||
| 383 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
| 384 | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); | ||
| 385 | input_dev->keycode = spitzkbd->keycode; | ||
| 386 | input_dev->keycodesize = sizeof(unsigned char); | ||
| 387 | input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode); | ||
| 388 | |||
| 389 | memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); | ||
| 390 | for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) | ||
| 391 | set_bit(spitzkbd->keycode[i], input_dev->keybit); | ||
| 392 | clear_bit(0, input_dev->keybit); | ||
| 393 | set_bit(KEY_SUSPEND, input_dev->keybit); | ||
| 394 | set_bit(SW_LID, input_dev->swbit); | ||
| 395 | set_bit(SW_TABLET_MODE, input_dev->swbit); | ||
| 396 | set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); | ||
| 397 | |||
| 398 | err = input_register_device(input_dev); | ||
| 399 | if (err) | ||
| 400 | goto fail; | ||
| 401 | |||
| 402 | mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 403 | |||
| 404 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
| 405 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { | ||
| 406 | pxa_gpio_mode(spitz_senses[i] | GPIO_IN); | ||
| 407 | if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, | ||
| 408 | IRQF_DISABLED|IRQF_TRIGGER_RISING, | ||
| 409 | "Spitzkbd Sense", spitzkbd)) | ||
| 410 | printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); | ||
| 411 | } | ||
| 412 | |||
| 413 | /* Set Strobe lines as outputs - set high */ | ||
| 414 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
| 415 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 416 | |||
| 417 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
| 418 | pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); | ||
| 419 | pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); | ||
| 420 | pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); | ||
| 421 | |||
| 422 | request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, | ||
| 423 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 424 | "Spitzkbd Sync", spitzkbd); | ||
| 425 | request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, | ||
| 426 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 427 | "Spitzkbd PwrOn", spitzkbd); | ||
| 428 | request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, | ||
| 429 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 430 | "Spitzkbd SWA", spitzkbd); | ||
| 431 | request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, | ||
| 432 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 433 | "Spitzkbd SWB", spitzkbd); | ||
| 434 | request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, | ||
| 435 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 436 | "Spitzkbd HP", spitzkbd); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | |||
| 440 | fail: input_free_device(input_dev); | ||
| 441 | kfree(spitzkbd); | ||
| 442 | return err; | ||
| 443 | } | ||
| 444 | |||
| 445 | static int __devexit spitzkbd_remove(struct platform_device *dev) | ||
| 446 | { | ||
| 447 | int i; | ||
| 448 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
| 449 | |||
| 450 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) | ||
| 451 | free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); | ||
| 452 | |||
| 453 | free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); | ||
| 454 | free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); | ||
| 455 | free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); | ||
| 456 | free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); | ||
| 457 | free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); | ||
| 458 | |||
| 459 | del_timer_sync(&spitzkbd->htimer); | ||
| 460 | del_timer_sync(&spitzkbd->timer); | ||
| 461 | |||
| 462 | input_unregister_device(spitzkbd->input); | ||
| 463 | |||
| 464 | kfree(spitzkbd); | ||
| 465 | |||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | static struct platform_driver spitzkbd_driver = { | ||
| 470 | .probe = spitzkbd_probe, | ||
| 471 | .remove = __devexit_p(spitzkbd_remove), | ||
| 472 | .suspend = spitzkbd_suspend, | ||
| 473 | .resume = spitzkbd_resume, | ||
| 474 | .driver = { | ||
| 475 | .name = "spitz-keyboard", | ||
| 476 | .owner = THIS_MODULE, | ||
| 477 | }, | ||
| 478 | }; | ||
| 479 | |||
| 480 | static int __init spitzkbd_init(void) | ||
| 481 | { | ||
| 482 | return platform_driver_register(&spitzkbd_driver); | ||
| 483 | } | ||
| 484 | |||
| 485 | static void __exit spitzkbd_exit(void) | ||
| 486 | { | ||
| 487 | platform_driver_unregister(&spitzkbd_driver); | ||
| 488 | } | ||
| 489 | |||
| 490 | module_init(spitzkbd_init); | ||
| 491 | module_exit(spitzkbd_exit); | ||
| 492 | |||
| 493 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 494 | MODULE_DESCRIPTION("Spitz Keyboard Driver"); | ||
| 495 | MODULE_LICENSE("GPL v2"); | ||
| 496 | MODULE_ALIAS("platform:spitz-keyboard"); | ||
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c deleted file mode 100644 index 3910f269cfc8..000000000000 --- a/drivers/input/keyboard/tosakbd.c +++ /dev/null | |||
| @@ -1,431 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Keyboard driver for Sharp Tosa models (SL-6000x) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Dirk Opfer | ||
| 5 | * Copyright (c) 2007 Dmitry Baryshkov | ||
| 6 | * | ||
| 7 | * Based on xtkbd.c/locomkbd.c/corgikbd.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | |||
| 23 | #include <mach/gpio.h> | ||
| 24 | #include <mach/tosa.h> | ||
| 25 | |||
| 26 | #define KB_ROWMASK(r) (1 << (r)) | ||
| 27 | #define SCANCODE(r, c) (((r)<<4) + (c) + 1) | ||
| 28 | #define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 | ||
| 29 | |||
| 30 | #define SCAN_INTERVAL (HZ/10) | ||
| 31 | |||
| 32 | #define KB_DISCHARGE_DELAY 10 | ||
| 33 | #define KB_ACTIVATE_DELAY 10 | ||
| 34 | |||
| 35 | static unsigned short tosakbd_keycode[NR_SCANCODES] = { | ||
| 36 | 0, | ||
| 37 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | ||
| 38 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 39 | KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, | ||
| 40 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 41 | KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, | ||
| 42 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 43 | KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, | ||
| 44 | KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, | ||
| 45 | KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, | ||
| 46 | 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, | ||
| 47 | KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, | ||
| 48 | 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, | ||
| 49 | KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, | ||
| 50 | 0, 0, 0, | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct tosakbd { | ||
| 54 | unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; | ||
| 55 | struct input_dev *input; | ||
| 56 | bool suspended; | ||
| 57 | spinlock_t lock; /* protect kbd scanning */ | ||
| 58 | struct timer_list timer; | ||
| 59 | }; | ||
| 60 | |||
| 61 | |||
| 62 | /* Helper functions for reading the keyboard matrix | ||
| 63 | * Note: We should really be using the generic gpio functions to alter | ||
| 64 | * GPDR but it requires a function call per GPIO bit which is | ||
| 65 | * excessive when we need to access 12 bits at once, multiple times. | ||
| 66 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
| 67 | * or similar. | ||
| 68 | */ | ||
| 69 | #define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) | ||
| 70 | |||
| 71 | static inline void tosakbd_discharge_all(void) | ||
| 72 | { | ||
| 73 | /* STROBE All HiZ */ | ||
| 74 | GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 75 | GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 76 | GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
| 77 | GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void tosakbd_activate_all(void) | ||
| 81 | { | ||
| 82 | /* STROBE ALL -> High */ | ||
| 83 | GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 84 | GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 85 | GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
| 86 | GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; | ||
| 87 | |||
| 88 | udelay(KB_DISCHARGE_DELAY); | ||
| 89 | |||
| 90 | /* STATE CLEAR */ | ||
| 91 | GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline void tosakbd_activate_col(int col) | ||
| 95 | { | ||
| 96 | if (col <= 5) { | ||
| 97 | /* STROBE col -> High, not col -> HiZ */ | ||
| 98 | GPSR1 = TOSA_GPIO_STROBE_BIT(col); | ||
| 99 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 100 | } else { | ||
| 101 | /* STROBE col -> High, not col -> HiZ */ | ||
| 102 | GPSR2 = TOSA_GPIO_STROBE_BIT(col); | ||
| 103 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void tosakbd_reset_col(int col) | ||
| 108 | { | ||
| 109 | if (col <= 5) { | ||
| 110 | /* STROBE col -> Low */ | ||
| 111 | GPCR1 = TOSA_GPIO_STROBE_BIT(col); | ||
| 112 | /* STROBE col -> out, not col -> HiZ */ | ||
| 113 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 114 | } else { | ||
| 115 | /* STROBE col -> Low */ | ||
| 116 | GPCR2 = TOSA_GPIO_STROBE_BIT(col); | ||
| 117 | /* STROBE col -> out, not col -> HiZ */ | ||
| 118 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | /* | ||
| 122 | * The tosa keyboard only generates interrupts when a key is pressed. | ||
| 123 | * So when a key is pressed, we enable a timer. This timer scans the | ||
| 124 | * keyboard, and this is how we detect when the key is released. | ||
| 125 | */ | ||
| 126 | |||
| 127 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
| 128 | static void tosakbd_scankeyboard(struct platform_device *dev) | ||
| 129 | { | ||
| 130 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 131 | unsigned int row, col, rowd; | ||
| 132 | unsigned long flags; | ||
| 133 | unsigned int num_pressed = 0; | ||
| 134 | |||
| 135 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
| 136 | |||
| 137 | if (tosakbd->suspended) | ||
| 138 | goto out; | ||
| 139 | |||
| 140 | for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { | ||
| 141 | /* | ||
| 142 | * Discharge the output driver capacitatance | ||
| 143 | * in the keyboard matrix. (Yes it is significant..) | ||
| 144 | */ | ||
| 145 | tosakbd_discharge_all(); | ||
| 146 | udelay(KB_DISCHARGE_DELAY); | ||
| 147 | |||
| 148 | tosakbd_activate_col(col); | ||
| 149 | udelay(KB_ACTIVATE_DELAY); | ||
| 150 | |||
| 151 | rowd = GET_ROWS_STATUS(col); | ||
| 152 | |||
| 153 | for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { | ||
| 154 | unsigned int scancode, pressed; | ||
| 155 | scancode = SCANCODE(row, col); | ||
| 156 | pressed = rowd & KB_ROWMASK(row); | ||
| 157 | |||
| 158 | if (pressed && !tosakbd->keycode[scancode]) | ||
| 159 | dev_warn(&dev->dev, | ||
| 160 | "unhandled scancode: 0x%02x\n", | ||
| 161 | scancode); | ||
| 162 | |||
| 163 | input_report_key(tosakbd->input, | ||
| 164 | tosakbd->keycode[scancode], | ||
| 165 | pressed); | ||
| 166 | if (pressed) | ||
| 167 | num_pressed++; | ||
| 168 | } | ||
| 169 | |||
| 170 | tosakbd_reset_col(col); | ||
| 171 | } | ||
| 172 | |||
| 173 | tosakbd_activate_all(); | ||
| 174 | |||
| 175 | input_sync(tosakbd->input); | ||
| 176 | |||
| 177 | /* if any keys are pressed, enable the timer */ | ||
| 178 | if (num_pressed) | ||
| 179 | mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); | ||
| 180 | |||
| 181 | out: | ||
| 182 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
| 183 | } | ||
| 184 | |||
| 185 | /* | ||
| 186 | * tosa keyboard interrupt handler. | ||
| 187 | */ | ||
| 188 | static irqreturn_t tosakbd_interrupt(int irq, void *__dev) | ||
| 189 | { | ||
| 190 | struct platform_device *dev = __dev; | ||
| 191 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 192 | |||
| 193 | if (!timer_pending(&tosakbd->timer)) { | ||
| 194 | /** wait chattering delay **/ | ||
| 195 | udelay(20); | ||
| 196 | tosakbd_scankeyboard(dev); | ||
| 197 | } | ||
| 198 | |||
| 199 | return IRQ_HANDLED; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | ||
| 203 | * tosa timer checking for released keys | ||
| 204 | */ | ||
| 205 | static void tosakbd_timer_callback(unsigned long __dev) | ||
| 206 | { | ||
| 207 | struct platform_device *dev = (struct platform_device *)__dev; | ||
| 208 | |||
| 209 | tosakbd_scankeyboard(dev); | ||
| 210 | } | ||
| 211 | |||
| 212 | #ifdef CONFIG_PM | ||
| 213 | static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | ||
| 214 | { | ||
| 215 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 216 | unsigned long flags; | ||
| 217 | |||
| 218 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
| 219 | tosakbd->suspended = true; | ||
| 220 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
| 221 | |||
| 222 | del_timer_sync(&tosakbd->timer); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int tosakbd_resume(struct platform_device *dev) | ||
| 228 | { | ||
| 229 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 230 | |||
| 231 | tosakbd->suspended = false; | ||
| 232 | tosakbd_scankeyboard(dev); | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | #else | ||
| 237 | #define tosakbd_suspend NULL | ||
| 238 | #define tosakbd_resume NULL | ||
| 239 | #endif | ||
| 240 | |||
| 241 | static int __devinit tosakbd_probe(struct platform_device *pdev) { | ||
| 242 | |||
| 243 | int i; | ||
| 244 | struct tosakbd *tosakbd; | ||
| 245 | struct input_dev *input_dev; | ||
| 246 | int error; | ||
| 247 | |||
| 248 | tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); | ||
| 249 | if (!tosakbd) | ||
| 250 | return -ENOMEM; | ||
| 251 | |||
| 252 | input_dev = input_allocate_device(); | ||
| 253 | if (!input_dev) { | ||
| 254 | kfree(tosakbd); | ||
| 255 | return -ENOMEM; | ||
| 256 | } | ||
| 257 | |||
| 258 | platform_set_drvdata(pdev, tosakbd); | ||
| 259 | |||
| 260 | spin_lock_init(&tosakbd->lock); | ||
| 261 | |||
| 262 | /* Init Keyboard rescan timer */ | ||
| 263 | init_timer(&tosakbd->timer); | ||
| 264 | tosakbd->timer.function = tosakbd_timer_callback; | ||
| 265 | tosakbd->timer.data = (unsigned long) pdev; | ||
| 266 | |||
| 267 | tosakbd->input = input_dev; | ||
| 268 | |||
| 269 | input_set_drvdata(input_dev, tosakbd); | ||
| 270 | input_dev->name = "Tosa Keyboard"; | ||
| 271 | input_dev->phys = "tosakbd/input0"; | ||
| 272 | input_dev->dev.parent = &pdev->dev; | ||
| 273 | |||
| 274 | input_dev->id.bustype = BUS_HOST; | ||
| 275 | input_dev->id.vendor = 0x0001; | ||
| 276 | input_dev->id.product = 0x0001; | ||
| 277 | input_dev->id.version = 0x0100; | ||
| 278 | |||
| 279 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
| 280 | input_dev->keycode = tosakbd->keycode; | ||
| 281 | input_dev->keycodesize = sizeof(tosakbd->keycode[0]); | ||
| 282 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | ||
| 283 | |||
| 284 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | ||
| 285 | |||
| 286 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | ||
| 287 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | ||
| 288 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 289 | |||
| 290 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
| 291 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
| 292 | int gpio = TOSA_GPIO_KEY_SENSE(i); | ||
| 293 | int irq; | ||
| 294 | error = gpio_request(gpio, "tosakbd"); | ||
| 295 | if (error < 0) { | ||
| 296 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
| 297 | " error %d\n", gpio, error); | ||
| 298 | goto fail; | ||
| 299 | } | ||
| 300 | |||
| 301 | error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); | ||
| 302 | if (error < 0) { | ||
| 303 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
| 304 | " direction for GPIO %d, error %d\n", | ||
| 305 | gpio, error); | ||
| 306 | gpio_free(gpio); | ||
| 307 | goto fail; | ||
| 308 | } | ||
| 309 | |||
| 310 | irq = gpio_to_irq(gpio); | ||
| 311 | if (irq < 0) { | ||
| 312 | error = irq; | ||
| 313 | printk(KERN_ERR "gpio-keys: Unable to get irq number" | ||
| 314 | " for GPIO %d, error %d\n", | ||
| 315 | gpio, error); | ||
| 316 | gpio_free(gpio); | ||
| 317 | goto fail; | ||
| 318 | } | ||
| 319 | |||
| 320 | error = request_irq(irq, tosakbd_interrupt, | ||
| 321 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
| 322 | "tosakbd", pdev); | ||
| 323 | |||
| 324 | if (error) { | ||
| 325 | printk("tosakbd: Can't get IRQ: %d: error %d!\n", | ||
| 326 | irq, error); | ||
| 327 | gpio_free(gpio); | ||
| 328 | goto fail; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | /* Set Strobe lines as outputs - set high */ | ||
| 333 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { | ||
| 334 | int gpio = TOSA_GPIO_KEY_STROBE(i); | ||
| 335 | error = gpio_request(gpio, "tosakbd"); | ||
| 336 | if (error < 0) { | ||
| 337 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
| 338 | " error %d\n", gpio, error); | ||
| 339 | goto fail2; | ||
| 340 | } | ||
| 341 | |||
| 342 | error = gpio_direction_output(gpio, 1); | ||
| 343 | if (error < 0) { | ||
| 344 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
| 345 | " direction for GPIO %d, error %d\n", | ||
| 346 | gpio, error); | ||
| 347 | gpio_free(gpio); | ||
| 348 | goto fail2; | ||
| 349 | } | ||
| 350 | |||
| 351 | } | ||
| 352 | |||
| 353 | error = input_register_device(input_dev); | ||
| 354 | if (error) { | ||
| 355 | printk(KERN_ERR "tosakbd: Unable to register input device, " | ||
| 356 | "error: %d\n", error); | ||
| 357 | goto fail2; | ||
| 358 | } | ||
| 359 | |||
| 360 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | |||
| 364 | fail2: | ||
| 365 | while (--i >= 0) | ||
| 366 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
| 367 | |||
| 368 | i = TOSA_KEY_SENSE_NUM; | ||
| 369 | fail: | ||
| 370 | while (--i >= 0) { | ||
| 371 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); | ||
| 372 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
| 373 | } | ||
| 374 | |||
| 375 | platform_set_drvdata(pdev, NULL); | ||
| 376 | input_free_device(input_dev); | ||
| 377 | kfree(tosakbd); | ||
| 378 | |||
| 379 | return error; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int __devexit tosakbd_remove(struct platform_device *dev) | ||
| 383 | { | ||
| 384 | int i; | ||
| 385 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 386 | |||
| 387 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) | ||
| 388 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
| 389 | |||
| 390 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
| 391 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); | ||
| 392 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
| 393 | } | ||
| 394 | |||
| 395 | del_timer_sync(&tosakbd->timer); | ||
| 396 | |||
| 397 | input_unregister_device(tosakbd->input); | ||
| 398 | |||
| 399 | kfree(tosakbd); | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | static struct platform_driver tosakbd_driver = { | ||
| 405 | .probe = tosakbd_probe, | ||
| 406 | .remove = __devexit_p(tosakbd_remove), | ||
| 407 | .suspend = tosakbd_suspend, | ||
| 408 | .resume = tosakbd_resume, | ||
| 409 | .driver = { | ||
| 410 | .name = "tosa-keyboard", | ||
| 411 | .owner = THIS_MODULE, | ||
| 412 | }, | ||
| 413 | }; | ||
| 414 | |||
| 415 | static int __devinit tosakbd_init(void) | ||
| 416 | { | ||
| 417 | return platform_driver_register(&tosakbd_driver); | ||
| 418 | } | ||
| 419 | |||
| 420 | static void __exit tosakbd_exit(void) | ||
| 421 | { | ||
| 422 | platform_driver_unregister(&tosakbd_driver); | ||
| 423 | } | ||
| 424 | |||
| 425 | module_init(tosakbd_init); | ||
| 426 | module_exit(tosakbd_exit); | ||
| 427 | |||
| 428 | MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); | ||
| 429 | MODULE_DESCRIPTION("Tosa Keyboard Driver"); | ||
| 430 | MODULE_LICENSE("GPL v2"); | ||
| 431 | MODULE_ALIAS("platform:tosa-keyboard"); | ||
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index ea4e1fd12651..f080dd31499b 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -30,7 +30,7 @@ MODULE_ALIAS("platform:pcspkr"); | |||
| 30 | #include <asm/i8253.h> | 30 | #include <asm/i8253.h> |
| 31 | #else | 31 | #else |
| 32 | #include <asm/8253pit.h> | 32 | #include <asm/8253pit.h> |
| 33 | static DEFINE_SPINLOCK(i8253_lock); | 33 | static DEFINE_RAW_SPINLOCK(i8253_lock); |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
| @@ -50,7 +50,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 50 | if (value > 20 && value < 32767) | 50 | if (value > 20 && value < 32767) |
| 51 | count = PIT_TICK_RATE / value; | 51 | count = PIT_TICK_RATE / value; |
| 52 | 52 | ||
| 53 | spin_lock_irqsave(&i8253_lock, flags); | 53 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 54 | 54 | ||
| 55 | if (count) { | 55 | if (count) { |
| 56 | /* set command for counter 2, 2 byte write */ | 56 | /* set command for counter 2, 2 byte write */ |
| @@ -65,7 +65,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 65 | outb(inb_p(0x61) & 0xFC, 0x61); | 65 | outb(inb_p(0x61) & 0xFC, 0x61); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | spin_unlock_irqrestore(&i8253_lock, flags); | 68 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 69 | 69 | ||
| 70 | return 0; | 70 | return 0; |
| 71 | } | 71 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d2d6a8..3d1ade2e5196 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY | |||
| 99 | To compile this driver as a module, choose M here: the | 99 | To compile this driver as a module, choose M here: the |
| 100 | module will be called h3600_ts_input. | 100 | module will be called h3600_ts_input. |
| 101 | 101 | ||
| 102 | config TOUCHSCREEN_CORGI | ||
| 103 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" | ||
| 104 | depends on PXA_SHARPSL | ||
| 105 | select CORGI_SSP_DEPRECATED | ||
| 106 | help | ||
| 107 | Say Y here to enable the driver for the touchscreen on the | ||
| 108 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. | ||
| 109 | |||
| 110 | If unsure, say N. | ||
| 111 | |||
| 112 | To compile this driver as a module, choose M here: the | ||
| 113 | module will be called corgi_ts. | ||
| 114 | |||
| 115 | NOTE: this driver is deprecated, try enable SPI and generic | ||
| 116 | ADS7846-based touchscreen driver. | ||
| 117 | |||
| 118 | config TOUCHSCREEN_DA9034 | 102 | config TOUCHSCREEN_DA9034 |
| 119 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 103 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
| 120 | depends on PMIC_DA903X | 104 | depends on PMIC_DA903X |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5cca23..41145d074dec 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -12,7 +12,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o | |||
| 12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
| 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
| 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
| 15 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | ||
| 16 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 15 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
| 17 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 16 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 18 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919d439d..000000000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null | |||
| @@ -1,385 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models | ||
| 3 | * | ||
| 4 | * Copyright (c) 2004-2005 Richard Purdie | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | |||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/irq.h> | ||
| 21 | |||
| 22 | #include <mach/sharpsl.h> | ||
| 23 | #include <mach/hardware.h> | ||
| 24 | #include <mach/pxa2xx-gpio.h> | ||
| 25 | |||
| 26 | |||
| 27 | #define PWR_MODE_ACTIVE 0 | ||
| 28 | #define PWR_MODE_SUSPEND 1 | ||
| 29 | |||
| 30 | #define X_AXIS_MAX 3830 | ||
| 31 | #define X_AXIS_MIN 150 | ||
| 32 | #define Y_AXIS_MAX 3830 | ||
| 33 | #define Y_AXIS_MIN 190 | ||
| 34 | #define PRESSURE_MIN 0 | ||
| 35 | #define PRESSURE_MAX 15000 | ||
| 36 | |||
| 37 | struct ts_event { | ||
| 38 | short pressure; | ||
| 39 | short x; | ||
| 40 | short y; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct corgi_ts { | ||
| 44 | struct input_dev *input; | ||
| 45 | struct timer_list timer; | ||
| 46 | struct ts_event tc; | ||
| 47 | int pendown; | ||
| 48 | int power_mode; | ||
| 49 | int irq_gpio; | ||
| 50 | struct corgits_machinfo *machinfo; | ||
| 51 | }; | ||
| 52 | |||
| 53 | #ifdef CONFIG_PXA25x | ||
| 54 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) | ||
| 55 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) | ||
| 56 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) | ||
| 57 | #endif | ||
| 58 | #ifdef CONFIG_PXA27x | ||
| 59 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) | ||
| 60 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) | ||
| 61 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /* ADS7846 Touch Screen Controller bit definitions */ | ||
| 65 | #define ADSCTRL_PD0 (1u << 0) /* PD0 */ | ||
| 66 | #define ADSCTRL_PD1 (1u << 1) /* PD1 */ | ||
| 67 | #define ADSCTRL_DFR (1u << 2) /* SER/DFR */ | ||
| 68 | #define ADSCTRL_MOD (1u << 3) /* Mode */ | ||
| 69 | #define ADSCTRL_ADR_SH 4 /* Address setting */ | ||
| 70 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ | ||
| 71 | |||
| 72 | /* External Functions */ | ||
| 73 | extern unsigned int get_clk_frequency_khz(int info); | ||
| 74 | |||
| 75 | static unsigned long calc_waittime(struct corgi_ts *corgi_ts) | ||
| 76 | { | ||
| 77 | unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); | ||
| 78 | |||
| 79 | if (hsync_invperiod) | ||
| 80 | return get_clk_frequency_khz(0)*1000/hsync_invperiod; | ||
| 81 | else | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, | ||
| 86 | unsigned int address, unsigned long wait_time) | ||
| 87 | { | ||
| 88 | unsigned long timer1 = 0, timer2, pmnc = 0; | ||
| 89 | int pos = 0; | ||
| 90 | |||
| 91 | if (wait_time && doSend) { | ||
| 92 | PMNC_GET(pmnc); | ||
| 93 | if (!(pmnc & 0x01)) | ||
| 94 | PMNC_SET(0x01); | ||
| 95 | |||
| 96 | /* polling HSync */ | ||
| 97 | corgi_ts->machinfo->wait_hsync(); | ||
| 98 | /* get CCNT */ | ||
| 99 | CCNT(timer1); | ||
| 100 | } | ||
| 101 | |||
| 102 | if (doRecive) | ||
| 103 | pos = corgi_ssp_ads7846_get(); | ||
| 104 | |||
| 105 | if (doSend) { | ||
| 106 | int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; | ||
| 107 | /* dummy command */ | ||
| 108 | corgi_ssp_ads7846_put(cmd); | ||
| 109 | corgi_ssp_ads7846_get(); | ||
| 110 | |||
| 111 | if (wait_time) { | ||
| 112 | /* Wait after HSync */ | ||
| 113 | CCNT(timer2); | ||
| 114 | if (timer2-timer1 > wait_time) { | ||
| 115 | /* too slow - timeout, try again */ | ||
| 116 | corgi_ts->machinfo->wait_hsync(); | ||
| 117 | /* get CCNT */ | ||
| 118 | CCNT(timer1); | ||
| 119 | /* Wait after HSync */ | ||
| 120 | CCNT(timer2); | ||
| 121 | } | ||
| 122 | while (timer2 - timer1 < wait_time) | ||
| 123 | CCNT(timer2); | ||
| 124 | } | ||
| 125 | corgi_ssp_ads7846_put(cmd); | ||
| 126 | if (wait_time && !(pmnc & 0x01)) | ||
| 127 | PMNC_SET(pmnc); | ||
| 128 | } | ||
| 129 | return pos; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int read_xydata(struct corgi_ts *corgi_ts) | ||
| 133 | { | ||
| 134 | unsigned int x, y, z1, z2; | ||
| 135 | unsigned long flags, wait_time; | ||
| 136 | |||
| 137 | /* critical section */ | ||
| 138 | local_irq_save(flags); | ||
| 139 | corgi_ssp_ads7846_lock(); | ||
| 140 | wait_time = calc_waittime(corgi_ts); | ||
| 141 | |||
| 142 | /* Y-axis */ | ||
| 143 | sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); | ||
| 144 | |||
| 145 | /* Y-axis */ | ||
| 146 | sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); | ||
| 147 | |||
| 148 | /* X-axis */ | ||
| 149 | y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); | ||
| 150 | |||
| 151 | /* Z1 */ | ||
| 152 | x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); | ||
| 153 | |||
| 154 | /* Z2 */ | ||
| 155 | z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); | ||
| 156 | z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); | ||
| 157 | |||
| 158 | /* Power-Down Enable */ | ||
| 159 | corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 160 | corgi_ssp_ads7846_get(); | ||
| 161 | |||
| 162 | corgi_ssp_ads7846_unlock(); | ||
| 163 | local_irq_restore(flags); | ||
| 164 | |||
| 165 | if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { | ||
| 166 | corgi_ts->tc.pressure = 0; | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | corgi_ts->tc.x = x; | ||
| 171 | corgi_ts->tc.y = y; | ||
| 172 | corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; | ||
| 173 | return 1; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void new_data(struct corgi_ts *corgi_ts) | ||
| 177 | { | ||
| 178 | struct input_dev *dev = corgi_ts->input; | ||
| 179 | |||
| 180 | if (corgi_ts->power_mode != PWR_MODE_ACTIVE) | ||
| 181 | return; | ||
| 182 | |||
| 183 | if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) | ||
| 184 | return; | ||
| 185 | |||
| 186 | input_report_abs(dev, ABS_X, corgi_ts->tc.x); | ||
| 187 | input_report_abs(dev, ABS_Y, corgi_ts->tc.y); | ||
| 188 | input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); | ||
| 189 | input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); | ||
| 190 | input_sync(dev); | ||
| 191 | } | ||
| 192 | |||
| 193 | static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) | ||
| 194 | { | ||
| 195 | if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { | ||
| 196 | /* Disable Interrupt */ | ||
| 197 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); | ||
| 198 | if (read_xydata(corgi_ts)) { | ||
| 199 | corgi_ts->pendown = 1; | ||
| 200 | new_data(corgi_ts); | ||
| 201 | } | ||
| 202 | mod_timer(&corgi_ts->timer, jiffies + HZ / 100); | ||
| 203 | } else { | ||
| 204 | if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { | ||
| 205 | mod_timer(&corgi_ts->timer, jiffies + HZ / 100); | ||
| 206 | corgi_ts->pendown++; | ||
| 207 | return; | ||
| 208 | } | ||
| 209 | |||
| 210 | if (corgi_ts->pendown) { | ||
| 211 | corgi_ts->tc.pressure = 0; | ||
| 212 | new_data(corgi_ts); | ||
| 213 | } | ||
| 214 | |||
| 215 | /* Enable Falling Edge */ | ||
| 216 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
| 217 | corgi_ts->pendown = 0; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | static void corgi_ts_timer(unsigned long data) | ||
| 222 | { | ||
| 223 | struct corgi_ts *corgits_data = (struct corgi_ts *) data; | ||
| 224 | |||
| 225 | ts_interrupt_main(corgits_data, 1); | ||
| 226 | } | ||
| 227 | |||
| 228 | static irqreturn_t ts_interrupt(int irq, void *dev_id) | ||
| 229 | { | ||
| 230 | struct corgi_ts *corgits_data = dev_id; | ||
| 231 | |||
| 232 | ts_interrupt_main(corgits_data, 0); | ||
| 233 | return IRQ_HANDLED; | ||
| 234 | } | ||
| 235 | |||
| 236 | #ifdef CONFIG_PM | ||
| 237 | static int corgits_suspend(struct platform_device *dev, pm_message_t state) | ||
| 238 | { | ||
| 239 | struct corgi_ts *corgi_ts = platform_get_drvdata(dev); | ||
| 240 | |||
| 241 | if (corgi_ts->pendown) { | ||
| 242 | del_timer_sync(&corgi_ts->timer); | ||
| 243 | corgi_ts->tc.pressure = 0; | ||
| 244 | new_data(corgi_ts); | ||
| 245 | corgi_ts->pendown = 0; | ||
| 246 | } | ||
| 247 | corgi_ts->power_mode = PWR_MODE_SUSPEND; | ||
| 248 | |||
| 249 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int corgits_resume(struct platform_device *dev) | ||
| 255 | { | ||
| 256 | struct corgi_ts *corgi_ts = platform_get_drvdata(dev); | ||
| 257 | |||
| 258 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 259 | /* Enable Falling Edge */ | ||
| 260 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
| 261 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | #else | ||
| 266 | #define corgits_suspend NULL | ||
| 267 | #define corgits_resume NULL | ||
| 268 | #endif | ||
| 269 | |||
| 270 | static int __devinit corgits_probe(struct platform_device *pdev) | ||
| 271 | { | ||
| 272 | struct corgi_ts *corgi_ts; | ||
| 273 | struct input_dev *input_dev; | ||
| 274 | int err = -ENOMEM; | ||
| 275 | |||
| 276 | corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); | ||
| 277 | input_dev = input_allocate_device(); | ||
| 278 | if (!corgi_ts || !input_dev) | ||
| 279 | goto fail1; | ||
| 280 | |||
| 281 | platform_set_drvdata(pdev, corgi_ts); | ||
| 282 | |||
| 283 | corgi_ts->machinfo = pdev->dev.platform_data; | ||
| 284 | corgi_ts->irq_gpio = platform_get_irq(pdev, 0); | ||
| 285 | |||
| 286 | if (corgi_ts->irq_gpio < 0) { | ||
| 287 | err = -ENODEV; | ||
| 288 | goto fail1; | ||
| 289 | } | ||
| 290 | |||
| 291 | corgi_ts->input = input_dev; | ||
| 292 | |||
| 293 | init_timer(&corgi_ts->timer); | ||
| 294 | corgi_ts->timer.data = (unsigned long) corgi_ts; | ||
| 295 | corgi_ts->timer.function = corgi_ts_timer; | ||
| 296 | |||
| 297 | input_dev->name = "Corgi Touchscreen"; | ||
| 298 | input_dev->phys = "corgits/input0"; | ||
| 299 | input_dev->id.bustype = BUS_HOST; | ||
| 300 | input_dev->id.vendor = 0x0001; | ||
| 301 | input_dev->id.product = 0x0002; | ||
| 302 | input_dev->id.version = 0x0100; | ||
| 303 | input_dev->dev.parent = &pdev->dev; | ||
| 304 | |||
| 305 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 306 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 307 | input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); | ||
| 308 | input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); | ||
| 309 | input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); | ||
| 310 | |||
| 311 | pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); | ||
| 312 | |||
| 313 | /* Initiaize ADS7846 Difference Reference mode */ | ||
| 314 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 315 | mdelay(5); | ||
| 316 | corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 317 | mdelay(5); | ||
| 318 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 319 | mdelay(5); | ||
| 320 | corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 321 | mdelay(5); | ||
| 322 | |||
| 323 | if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { | ||
| 324 | err = -EBUSY; | ||
| 325 | goto fail1; | ||
| 326 | } | ||
| 327 | |||
| 328 | err = input_register_device(corgi_ts->input); | ||
| 329 | if (err) | ||
| 330 | goto fail2; | ||
| 331 | |||
| 332 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | ||
| 333 | |||
| 334 | /* Enable Falling Edge */ | ||
| 335 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | |||
| 339 | fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); | ||
| 340 | fail1: input_free_device(input_dev); | ||
| 341 | kfree(corgi_ts); | ||
| 342 | return err; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int __devexit corgits_remove(struct platform_device *pdev) | ||
| 346 | { | ||
| 347 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); | ||
| 348 | |||
| 349 | free_irq(corgi_ts->irq_gpio, corgi_ts); | ||
| 350 | del_timer_sync(&corgi_ts->timer); | ||
| 351 | corgi_ts->machinfo->put_hsync(); | ||
| 352 | input_unregister_device(corgi_ts->input); | ||
| 353 | kfree(corgi_ts); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static struct platform_driver corgits_driver = { | ||
| 359 | .probe = corgits_probe, | ||
| 360 | .remove = __devexit_p(corgits_remove), | ||
| 361 | .suspend = corgits_suspend, | ||
| 362 | .resume = corgits_resume, | ||
| 363 | .driver = { | ||
| 364 | .name = "corgi-ts", | ||
| 365 | .owner = THIS_MODULE, | ||
| 366 | }, | ||
| 367 | }; | ||
| 368 | |||
| 369 | static int __init corgits_init(void) | ||
| 370 | { | ||
| 371 | return platform_driver_register(&corgits_driver); | ||
| 372 | } | ||
| 373 | |||
| 374 | static void __exit corgits_exit(void) | ||
| 375 | { | ||
| 376 | platform_driver_unregister(&corgits_driver); | ||
| 377 | } | ||
| 378 | |||
| 379 | module_init(corgits_init); | ||
| 380 | module_exit(corgits_exit); | ||
| 381 | |||
| 382 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 383 | MODULE_DESCRIPTION("Corgi TouchScreen Driver"); | ||
| 384 | MODULE_LICENSE("GPL"); | ||
| 385 | MODULE_ALIAS("platform:corgi-ts"); | ||
diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c index e7161c4e3798..db9cd0240c6f 100644 --- a/drivers/misc/vmware_balloon.c +++ b/drivers/misc/vmware_balloon.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #include <linux/workqueue.h> | 41 | #include <linux/workqueue.h> |
| 42 | #include <linux/debugfs.h> | 42 | #include <linux/debugfs.h> |
| 43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
| 44 | #include <asm/vmware.h> | 44 | #include <asm/hypervisor.h> |
| 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"); |
| @@ -767,7 +767,7 @@ static int __init vmballoon_init(void) | |||
| 767 | * Check if we are running on VMware's hypervisor and bail out | 767 | * Check if we are running on VMware's hypervisor and bail out |
| 768 | * if we are not. | 768 | * if we are not. |
| 769 | */ | 769 | */ |
| 770 | if (!vmware_platform()) | 770 | if (x86_hyper != &x86_hyper_vmware) |
| 771 | return -ENODEV; | 771 | return -ENODEV; |
| 772 | 772 | ||
| 773 | vmballoon_wq = create_freezeable_workqueue("vmmemctl"); | 773 | vmballoon_wq = create_freezeable_workqueue("vmmemctl"); |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 84c103a7ee13..ff115d920888 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -55,14 +55,16 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | |||
| 55 | host->cclk = host->mclk / (2 * (clk + 1)); | 55 | host->cclk = host->mclk / (2 * (clk + 1)); |
| 56 | } | 56 | } |
| 57 | if (host->hw_designer == AMBA_VENDOR_ST) | 57 | if (host->hw_designer == AMBA_VENDOR_ST) |
| 58 | clk |= MCI_FCEN; /* Bug fix in ST IP block */ | 58 | clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */ |
| 59 | clk |= MCI_CLK_ENABLE; | 59 | clk |= MCI_CLK_ENABLE; |
| 60 | /* This hasn't proven to be worthwhile */ | 60 | /* This hasn't proven to be worthwhile */ |
| 61 | /* clk |= MCI_CLK_PWRSAVE; */ | 61 | /* clk |= MCI_CLK_PWRSAVE; */ |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) | 64 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) |
| 65 | clk |= MCI_WIDE_BUS; | 65 | clk |= MCI_4BIT_BUS; |
| 66 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) | ||
| 67 | clk |= MCI_ST_8BIT_BUS; | ||
| 66 | 68 | ||
| 67 | writel(clk, host->base + MMCICLOCK); | 69 | writel(clk, host->base + MMCICLOCK); |
| 68 | } | 70 | } |
| @@ -629,7 +631,18 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 629 | 631 | ||
| 630 | mmc->ops = &mmci_ops; | 632 | mmc->ops = &mmci_ops; |
| 631 | mmc->f_min = (host->mclk + 511) / 512; | 633 | mmc->f_min = (host->mclk + 511) / 512; |
| 632 | mmc->f_max = min(host->mclk, fmax); | 634 | /* |
| 635 | * If the platform data supplies a maximum operating | ||
| 636 | * frequency, this takes precedence. Else, we fall back | ||
| 637 | * to using the module parameter, which has a (low) | ||
| 638 | * default value in case it is not specified. Either | ||
| 639 | * value must not exceed the clock rate into the block, | ||
| 640 | * of course. | ||
| 641 | */ | ||
| 642 | if (plat->f_max) | ||
| 643 | mmc->f_max = min(host->mclk, plat->f_max); | ||
| 644 | else | ||
| 645 | mmc->f_max = min(host->mclk, fmax); | ||
| 633 | dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); | 646 | dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); |
| 634 | 647 | ||
| 635 | #ifdef CONFIG_REGULATOR | 648 | #ifdef CONFIG_REGULATOR |
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 1ceb9a90f59b..d77062e5e3af 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
| @@ -25,9 +25,11 @@ | |||
| 25 | #define MCI_CLK_ENABLE (1 << 8) | 25 | #define MCI_CLK_ENABLE (1 << 8) |
| 26 | #define MCI_CLK_PWRSAVE (1 << 9) | 26 | #define MCI_CLK_PWRSAVE (1 << 9) |
| 27 | #define MCI_CLK_BYPASS (1 << 10) | 27 | #define MCI_CLK_BYPASS (1 << 10) |
| 28 | #define MCI_WIDE_BUS (1 << 11) | 28 | #define MCI_4BIT_BUS (1 << 11) |
| 29 | /* 8bit wide buses supported in ST Micro versions */ | ||
| 30 | #define MCI_ST_8BIT_BUS (1 << 12) | ||
| 29 | /* HW flow control on the ST Micro version */ | 31 | /* HW flow control on the ST Micro version */ |
| 30 | #define MCI_FCEN (1 << 13) | 32 | #define MCI_ST_FCEN (1 << 13) |
| 31 | 33 | ||
| 32 | #define MMCIARGUMENT 0x008 | 34 | #define MMCIARGUMENT 0x008 |
| 33 | #define MMCICOMMAND 0x00c | 35 | #define MMCICOMMAND 0x00c |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0ed48959b590..e4f00e70a749 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -544,7 +544,7 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) | |||
| 544 | { | 544 | { |
| 545 | struct pxamci_host *host = mmc_priv(devid); | 545 | struct pxamci_host *host = mmc_priv(devid); |
| 546 | 546 | ||
| 547 | mmc_detect_change(devid, host->pdata->detect_delay); | 547 | mmc_detect_change(devid, msecs_to_jiffies(host->pdata->detect_delay_ms)); |
| 548 | return IRQ_HANDLED; | 548 | return IRQ_HANDLED; |
| 549 | } | 549 | } |
| 550 | 550 | ||
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index ed5e9742be2c..a8f0512bad38 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c | |||
| @@ -674,6 +674,7 @@ static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { | |||
| 674 | { ZORRO_PROD_AMERISTAR_A2065 }, | 674 | { ZORRO_PROD_AMERISTAR_A2065 }, |
| 675 | { 0 } | 675 | { 0 } |
| 676 | }; | 676 | }; |
| 677 | MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl); | ||
| 677 | 678 | ||
| 678 | static struct zorro_driver a2065_driver = { | 679 | static struct zorro_driver a2065_driver = { |
| 679 | .name = "a2065", | 680 | .name = "a2065", |
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index fa1a2354f5f9..4b30a46486e2 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c | |||
| @@ -145,6 +145,7 @@ static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { | |||
| 145 | { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, | 145 | { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, |
| 146 | { 0 } | 146 | { 0 } |
| 147 | }; | 147 | }; |
| 148 | MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); | ||
| 148 | 149 | ||
| 149 | static struct zorro_driver ariadne_driver = { | 150 | static struct zorro_driver ariadne_driver = { |
| 150 | .name = "ariadne", | 151 | .name = "ariadne", |
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 24724b4ad709..07d8e5b634f3 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c | |||
| @@ -71,6 +71,7 @@ static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { | |||
| 71 | { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, | 71 | { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, |
| 72 | { 0 } | 72 | { 0 } |
| 73 | }; | 73 | }; |
| 74 | MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl); | ||
| 74 | 75 | ||
| 75 | static struct zorro_driver hydra_driver = { | 76 | static struct zorro_driver hydra_driver = { |
| 76 | .name = "hydra", | 77 | .name = "hydra", |
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 81c753a617ab..9548cbb5012a 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c | |||
| @@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { | |||
| 102 | { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, | 102 | { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, |
| 103 | { 0 } | 103 | { 0 } |
| 104 | }; | 104 | }; |
| 105 | MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl); | ||
| 105 | 106 | ||
| 106 | static struct zorro_driver zorro8390_driver = { | 107 | static struct zorro_driver zorro8390_driver = { |
| 107 | .name = "zorro8390", | 108 | .name = "zorro8390", |
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 166b67ea622f..219f79e2210a 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
| @@ -30,23 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #define OP_BUFFER_FLAGS 0 | 31 | #define OP_BUFFER_FLAGS 0 |
| 32 | 32 | ||
| 33 | /* | 33 | static struct ring_buffer *op_ring_buffer; |
| 34 | * Read and write access is using spin locking. Thus, writing to the | ||
| 35 | * buffer by NMI handler (x86) could occur also during critical | ||
| 36 | * sections when reading the buffer. To avoid this, there are 2 | ||
| 37 | * buffers for independent read and write access. Read access is in | ||
| 38 | * process context only, write access only in the NMI handler. If the | ||
| 39 | * read buffer runs empty, both buffers are swapped atomically. There | ||
| 40 | * is potentially a small window during swapping where the buffers are | ||
| 41 | * disabled and samples could be lost. | ||
| 42 | * | ||
| 43 | * Using 2 buffers is a little bit overhead, but the solution is clear | ||
| 44 | * and does not require changes in the ring buffer implementation. It | ||
| 45 | * can be changed to a single buffer solution when the ring buffer | ||
| 46 | * access is implemented as non-locking atomic code. | ||
| 47 | */ | ||
| 48 | static struct ring_buffer *op_ring_buffer_read; | ||
| 49 | static struct ring_buffer *op_ring_buffer_write; | ||
| 50 | DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); | 34 | DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); |
| 51 | 35 | ||
| 52 | static void wq_sync_buffer(struct work_struct *work); | 36 | static void wq_sync_buffer(struct work_struct *work); |
| @@ -68,12 +52,9 @@ void oprofile_cpu_buffer_inc_smpl_lost(void) | |||
| 68 | 52 | ||
| 69 | void free_cpu_buffers(void) | 53 | void free_cpu_buffers(void) |
| 70 | { | 54 | { |
| 71 | if (op_ring_buffer_read) | 55 | if (op_ring_buffer) |
| 72 | ring_buffer_free(op_ring_buffer_read); | 56 | ring_buffer_free(op_ring_buffer); |
| 73 | op_ring_buffer_read = NULL; | 57 | op_ring_buffer = NULL; |
| 74 | if (op_ring_buffer_write) | ||
| 75 | ring_buffer_free(op_ring_buffer_write); | ||
| 76 | op_ring_buffer_write = NULL; | ||
| 77 | } | 58 | } |
| 78 | 59 | ||
| 79 | #define RB_EVENT_HDR_SIZE 4 | 60 | #define RB_EVENT_HDR_SIZE 4 |
| @@ -86,11 +67,8 @@ int alloc_cpu_buffers(void) | |||
| 86 | unsigned long byte_size = buffer_size * (sizeof(struct op_sample) + | 67 | unsigned long byte_size = buffer_size * (sizeof(struct op_sample) + |
| 87 | RB_EVENT_HDR_SIZE); | 68 | RB_EVENT_HDR_SIZE); |
| 88 | 69 | ||
| 89 | op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); | 70 | op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); |
| 90 | if (!op_ring_buffer_read) | 71 | if (!op_ring_buffer) |
| 91 | goto fail; | ||
| 92 | op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); | ||
| 93 | if (!op_ring_buffer_write) | ||
| 94 | goto fail; | 72 | goto fail; |
| 95 | 73 | ||
| 96 | for_each_possible_cpu(i) { | 74 | for_each_possible_cpu(i) { |
| @@ -162,16 +140,11 @@ struct op_sample | |||
| 162 | *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) | 140 | *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) |
| 163 | { | 141 | { |
| 164 | entry->event = ring_buffer_lock_reserve | 142 | entry->event = ring_buffer_lock_reserve |
| 165 | (op_ring_buffer_write, sizeof(struct op_sample) + | 143 | (op_ring_buffer, sizeof(struct op_sample) + |
| 166 | size * sizeof(entry->sample->data[0])); | 144 | size * sizeof(entry->sample->data[0])); |
| 167 | if (entry->event) | 145 | if (!entry->event) |
| 168 | entry->sample = ring_buffer_event_data(entry->event); | ||
| 169 | else | ||
| 170 | entry->sample = NULL; | ||
| 171 | |||
| 172 | if (!entry->sample) | ||
| 173 | return NULL; | 146 | return NULL; |
| 174 | 147 | entry->sample = ring_buffer_event_data(entry->event); | |
| 175 | entry->size = size; | 148 | entry->size = size; |
| 176 | entry->data = entry->sample->data; | 149 | entry->data = entry->sample->data; |
| 177 | 150 | ||
| @@ -180,25 +153,16 @@ struct op_sample | |||
| 180 | 153 | ||
| 181 | int op_cpu_buffer_write_commit(struct op_entry *entry) | 154 | int op_cpu_buffer_write_commit(struct op_entry *entry) |
| 182 | { | 155 | { |
| 183 | return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event); | 156 | return ring_buffer_unlock_commit(op_ring_buffer, entry->event); |
| 184 | } | 157 | } |
| 185 | 158 | ||
| 186 | struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) | 159 | struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) |
| 187 | { | 160 | { |
| 188 | struct ring_buffer_event *e; | 161 | struct ring_buffer_event *e; |
| 189 | e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); | 162 | e = ring_buffer_consume(op_ring_buffer, cpu, NULL, NULL); |
| 190 | if (e) | 163 | if (!e) |
| 191 | goto event; | ||
| 192 | if (ring_buffer_swap_cpu(op_ring_buffer_read, | ||
| 193 | op_ring_buffer_write, | ||
| 194 | cpu)) | ||
| 195 | return NULL; | 164 | return NULL; |
| 196 | e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); | ||
| 197 | if (e) | ||
| 198 | goto event; | ||
| 199 | return NULL; | ||
| 200 | 165 | ||
| 201 | event: | ||
| 202 | entry->event = e; | 166 | entry->event = e; |
| 203 | entry->sample = ring_buffer_event_data(e); | 167 | entry->sample = ring_buffer_event_data(e); |
| 204 | entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) | 168 | entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) |
| @@ -209,8 +173,7 @@ event: | |||
| 209 | 173 | ||
| 210 | unsigned long op_cpu_buffer_entries(int cpu) | 174 | unsigned long op_cpu_buffer_entries(int cpu) |
| 211 | { | 175 | { |
| 212 | return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) | 176 | return ring_buffer_entries_cpu(op_ring_buffer, cpu); |
| 213 | + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); | ||
| 214 | } | 177 | } |
| 215 | 178 | ||
| 216 | static int | 179 | static int |
| @@ -356,8 +319,16 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, | |||
| 356 | 319 | ||
| 357 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) | 320 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) |
| 358 | { | 321 | { |
| 359 | int is_kernel = !user_mode(regs); | 322 | int is_kernel; |
| 360 | unsigned long pc = profile_pc(regs); | 323 | unsigned long pc; |
| 324 | |||
| 325 | if (likely(regs)) { | ||
| 326 | is_kernel = !user_mode(regs); | ||
| 327 | pc = profile_pc(regs); | ||
| 328 | } else { | ||
| 329 | is_kernel = 0; /* This value will not be used */ | ||
| 330 | pc = ESCAPE_CODE; /* as this causes an early return. */ | ||
| 331 | } | ||
| 361 | 332 | ||
| 362 | __oprofile_add_ext_sample(pc, regs, event, is_kernel); | 333 | __oprofile_add_ext_sample(pc, regs, event, is_kernel); |
| 363 | } | 334 | } |
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dc8a0428260d..b336cd9ee7a1 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c | |||
| @@ -253,22 +253,26 @@ static int __init oprofile_init(void) | |||
| 253 | int err; | 253 | int err; |
| 254 | 254 | ||
| 255 | err = oprofile_arch_init(&oprofile_ops); | 255 | err = oprofile_arch_init(&oprofile_ops); |
| 256 | |||
| 257 | if (err < 0 || timer) { | 256 | if (err < 0 || timer) { |
| 258 | printk(KERN_INFO "oprofile: using timer interrupt.\n"); | 257 | printk(KERN_INFO "oprofile: using timer interrupt.\n"); |
| 259 | oprofile_timer_init(&oprofile_ops); | 258 | err = oprofile_timer_init(&oprofile_ops); |
| 259 | if (err) | ||
| 260 | goto out_arch; | ||
| 260 | } | 261 | } |
| 261 | |||
| 262 | err = oprofilefs_register(); | 262 | err = oprofilefs_register(); |
| 263 | if (err) | 263 | if (err) |
| 264 | oprofile_arch_exit(); | 264 | goto out_arch; |
| 265 | return 0; | ||
| 265 | 266 | ||
| 267 | out_arch: | ||
| 268 | oprofile_arch_exit(); | ||
| 266 | return err; | 269 | return err; |
| 267 | } | 270 | } |
| 268 | 271 | ||
| 269 | 272 | ||
| 270 | static void __exit oprofile_exit(void) | 273 | static void __exit oprofile_exit(void) |
| 271 | { | 274 | { |
| 275 | oprofile_timer_exit(); | ||
| 272 | oprofilefs_unregister(); | 276 | oprofilefs_unregister(); |
| 273 | oprofile_arch_exit(); | 277 | oprofile_arch_exit(); |
| 274 | } | 278 | } |
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index cb92f5c98c1a..47e12cb4ee8b 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h | |||
| @@ -34,7 +34,8 @@ struct super_block; | |||
| 34 | struct dentry; | 34 | struct dentry; |
| 35 | 35 | ||
| 36 | void oprofile_create_files(struct super_block *sb, struct dentry *root); | 36 | void oprofile_create_files(struct super_block *sb, struct dentry *root); |
| 37 | void oprofile_timer_init(struct oprofile_operations *ops); | 37 | int oprofile_timer_init(struct oprofile_operations *ops); |
| 38 | void oprofile_timer_exit(void); | ||
| 38 | 39 | ||
| 39 | int oprofile_set_backtrace(unsigned long depth); | 40 | int oprofile_set_backtrace(unsigned long depth); |
| 40 | int oprofile_set_timeout(unsigned long time); | 41 | int oprofile_set_timeout(unsigned long time); |
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 333f915568c7..dc0ae4d14dff 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c | |||
| @@ -13,34 +13,94 @@ | |||
| 13 | #include <linux/oprofile.h> | 13 | #include <linux/oprofile.h> |
| 14 | #include <linux/profile.h> | 14 | #include <linux/profile.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/cpu.h> | ||
| 17 | #include <linux/hrtimer.h> | ||
| 18 | #include <asm/irq_regs.h> | ||
| 16 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
| 17 | 20 | ||
| 18 | #include "oprof.h" | 21 | #include "oprof.h" |
| 19 | 22 | ||
| 20 | static int timer_notify(struct pt_regs *regs) | 23 | static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); |
| 24 | |||
| 25 | static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer) | ||
| 26 | { | ||
| 27 | oprofile_add_sample(get_irq_regs(), 0); | ||
| 28 | hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC)); | ||
| 29 | return HRTIMER_RESTART; | ||
| 30 | } | ||
| 31 | |||
| 32 | static void __oprofile_hrtimer_start(void *unused) | ||
| 33 | { | ||
| 34 | struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer); | ||
| 35 | |||
| 36 | hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
| 37 | hrtimer->function = oprofile_hrtimer_notify; | ||
| 38 | |||
| 39 | hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC), | ||
| 40 | HRTIMER_MODE_REL_PINNED); | ||
| 41 | } | ||
| 42 | |||
| 43 | static int oprofile_hrtimer_start(void) | ||
| 21 | { | 44 | { |
| 22 | oprofile_add_sample(regs, 0); | 45 | on_each_cpu(__oprofile_hrtimer_start, NULL, 1); |
| 23 | return 0; | 46 | return 0; |
| 24 | } | 47 | } |
| 25 | 48 | ||
| 26 | static int timer_start(void) | 49 | static void __oprofile_hrtimer_stop(int cpu) |
| 27 | { | 50 | { |
| 28 | return register_timer_hook(timer_notify); | 51 | struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); |
| 52 | |||
| 53 | hrtimer_cancel(hrtimer); | ||
| 29 | } | 54 | } |
| 30 | 55 | ||
| 56 | static void oprofile_hrtimer_stop(void) | ||
| 57 | { | ||
| 58 | int cpu; | ||
| 59 | |||
| 60 | for_each_online_cpu(cpu) | ||
| 61 | __oprofile_hrtimer_stop(cpu); | ||
| 62 | } | ||
| 31 | 63 | ||
| 32 | static void timer_stop(void) | 64 | static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, |
| 65 | unsigned long action, void *hcpu) | ||
| 33 | { | 66 | { |
| 34 | unregister_timer_hook(timer_notify); | 67 | long cpu = (long) hcpu; |
| 68 | |||
| 69 | switch (action) { | ||
| 70 | case CPU_ONLINE: | ||
| 71 | case CPU_ONLINE_FROZEN: | ||
| 72 | smp_call_function_single(cpu, __oprofile_hrtimer_start, | ||
| 73 | NULL, 1); | ||
| 74 | break; | ||
| 75 | case CPU_DEAD: | ||
| 76 | case CPU_DEAD_FROZEN: | ||
| 77 | __oprofile_hrtimer_stop(cpu); | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | return NOTIFY_OK; | ||
| 35 | } | 81 | } |
| 36 | 82 | ||
| 83 | static struct notifier_block __refdata oprofile_cpu_notifier = { | ||
| 84 | .notifier_call = oprofile_cpu_notify, | ||
| 85 | }; | ||
| 37 | 86 | ||
| 38 | void __init oprofile_timer_init(struct oprofile_operations *ops) | 87 | int __init oprofile_timer_init(struct oprofile_operations *ops) |
| 39 | { | 88 | { |
| 89 | int rc; | ||
| 90 | |||
| 91 | rc = register_hotcpu_notifier(&oprofile_cpu_notifier); | ||
| 92 | if (rc) | ||
| 93 | return rc; | ||
| 40 | ops->create_files = NULL; | 94 | ops->create_files = NULL; |
| 41 | ops->setup = NULL; | 95 | ops->setup = NULL; |
| 42 | ops->shutdown = NULL; | 96 | ops->shutdown = NULL; |
| 43 | ops->start = timer_start; | 97 | ops->start = oprofile_hrtimer_start; |
| 44 | ops->stop = timer_stop; | 98 | ops->stop = oprofile_hrtimer_stop; |
| 45 | ops->cpu_type = "timer"; | 99 | ops->cpu_type = "timer"; |
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | void __exit oprofile_timer_exit(void) | ||
| 104 | { | ||
| 105 | unregister_hotcpu_notifier(&oprofile_cpu_notifier); | ||
| 46 | } | 106 | } |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 417312528ddf..371dc564e2e4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -3626,14 +3626,15 @@ static void intel_iommu_detach_device(struct iommu_domain *domain, | |||
| 3626 | domain_remove_one_dev_info(dmar_domain, pdev); | 3626 | domain_remove_one_dev_info(dmar_domain, pdev); |
| 3627 | } | 3627 | } |
| 3628 | 3628 | ||
| 3629 | static int intel_iommu_map_range(struct iommu_domain *domain, | 3629 | static int intel_iommu_map(struct iommu_domain *domain, |
| 3630 | unsigned long iova, phys_addr_t hpa, | 3630 | unsigned long iova, phys_addr_t hpa, |
| 3631 | size_t size, int iommu_prot) | 3631 | int gfp_order, int iommu_prot) |
| 3632 | { | 3632 | { |
| 3633 | struct dmar_domain *dmar_domain = domain->priv; | 3633 | struct dmar_domain *dmar_domain = domain->priv; |
| 3634 | u64 max_addr; | 3634 | u64 max_addr; |
| 3635 | int addr_width; | 3635 | int addr_width; |
| 3636 | int prot = 0; | 3636 | int prot = 0; |
| 3637 | size_t size; | ||
| 3637 | int ret; | 3638 | int ret; |
| 3638 | 3639 | ||
| 3639 | if (iommu_prot & IOMMU_READ) | 3640 | if (iommu_prot & IOMMU_READ) |
| @@ -3643,6 +3644,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3643 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3644 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
| 3644 | prot |= DMA_PTE_SNP; | 3645 | prot |= DMA_PTE_SNP; |
| 3645 | 3646 | ||
| 3647 | size = PAGE_SIZE << gfp_order; | ||
| 3646 | max_addr = iova + size; | 3648 | max_addr = iova + size; |
| 3647 | if (dmar_domain->max_addr < max_addr) { | 3649 | if (dmar_domain->max_addr < max_addr) { |
| 3648 | int min_agaw; | 3650 | int min_agaw; |
| @@ -3669,19 +3671,19 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3669 | return ret; | 3671 | return ret; |
| 3670 | } | 3672 | } |
| 3671 | 3673 | ||
| 3672 | static void intel_iommu_unmap_range(struct iommu_domain *domain, | 3674 | static int intel_iommu_unmap(struct iommu_domain *domain, |
| 3673 | unsigned long iova, size_t size) | 3675 | unsigned long iova, int gfp_order) |
| 3674 | { | 3676 | { |
| 3675 | struct dmar_domain *dmar_domain = domain->priv; | 3677 | struct dmar_domain *dmar_domain = domain->priv; |
| 3676 | 3678 | size_t size = PAGE_SIZE << gfp_order; | |
| 3677 | if (!size) | ||
| 3678 | return; | ||
| 3679 | 3679 | ||
| 3680 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, | 3680 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
| 3681 | (iova + size - 1) >> VTD_PAGE_SHIFT); | 3681 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
| 3682 | 3682 | ||
| 3683 | if (dmar_domain->max_addr == iova + size) | 3683 | if (dmar_domain->max_addr == iova + size) |
| 3684 | dmar_domain->max_addr = iova; | 3684 | dmar_domain->max_addr = iova; |
| 3685 | |||
| 3686 | return gfp_order; | ||
| 3685 | } | 3687 | } |
| 3686 | 3688 | ||
| 3687 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3689 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
| @@ -3714,8 +3716,8 @@ static struct iommu_ops intel_iommu_ops = { | |||
| 3714 | .domain_destroy = intel_iommu_domain_destroy, | 3716 | .domain_destroy = intel_iommu_domain_destroy, |
| 3715 | .attach_dev = intel_iommu_attach_device, | 3717 | .attach_dev = intel_iommu_attach_device, |
| 3716 | .detach_dev = intel_iommu_detach_device, | 3718 | .detach_dev = intel_iommu_detach_device, |
| 3717 | .map = intel_iommu_map_range, | 3719 | .map = intel_iommu_map, |
| 3718 | .unmap = intel_iommu_unmap_range, | 3720 | .unmap = intel_iommu_unmap, |
| 3719 | .iova_to_phys = intel_iommu_iova_to_phys, | 3721 | .iova_to_phys = intel_iommu_iova_to_phys, |
| 3720 | .domain_has_cap = intel_iommu_domain_has_cap, | 3722 | .domain_has_cap = intel_iommu_domain_has_cap, |
| 3721 | }; | 3723 | }; |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d189e4743e69..a44733d44ca1 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
| @@ -234,7 +234,8 @@ config PCMCIA_PXA2XX | |||
| 234 | depends on ARM && ARCH_PXA && PCMCIA | 234 | depends on ARM && ARCH_PXA && PCMCIA |
| 235 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ | 235 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ |
| 236 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ | 236 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ |
| 237 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2) | 237 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ |
| 238 | || MACH_VPAC270) | ||
| 238 | select PCMCIA_SOC_COMMON | 239 | select PCMCIA_SOC_COMMON |
| 239 | help | 240 | help |
| 240 | Say Y here to include support for the PXA2xx PCMCIA controller | 241 | Say Y here to include support for the PXA2xx PCMCIA controller |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 381b031d9d75..4dae3613c458 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
| @@ -66,6 +66,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o | |||
| 66 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o | 66 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o |
| 67 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o | 67 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o |
| 68 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o | 68 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o |
| 69 | pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o | ||
| 69 | 70 | ||
| 70 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) | 71 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) |
| 71 | 72 | ||
diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c new file mode 100644 index 000000000000..55627eccee8e --- /dev/null +++ b/drivers/pcmcia/pxa2xx_vpac270.c | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/pcmcia/pxa2xx_vpac270.c | ||
| 3 | * | ||
| 4 | * Driver for Voipac PXA270 PCMCIA and CF sockets | ||
| 5 | * | ||
| 6 | * Copyright (C) 2010 | ||
| 7 | * Marek Vasut <marek.vasut@gmail.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | |||
| 18 | #include <asm/mach-types.h> | ||
| 19 | |||
| 20 | #include <mach/gpio.h> | ||
| 21 | #include <mach/vpac270.h> | ||
| 22 | |||
| 23 | #include "soc_common.h" | ||
| 24 | |||
| 25 | static struct pcmcia_irqs cd_irqs[] = { | ||
| 26 | { | ||
| 27 | .sock = 0, | ||
| 28 | .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD), | ||
| 29 | .str = "PCMCIA CD" | ||
| 30 | }, | ||
| 31 | { | ||
| 32 | .sock = 1, | ||
| 33 | .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD), | ||
| 34 | .str = "CF CD" | ||
| 35 | }, | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
| 39 | { | ||
| 40 | int ret; | ||
| 41 | |||
| 42 | if (skt->nr == 0) { | ||
| 43 | ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD"); | ||
| 44 | if (ret) | ||
| 45 | goto err1; | ||
| 46 | ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD); | ||
| 47 | if (ret) | ||
| 48 | goto err2; | ||
| 49 | |||
| 50 | ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY"); | ||
| 51 | if (ret) | ||
| 52 | goto err2; | ||
| 53 | ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 54 | if (ret) | ||
| 55 | goto err3; | ||
| 56 | |||
| 57 | ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN"); | ||
| 58 | if (ret) | ||
| 59 | goto err3; | ||
| 60 | ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0); | ||
| 61 | if (ret) | ||
| 62 | goto err4; | ||
| 63 | |||
| 64 | ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET"); | ||
| 65 | if (ret) | ||
| 66 | goto err4; | ||
| 67 | ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0); | ||
| 68 | if (ret) | ||
| 69 | goto err5; | ||
| 70 | |||
| 71 | skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 72 | |||
| 73 | return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); | ||
| 74 | |||
| 75 | err5: | ||
| 76 | gpio_free(GPIO11_VPAC270_PCMCIA_RESET); | ||
| 77 | err4: | ||
| 78 | gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); | ||
| 79 | err3: | ||
| 80 | gpio_free(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 81 | err2: | ||
| 82 | gpio_free(GPIO84_VPAC270_PCMCIA_CD); | ||
| 83 | err1: | ||
| 84 | return ret; | ||
| 85 | |||
| 86 | } else { | ||
| 87 | ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD"); | ||
| 88 | if (ret) | ||
| 89 | goto err6; | ||
| 90 | ret = gpio_direction_input(GPIO17_VPAC270_CF_CD); | ||
| 91 | if (ret) | ||
| 92 | goto err7; | ||
| 93 | |||
| 94 | ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY"); | ||
| 95 | if (ret) | ||
| 96 | goto err7; | ||
| 97 | ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY); | ||
| 98 | if (ret) | ||
| 99 | goto err8; | ||
| 100 | |||
| 101 | ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET"); | ||
| 102 | if (ret) | ||
| 103 | goto err8; | ||
| 104 | ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0); | ||
| 105 | if (ret) | ||
| 106 | goto err9; | ||
| 107 | |||
| 108 | skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); | ||
| 109 | |||
| 110 | return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); | ||
| 111 | |||
| 112 | err9: | ||
| 113 | gpio_free(GPIO16_VPAC270_CF_RESET); | ||
| 114 | err8: | ||
| 115 | gpio_free(GPIO12_VPAC270_CF_RDY); | ||
| 116 | err7: | ||
| 117 | gpio_free(GPIO17_VPAC270_CF_CD); | ||
| 118 | err6: | ||
| 119 | return ret; | ||
| 120 | |||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | ||
| 125 | { | ||
| 126 | gpio_free(GPIO11_VPAC270_PCMCIA_RESET); | ||
| 127 | gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); | ||
| 128 | gpio_free(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 129 | gpio_free(GPIO84_VPAC270_PCMCIA_CD); | ||
| 130 | gpio_free(GPIO16_VPAC270_CF_RESET); | ||
| 131 | gpio_free(GPIO12_VPAC270_CF_RDY); | ||
| 132 | gpio_free(GPIO17_VPAC270_CF_CD); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | ||
| 136 | struct pcmcia_state *state) | ||
| 137 | { | ||
| 138 | if (skt->nr == 0) { | ||
| 139 | state->detect = !gpio_get_value(GPIO84_VPAC270_PCMCIA_CD); | ||
| 140 | state->ready = !!gpio_get_value(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 141 | } else { | ||
| 142 | state->detect = !gpio_get_value(GPIO17_VPAC270_CF_CD); | ||
| 143 | state->ready = !!gpio_get_value(GPIO12_VPAC270_CF_RDY); | ||
| 144 | } | ||
| 145 | state->bvd1 = 1; | ||
| 146 | state->bvd2 = 1; | ||
| 147 | state->wrprot = 0; | ||
| 148 | state->vs_3v = 1; | ||
| 149 | state->vs_Xv = 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int | ||
| 153 | vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
| 154 | const socket_state_t *state) | ||
| 155 | { | ||
| 156 | if (skt->nr == 0) { | ||
| 157 | gpio_set_value(GPIO11_VPAC270_PCMCIA_RESET, | ||
| 158 | (state->flags & SS_RESET)); | ||
| 159 | gpio_set_value(GPIO107_VPAC270_PCMCIA_PPEN, | ||
| 160 | !(state->Vcc == 33 || state->Vcc == 50)); | ||
| 161 | } else { | ||
| 162 | gpio_set_value(GPIO16_VPAC270_CF_RESET, | ||
| 163 | (state->flags & SS_RESET)); | ||
| 164 | } | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static void vpac270_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | ||
| 170 | { | ||
| 171 | } | ||
| 172 | |||
| 173 | static void vpac270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | ||
| 174 | { | ||
| 175 | } | ||
| 176 | |||
| 177 | static struct pcmcia_low_level vpac270_pcmcia_ops = { | ||
| 178 | .owner = THIS_MODULE, | ||
| 179 | |||
| 180 | .first = 0, | ||
| 181 | .nr = 2, | ||
| 182 | |||
| 183 | .hw_init = vpac270_pcmcia_hw_init, | ||
| 184 | .hw_shutdown = vpac270_pcmcia_hw_shutdown, | ||
| 185 | |||
| 186 | .socket_state = vpac270_pcmcia_socket_state, | ||
| 187 | .configure_socket = vpac270_pcmcia_configure_socket, | ||
| 188 | |||
| 189 | .socket_init = vpac270_pcmcia_socket_init, | ||
| 190 | .socket_suspend = vpac270_pcmcia_socket_suspend, | ||
| 191 | }; | ||
| 192 | |||
| 193 | static struct platform_device *vpac270_pcmcia_device; | ||
| 194 | |||
| 195 | static int __init vpac270_pcmcia_init(void) | ||
| 196 | { | ||
| 197 | int ret; | ||
| 198 | |||
| 199 | if (!machine_is_vpac270()) | ||
| 200 | return -ENODEV; | ||
| 201 | |||
| 202 | vpac270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | ||
| 203 | if (!vpac270_pcmcia_device) | ||
| 204 | return -ENOMEM; | ||
| 205 | |||
| 206 | ret = platform_device_add_data(vpac270_pcmcia_device, | ||
| 207 | &vpac270_pcmcia_ops, sizeof(vpac270_pcmcia_ops)); | ||
| 208 | |||
| 209 | if (!ret) | ||
| 210 | ret = platform_device_add(vpac270_pcmcia_device); | ||
| 211 | |||
| 212 | if (ret) | ||
| 213 | platform_device_put(vpac270_pcmcia_device); | ||
| 214 | |||
| 215 | return ret; | ||
| 216 | } | ||
| 217 | |||
| 218 | static void __exit vpac270_pcmcia_exit(void) | ||
| 219 | { | ||
| 220 | platform_device_unregister(vpac270_pcmcia_device); | ||
| 221 | } | ||
| 222 | |||
| 223 | module_init(vpac270_pcmcia_init); | ||
| 224 | module_exit(vpac270_pcmcia_exit); | ||
| 225 | |||
| 226 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
| 227 | MODULE_DESCRIPTION("PCMCIA support for Voipac PXA270"); | ||
| 228 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
| 229 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index fa2339cb1681..0e86247d791e 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -65,6 +65,7 @@ static void dasd_device_tasklet(struct dasd_device *); | |||
| 65 | static void dasd_block_tasklet(struct dasd_block *); | 65 | static void dasd_block_tasklet(struct dasd_block *); |
| 66 | static void do_kick_device(struct work_struct *); | 66 | static void do_kick_device(struct work_struct *); |
| 67 | static void do_restore_device(struct work_struct *); | 67 | static void do_restore_device(struct work_struct *); |
| 68 | static void do_reload_device(struct work_struct *); | ||
| 68 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); | 69 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); |
| 69 | static void dasd_device_timeout(unsigned long); | 70 | static void dasd_device_timeout(unsigned long); |
| 70 | static void dasd_block_timeout(unsigned long); | 71 | static void dasd_block_timeout(unsigned long); |
| @@ -115,6 +116,7 @@ struct dasd_device *dasd_alloc_device(void) | |||
| 115 | device->timer.data = (unsigned long) device; | 116 | device->timer.data = (unsigned long) device; |
| 116 | INIT_WORK(&device->kick_work, do_kick_device); | 117 | INIT_WORK(&device->kick_work, do_kick_device); |
| 117 | INIT_WORK(&device->restore_device, do_restore_device); | 118 | INIT_WORK(&device->restore_device, do_restore_device); |
| 119 | INIT_WORK(&device->reload_device, do_reload_device); | ||
| 118 | device->state = DASD_STATE_NEW; | 120 | device->state = DASD_STATE_NEW; |
| 119 | device->target = DASD_STATE_NEW; | 121 | device->target = DASD_STATE_NEW; |
| 120 | mutex_init(&device->state_mutex); | 122 | mutex_init(&device->state_mutex); |
| @@ -521,6 +523,26 @@ void dasd_kick_device(struct dasd_device *device) | |||
| 521 | } | 523 | } |
| 522 | 524 | ||
| 523 | /* | 525 | /* |
| 526 | * dasd_reload_device will schedule a call do do_reload_device to the kernel | ||
| 527 | * event daemon. | ||
| 528 | */ | ||
| 529 | static void do_reload_device(struct work_struct *work) | ||
| 530 | { | ||
| 531 | struct dasd_device *device = container_of(work, struct dasd_device, | ||
| 532 | reload_device); | ||
| 533 | device->discipline->reload(device); | ||
| 534 | dasd_put_device(device); | ||
| 535 | } | ||
| 536 | |||
| 537 | void dasd_reload_device(struct dasd_device *device) | ||
| 538 | { | ||
| 539 | dasd_get_device(device); | ||
| 540 | /* queue call to dasd_reload_device to the kernel event daemon. */ | ||
| 541 | schedule_work(&device->reload_device); | ||
| 542 | } | ||
| 543 | EXPORT_SYMBOL(dasd_reload_device); | ||
| 544 | |||
| 545 | /* | ||
| 524 | * dasd_restore_device will schedule a call do do_restore_device to the kernel | 546 | * dasd_restore_device will schedule a call do do_restore_device to the kernel |
| 525 | * event daemon. | 547 | * event daemon. |
| 526 | */ | 548 | */ |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 6632649dd6aa..85bfd8794856 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
| @@ -1418,9 +1418,29 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( | |||
| 1418 | struct dasd_ccw_req *erp) | 1418 | struct dasd_ccw_req *erp) |
| 1419 | { | 1419 | { |
| 1420 | struct dasd_ccw_req *cqr = erp->refers; | 1420 | struct dasd_ccw_req *cqr = erp->refers; |
| 1421 | char *sense; | ||
| 1421 | 1422 | ||
| 1422 | if (cqr->block && | 1423 | if (cqr->block && |
| 1423 | (cqr->block->base != cqr->startdev)) { | 1424 | (cqr->block->base != cqr->startdev)) { |
| 1425 | |||
| 1426 | sense = dasd_get_sense(&erp->refers->irb); | ||
| 1427 | /* | ||
| 1428 | * dynamic pav may have changed base alias mapping | ||
| 1429 | */ | ||
| 1430 | if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense | ||
| 1431 | && (sense[0] == 0x10) && (sense[7] == 0x0F) | ||
| 1432 | && (sense[8] == 0x67)) { | ||
| 1433 | /* | ||
| 1434 | * remove device from alias handling to prevent new | ||
| 1435 | * requests from being scheduled on the | ||
| 1436 | * wrong alias device | ||
| 1437 | */ | ||
| 1438 | dasd_alias_remove_device(cqr->startdev); | ||
| 1439 | |||
| 1440 | /* schedule worker to reload device */ | ||
| 1441 | dasd_reload_device(cqr->startdev); | ||
| 1442 | } | ||
| 1443 | |||
| 1424 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { | 1444 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { |
| 1425 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, | 1445 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, |
| 1426 | "ERP on alias device for request %p," | 1446 | "ERP on alias device for request %p," |
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 8c4814258e93..4155805dcdff 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
| @@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 190 | struct alias_server *server, *newserver; | 190 | struct alias_server *server, *newserver; |
| 191 | struct alias_lcu *lcu, *newlcu; | 191 | struct alias_lcu *lcu, *newlcu; |
| 192 | int is_lcu_known; | 192 | int is_lcu_known; |
| 193 | struct dasd_uid *uid; | 193 | struct dasd_uid uid; |
| 194 | 194 | ||
| 195 | private = (struct dasd_eckd_private *) device->private; | 195 | private = (struct dasd_eckd_private *) device->private; |
| 196 | uid = &private->uid; | 196 | |
| 197 | device->discipline->get_uid(device, &uid); | ||
| 197 | spin_lock_irqsave(&aliastree.lock, flags); | 198 | spin_lock_irqsave(&aliastree.lock, flags); |
| 198 | is_lcu_known = 1; | 199 | is_lcu_known = 1; |
| 199 | server = _find_server(uid); | 200 | server = _find_server(&uid); |
| 200 | if (!server) { | 201 | if (!server) { |
| 201 | spin_unlock_irqrestore(&aliastree.lock, flags); | 202 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 202 | newserver = _allocate_server(uid); | 203 | newserver = _allocate_server(&uid); |
| 203 | if (IS_ERR(newserver)) | 204 | if (IS_ERR(newserver)) |
| 204 | return PTR_ERR(newserver); | 205 | return PTR_ERR(newserver); |
| 205 | spin_lock_irqsave(&aliastree.lock, flags); | 206 | spin_lock_irqsave(&aliastree.lock, flags); |
| 206 | server = _find_server(uid); | 207 | server = _find_server(&uid); |
| 207 | if (!server) { | 208 | if (!server) { |
| 208 | list_add(&newserver->server, &aliastree.serverlist); | 209 | list_add(&newserver->server, &aliastree.serverlist); |
| 209 | server = newserver; | 210 | server = newserver; |
| @@ -214,14 +215,14 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 214 | } | 215 | } |
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | lcu = _find_lcu(server, uid); | 218 | lcu = _find_lcu(server, &uid); |
| 218 | if (!lcu) { | 219 | if (!lcu) { |
| 219 | spin_unlock_irqrestore(&aliastree.lock, flags); | 220 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 220 | newlcu = _allocate_lcu(uid); | 221 | newlcu = _allocate_lcu(&uid); |
| 221 | if (IS_ERR(newlcu)) | 222 | if (IS_ERR(newlcu)) |
| 222 | return PTR_ERR(newlcu); | 223 | return PTR_ERR(newlcu); |
| 223 | spin_lock_irqsave(&aliastree.lock, flags); | 224 | spin_lock_irqsave(&aliastree.lock, flags); |
| 224 | lcu = _find_lcu(server, uid); | 225 | lcu = _find_lcu(server, &uid); |
| 225 | if (!lcu) { | 226 | if (!lcu) { |
| 226 | list_add(&newlcu->lcu, &server->lculist); | 227 | list_add(&newlcu->lcu, &server->lculist); |
| 227 | lcu = newlcu; | 228 | lcu = newlcu; |
| @@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device) | |||
| 256 | unsigned long flags; | 257 | unsigned long flags; |
| 257 | struct alias_server *server; | 258 | struct alias_server *server; |
| 258 | struct alias_lcu *lcu; | 259 | struct alias_lcu *lcu; |
| 259 | struct dasd_uid *uid; | 260 | struct dasd_uid uid; |
| 260 | 261 | ||
| 261 | private = (struct dasd_eckd_private *) device->private; | 262 | private = (struct dasd_eckd_private *) device->private; |
| 262 | uid = &private->uid; | 263 | device->discipline->get_uid(device, &uid); |
| 263 | lcu = NULL; | 264 | lcu = NULL; |
| 264 | spin_lock_irqsave(&aliastree.lock, flags); | 265 | spin_lock_irqsave(&aliastree.lock, flags); |
| 265 | server = _find_server(uid); | 266 | server = _find_server(&uid); |
| 266 | if (server) | 267 | if (server) |
| 267 | lcu = _find_lcu(server, uid); | 268 | lcu = _find_lcu(server, &uid); |
| 268 | spin_unlock_irqrestore(&aliastree.lock, flags); | 269 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 269 | if (!lcu) { | 270 | if (!lcu) { |
| 270 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | 271 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, |
| 271 | "could not find lcu for %04x %02x", | 272 | "could not find lcu for %04x %02x", |
| 272 | uid->ssid, uid->real_unit_addr); | 273 | uid.ssid, uid.real_unit_addr); |
| 273 | WARN_ON(1); | 274 | WARN_ON(1); |
| 274 | return; | 275 | return; |
| 275 | } | 276 | } |
| @@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) | |||
| 282 | unsigned long flags; | 283 | unsigned long flags; |
| 283 | struct alias_server *server; | 284 | struct alias_server *server; |
| 284 | struct alias_lcu *lcu; | 285 | struct alias_lcu *lcu; |
| 285 | struct dasd_uid *uid; | 286 | struct dasd_uid uid; |
| 286 | 287 | ||
| 287 | private = (struct dasd_eckd_private *) device->private; | 288 | private = (struct dasd_eckd_private *) device->private; |
| 288 | uid = &private->uid; | 289 | device->discipline->get_uid(device, &uid); |
| 289 | lcu = NULL; | 290 | lcu = NULL; |
| 290 | spin_lock_irqsave(&aliastree.lock, flags); | 291 | spin_lock_irqsave(&aliastree.lock, flags); |
| 291 | server = _find_server(uid); | 292 | server = _find_server(&uid); |
| 292 | if (server) | 293 | if (server) |
| 293 | lcu = _find_lcu(server, uid); | 294 | lcu = _find_lcu(server, &uid); |
| 294 | spin_unlock_irqrestore(&aliastree.lock, flags); | 295 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 295 | if (!lcu) { | 296 | if (!lcu) { |
| 296 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | 297 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, |
| 297 | "could not find lcu for %04x %02x", | 298 | "could not find lcu for %04x %02x", |
| 298 | uid->ssid, uid->real_unit_addr); | 299 | uid.ssid, uid.real_unit_addr); |
| 299 | WARN_ON(1); | 300 | WARN_ON(1); |
| 300 | return; | 301 | return; |
| 301 | } | 302 | } |
| @@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 314 | struct alias_lcu *lcu; | 315 | struct alias_lcu *lcu; |
| 315 | struct alias_server *server; | 316 | struct alias_server *server; |
| 316 | int was_pending; | 317 | int was_pending; |
| 318 | struct dasd_uid uid; | ||
| 317 | 319 | ||
| 318 | private = (struct dasd_eckd_private *) device->private; | 320 | private = (struct dasd_eckd_private *) device->private; |
| 319 | lcu = private->lcu; | 321 | lcu = private->lcu; |
| 322 | device->discipline->get_uid(device, &uid); | ||
| 320 | spin_lock_irqsave(&lcu->lock, flags); | 323 | spin_lock_irqsave(&lcu->lock, flags); |
| 321 | list_del_init(&device->alias_list); | 324 | list_del_init(&device->alias_list); |
| 322 | /* make sure that the workers don't use this device */ | 325 | /* make sure that the workers don't use this device */ |
| @@ -353,7 +356,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 353 | _schedule_lcu_update(lcu, NULL); | 356 | _schedule_lcu_update(lcu, NULL); |
| 354 | spin_unlock(&lcu->lock); | 357 | spin_unlock(&lcu->lock); |
| 355 | } | 358 | } |
| 356 | server = _find_server(&private->uid); | 359 | server = _find_server(&uid); |
| 357 | if (server && list_empty(&server->lculist)) { | 360 | if (server && list_empty(&server->lculist)) { |
| 358 | list_del(&server->server); | 361 | list_del(&server->server); |
| 359 | _free_server(server); | 362 | _free_server(server); |
| @@ -366,19 +369,30 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 366 | * in the lcu is up to date and will update the device uid before | 369 | * in the lcu is up to date and will update the device uid before |
| 367 | * adding it to a pav group. | 370 | * adding it to a pav group. |
| 368 | */ | 371 | */ |
| 372 | |||
| 369 | static int _add_device_to_lcu(struct alias_lcu *lcu, | 373 | static int _add_device_to_lcu(struct alias_lcu *lcu, |
| 370 | struct dasd_device *device) | 374 | struct dasd_device *device, |
| 375 | struct dasd_device *pos) | ||
| 371 | { | 376 | { |
| 372 | 377 | ||
| 373 | struct dasd_eckd_private *private; | 378 | struct dasd_eckd_private *private; |
| 374 | struct alias_pav_group *group; | 379 | struct alias_pav_group *group; |
| 375 | struct dasd_uid *uid; | 380 | struct dasd_uid uid; |
| 381 | unsigned long flags; | ||
| 376 | 382 | ||
| 377 | private = (struct dasd_eckd_private *) device->private; | 383 | private = (struct dasd_eckd_private *) device->private; |
| 378 | uid = &private->uid; | 384 | |
| 379 | uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type; | 385 | /* only lock if not already locked */ |
| 380 | uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua; | 386 | if (device != pos) |
| 381 | dasd_set_uid(device->cdev, &private->uid); | 387 | spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags, |
| 388 | CDEV_NESTED_SECOND); | ||
| 389 | private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; | ||
| 390 | private->uid.base_unit_addr = | ||
| 391 | lcu->uac->unit[private->uid.real_unit_addr].base_ua; | ||
| 392 | uid = private->uid; | ||
| 393 | |||
| 394 | if (device != pos) | ||
| 395 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 382 | 396 | ||
| 383 | /* if we have no PAV anyway, we don't need to bother with PAV groups */ | 397 | /* if we have no PAV anyway, we don't need to bother with PAV groups */ |
| 384 | if (lcu->pav == NO_PAV) { | 398 | if (lcu->pav == NO_PAV) { |
| @@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu, | |||
| 386 | return 0; | 400 | return 0; |
| 387 | } | 401 | } |
| 388 | 402 | ||
| 389 | group = _find_group(lcu, uid); | 403 | group = _find_group(lcu, &uid); |
| 390 | if (!group) { | 404 | if (!group) { |
| 391 | group = kzalloc(sizeof(*group), GFP_ATOMIC); | 405 | group = kzalloc(sizeof(*group), GFP_ATOMIC); |
| 392 | if (!group) | 406 | if (!group) |
| 393 | return -ENOMEM; | 407 | return -ENOMEM; |
| 394 | memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor)); | 408 | memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor)); |
| 395 | memcpy(group->uid.serial, uid->serial, sizeof(uid->serial)); | 409 | memcpy(group->uid.serial, uid.serial, sizeof(uid.serial)); |
| 396 | group->uid.ssid = uid->ssid; | 410 | group->uid.ssid = uid.ssid; |
| 397 | if (uid->type == UA_BASE_DEVICE) | 411 | if (uid.type == UA_BASE_DEVICE) |
| 398 | group->uid.base_unit_addr = uid->real_unit_addr; | 412 | group->uid.base_unit_addr = uid.real_unit_addr; |
| 399 | else | 413 | else |
| 400 | group->uid.base_unit_addr = uid->base_unit_addr; | 414 | group->uid.base_unit_addr = uid.base_unit_addr; |
| 401 | memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit)); | 415 | memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit)); |
| 402 | INIT_LIST_HEAD(&group->group); | 416 | INIT_LIST_HEAD(&group->group); |
| 403 | INIT_LIST_HEAD(&group->baselist); | 417 | INIT_LIST_HEAD(&group->baselist); |
| 404 | INIT_LIST_HEAD(&group->aliaslist); | 418 | INIT_LIST_HEAD(&group->aliaslist); |
| 405 | list_add(&group->group, &lcu->grouplist); | 419 | list_add(&group->group, &lcu->grouplist); |
| 406 | } | 420 | } |
| 407 | if (uid->type == UA_BASE_DEVICE) | 421 | if (uid.type == UA_BASE_DEVICE) |
| 408 | list_move(&device->alias_list, &group->baselist); | 422 | list_move(&device->alias_list, &group->baselist); |
| 409 | else | 423 | else |
| 410 | list_move(&device->alias_list, &group->aliaslist); | 424 | list_move(&device->alias_list, &group->aliaslist); |
| @@ -525,7 +539,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) | |||
| 525 | if (rc) | 539 | if (rc) |
| 526 | return rc; | 540 | return rc; |
| 527 | 541 | ||
| 528 | spin_lock_irqsave(&lcu->lock, flags); | 542 | /* need to take cdev lock before lcu lock */ |
| 543 | spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags, | ||
| 544 | CDEV_NESTED_FIRST); | ||
| 545 | spin_lock(&lcu->lock); | ||
| 529 | lcu->pav = NO_PAV; | 546 | lcu->pav = NO_PAV; |
| 530 | for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { | 547 | for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { |
| 531 | switch (lcu->uac->unit[i].ua_type) { | 548 | switch (lcu->uac->unit[i].ua_type) { |
| @@ -542,9 +559,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) | |||
| 542 | 559 | ||
| 543 | list_for_each_entry_safe(device, tempdev, &lcu->active_devices, | 560 | list_for_each_entry_safe(device, tempdev, &lcu->active_devices, |
| 544 | alias_list) { | 561 | alias_list) { |
| 545 | _add_device_to_lcu(lcu, device); | 562 | _add_device_to_lcu(lcu, device, refdev); |
| 546 | } | 563 | } |
| 547 | spin_unlock_irqrestore(&lcu->lock, flags); | 564 | spin_unlock(&lcu->lock); |
| 565 | spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags); | ||
| 548 | return 0; | 566 | return 0; |
| 549 | } | 567 | } |
| 550 | 568 | ||
| @@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device) | |||
| 628 | private = (struct dasd_eckd_private *) device->private; | 646 | private = (struct dasd_eckd_private *) device->private; |
| 629 | lcu = private->lcu; | 647 | lcu = private->lcu; |
| 630 | rc = 0; | 648 | rc = 0; |
| 631 | spin_lock_irqsave(&lcu->lock, flags); | 649 | |
| 650 | /* need to take cdev lock before lcu lock */ | ||
| 651 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 652 | spin_lock(&lcu->lock); | ||
| 632 | if (!(lcu->flags & UPDATE_PENDING)) { | 653 | if (!(lcu->flags & UPDATE_PENDING)) { |
| 633 | rc = _add_device_to_lcu(lcu, device); | 654 | rc = _add_device_to_lcu(lcu, device, device); |
| 634 | if (rc) | 655 | if (rc) |
| 635 | lcu->flags |= UPDATE_PENDING; | 656 | lcu->flags |= UPDATE_PENDING; |
| 636 | } | 657 | } |
| @@ -638,10 +659,19 @@ int dasd_alias_add_device(struct dasd_device *device) | |||
| 638 | list_move(&device->alias_list, &lcu->active_devices); | 659 | list_move(&device->alias_list, &lcu->active_devices); |
| 639 | _schedule_lcu_update(lcu, device); | 660 | _schedule_lcu_update(lcu, device); |
| 640 | } | 661 | } |
| 641 | spin_unlock_irqrestore(&lcu->lock, flags); | 662 | spin_unlock(&lcu->lock); |
| 663 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 642 | return rc; | 664 | return rc; |
| 643 | } | 665 | } |
| 644 | 666 | ||
| 667 | int dasd_alias_update_add_device(struct dasd_device *device) | ||
| 668 | { | ||
| 669 | struct dasd_eckd_private *private; | ||
| 670 | private = (struct dasd_eckd_private *) device->private; | ||
| 671 | private->lcu->flags |= UPDATE_PENDING; | ||
| 672 | return dasd_alias_add_device(device); | ||
| 673 | } | ||
| 674 | |||
| 645 | int dasd_alias_remove_device(struct dasd_device *device) | 675 | int dasd_alias_remove_device(struct dasd_device *device) |
| 646 | { | 676 | { |
| 647 | struct dasd_eckd_private *private; | 677 | struct dasd_eckd_private *private; |
| @@ -740,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu) | |||
| 740 | struct alias_pav_group *pavgroup; | 770 | struct alias_pav_group *pavgroup; |
| 741 | struct dasd_device *device; | 771 | struct dasd_device *device; |
| 742 | struct dasd_eckd_private *private; | 772 | struct dasd_eckd_private *private; |
| 773 | unsigned long flags; | ||
| 743 | 774 | ||
| 744 | /* active and inactive list can contain alias as well as base devices */ | 775 | /* active and inactive list can contain alias as well as base devices */ |
| 745 | list_for_each_entry(device, &lcu->active_devices, alias_list) { | 776 | list_for_each_entry(device, &lcu->active_devices, alias_list) { |
| 746 | private = (struct dasd_eckd_private *) device->private; | 777 | private = (struct dasd_eckd_private *) device->private; |
| 747 | if (private->uid.type != UA_BASE_DEVICE) | 778 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
| 779 | if (private->uid.type != UA_BASE_DEVICE) { | ||
| 780 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | ||
| 781 | flags); | ||
| 748 | continue; | 782 | continue; |
| 783 | } | ||
| 784 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 749 | dasd_schedule_block_bh(device->block); | 785 | dasd_schedule_block_bh(device->block); |
| 750 | dasd_schedule_device_bh(device); | 786 | dasd_schedule_device_bh(device); |
| 751 | } | 787 | } |
| 752 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { | 788 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { |
| 753 | private = (struct dasd_eckd_private *) device->private; | 789 | private = (struct dasd_eckd_private *) device->private; |
| 754 | if (private->uid.type != UA_BASE_DEVICE) | 790 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
| 791 | if (private->uid.type != UA_BASE_DEVICE) { | ||
| 792 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | ||
| 793 | flags); | ||
| 755 | continue; | 794 | continue; |
| 795 | } | ||
| 796 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 756 | dasd_schedule_block_bh(device->block); | 797 | dasd_schedule_block_bh(device->block); |
| 757 | dasd_schedule_device_bh(device); | 798 | dasd_schedule_device_bh(device); |
| 758 | } | 799 | } |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index eff9c812c5c2..34d51dd4c539 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
| @@ -49,7 +49,6 @@ struct dasd_devmap { | |||
| 49 | unsigned int devindex; | 49 | unsigned int devindex; |
| 50 | unsigned short features; | 50 | unsigned short features; |
| 51 | struct dasd_device *device; | 51 | struct dasd_device *device; |
| 52 | struct dasd_uid uid; | ||
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 55 | /* | 54 | /* |
| @@ -936,42 +935,46 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr, | |||
| 936 | 935 | ||
| 937 | static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); | 936 | static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); |
| 938 | 937 | ||
| 939 | static ssize_t | 938 | static ssize_t dasd_alias_show(struct device *dev, |
| 940 | dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) | 939 | struct device_attribute *attr, char *buf) |
| 941 | { | 940 | { |
| 942 | struct dasd_devmap *devmap; | 941 | struct dasd_device *device; |
| 943 | int alias; | 942 | struct dasd_uid uid; |
| 944 | 943 | ||
| 945 | devmap = dasd_find_busid(dev_name(dev)); | 944 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 946 | spin_lock(&dasd_devmap_lock); | 945 | if (IS_ERR(device)) |
| 947 | if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { | ||
| 948 | spin_unlock(&dasd_devmap_lock); | ||
| 949 | return sprintf(buf, "0\n"); | 946 | return sprintf(buf, "0\n"); |
| 947 | |||
| 948 | if (device->discipline && device->discipline->get_uid && | ||
| 949 | !device->discipline->get_uid(device, &uid)) { | ||
| 950 | if (uid.type == UA_BASE_PAV_ALIAS || | ||
| 951 | uid.type == UA_HYPER_PAV_ALIAS) | ||
| 952 | return sprintf(buf, "1\n"); | ||
| 950 | } | 953 | } |
| 951 | if (devmap->uid.type == UA_BASE_PAV_ALIAS || | 954 | dasd_put_device(device); |
| 952 | devmap->uid.type == UA_HYPER_PAV_ALIAS) | 955 | |
| 953 | alias = 1; | 956 | return sprintf(buf, "0\n"); |
| 954 | else | ||
| 955 | alias = 0; | ||
| 956 | spin_unlock(&dasd_devmap_lock); | ||
| 957 | return sprintf(buf, alias ? "1\n" : "0\n"); | ||
| 958 | } | 957 | } |
| 959 | 958 | ||
| 960 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); | 959 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); |
| 961 | 960 | ||
| 962 | static ssize_t | 961 | static ssize_t dasd_vendor_show(struct device *dev, |
| 963 | dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) | 962 | struct device_attribute *attr, char *buf) |
| 964 | { | 963 | { |
| 965 | struct dasd_devmap *devmap; | 964 | struct dasd_device *device; |
| 965 | struct dasd_uid uid; | ||
| 966 | char *vendor; | 966 | char *vendor; |
| 967 | 967 | ||
| 968 | devmap = dasd_find_busid(dev_name(dev)); | 968 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 969 | spin_lock(&dasd_devmap_lock); | 969 | vendor = ""; |
| 970 | if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) | 970 | if (IS_ERR(device)) |
| 971 | vendor = devmap->uid.vendor; | 971 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); |
| 972 | else | 972 | |
| 973 | vendor = ""; | 973 | if (device->discipline && device->discipline->get_uid && |
| 974 | spin_unlock(&dasd_devmap_lock); | 974 | !device->discipline->get_uid(device, &uid)) |
| 975 | vendor = uid.vendor; | ||
| 976 | |||
| 977 | dasd_put_device(device); | ||
| 975 | 978 | ||
| 976 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); | 979 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); |
| 977 | } | 980 | } |
| @@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL); | |||
| 985 | static ssize_t | 988 | static ssize_t |
| 986 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) | 989 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) |
| 987 | { | 990 | { |
| 988 | struct dasd_devmap *devmap; | 991 | struct dasd_device *device; |
| 992 | struct dasd_uid uid; | ||
| 989 | char uid_string[UID_STRLEN]; | 993 | char uid_string[UID_STRLEN]; |
| 990 | char ua_string[3]; | 994 | char ua_string[3]; |
| 991 | struct dasd_uid *uid; | ||
| 992 | 995 | ||
| 993 | devmap = dasd_find_busid(dev_name(dev)); | 996 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 994 | spin_lock(&dasd_devmap_lock); | 997 | uid_string[0] = 0; |
| 995 | if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { | 998 | if (IS_ERR(device)) |
| 996 | spin_unlock(&dasd_devmap_lock); | 999 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); |
| 997 | return sprintf(buf, "\n"); | 1000 | |
| 998 | } | 1001 | if (device->discipline && device->discipline->get_uid && |
| 999 | uid = &devmap->uid; | 1002 | !device->discipline->get_uid(device, &uid)) { |
| 1000 | switch (uid->type) { | 1003 | switch (uid.type) { |
| 1001 | case UA_BASE_DEVICE: | 1004 | case UA_BASE_DEVICE: |
| 1002 | sprintf(ua_string, "%02x", uid->real_unit_addr); | 1005 | snprintf(ua_string, sizeof(ua_string), "%02x", |
| 1003 | break; | 1006 | uid.real_unit_addr); |
| 1004 | case UA_BASE_PAV_ALIAS: | 1007 | break; |
| 1005 | sprintf(ua_string, "%02x", uid->base_unit_addr); | 1008 | case UA_BASE_PAV_ALIAS: |
| 1006 | break; | 1009 | snprintf(ua_string, sizeof(ua_string), "%02x", |
| 1007 | case UA_HYPER_PAV_ALIAS: | 1010 | uid.base_unit_addr); |
| 1008 | sprintf(ua_string, "xx"); | 1011 | break; |
| 1009 | break; | 1012 | case UA_HYPER_PAV_ALIAS: |
| 1010 | default: | 1013 | snprintf(ua_string, sizeof(ua_string), "xx"); |
| 1011 | /* should not happen, treat like base device */ | 1014 | break; |
| 1012 | sprintf(ua_string, "%02x", uid->real_unit_addr); | 1015 | default: |
| 1013 | break; | 1016 | /* should not happen, treat like base device */ |
| 1017 | snprintf(ua_string, sizeof(ua_string), "%02x", | ||
| 1018 | uid.real_unit_addr); | ||
| 1019 | break; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if (strlen(uid.vduit) > 0) | ||
| 1023 | snprintf(uid_string, sizeof(uid_string), | ||
| 1024 | "%s.%s.%04x.%s.%s", | ||
| 1025 | uid.vendor, uid.serial, uid.ssid, ua_string, | ||
| 1026 | uid.vduit); | ||
| 1027 | else | ||
| 1028 | snprintf(uid_string, sizeof(uid_string), | ||
| 1029 | "%s.%s.%04x.%s", | ||
| 1030 | uid.vendor, uid.serial, uid.ssid, ua_string); | ||
| 1014 | } | 1031 | } |
| 1015 | if (strlen(uid->vduit) > 0) | 1032 | dasd_put_device(device); |
| 1016 | snprintf(uid_string, sizeof(uid_string), | 1033 | |
| 1017 | "%s.%s.%04x.%s.%s", | ||
| 1018 | uid->vendor, uid->serial, | ||
| 1019 | uid->ssid, ua_string, | ||
| 1020 | uid->vduit); | ||
| 1021 | else | ||
| 1022 | snprintf(uid_string, sizeof(uid_string), | ||
| 1023 | "%s.%s.%04x.%s", | ||
| 1024 | uid->vendor, uid->serial, | ||
| 1025 | uid->ssid, ua_string); | ||
| 1026 | spin_unlock(&dasd_devmap_lock); | ||
| 1027 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); | 1034 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); |
| 1028 | } | 1035 | } |
| 1029 | |||
| 1030 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); | 1036 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); |
| 1031 | 1037 | ||
| 1032 | /* | 1038 | /* |
| @@ -1094,50 +1100,6 @@ static struct attribute_group dasd_attr_group = { | |||
| 1094 | }; | 1100 | }; |
| 1095 | 1101 | ||
| 1096 | /* | 1102 | /* |
| 1097 | * Return copy of the device unique identifier. | ||
| 1098 | */ | ||
| 1099 | int | ||
| 1100 | dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 1101 | { | ||
| 1102 | struct dasd_devmap *devmap; | ||
| 1103 | |||
| 1104 | devmap = dasd_find_busid(dev_name(&cdev->dev)); | ||
| 1105 | if (IS_ERR(devmap)) | ||
| 1106 | return PTR_ERR(devmap); | ||
| 1107 | spin_lock(&dasd_devmap_lock); | ||
| 1108 | *uid = devmap->uid; | ||
| 1109 | spin_unlock(&dasd_devmap_lock); | ||
| 1110 | return 0; | ||
| 1111 | } | ||
| 1112 | EXPORT_SYMBOL_GPL(dasd_get_uid); | ||
| 1113 | |||
| 1114 | /* | ||
| 1115 | * Register the given device unique identifier into devmap struct. | ||
| 1116 | * In addition check if the related storage server subsystem ID is already | ||
| 1117 | * contained in the dasd_server_ssid_list. If subsystem ID is not contained, | ||
| 1118 | * create new entry. | ||
| 1119 | * Return 0 if server was already in serverlist, | ||
| 1120 | * 1 if the server was added successful | ||
| 1121 | * <0 in case of error. | ||
| 1122 | */ | ||
| 1123 | int | ||
| 1124 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 1125 | { | ||
| 1126 | struct dasd_devmap *devmap; | ||
| 1127 | |||
| 1128 | devmap = dasd_find_busid(dev_name(&cdev->dev)); | ||
| 1129 | if (IS_ERR(devmap)) | ||
| 1130 | return PTR_ERR(devmap); | ||
| 1131 | |||
| 1132 | spin_lock(&dasd_devmap_lock); | ||
| 1133 | devmap->uid = *uid; | ||
| 1134 | spin_unlock(&dasd_devmap_lock); | ||
| 1135 | |||
| 1136 | return 0; | ||
| 1137 | } | ||
| 1138 | EXPORT_SYMBOL_GPL(dasd_set_uid); | ||
| 1139 | |||
| 1140 | /* | ||
| 1141 | * Return value of the specified feature. | 1103 | * Return value of the specified feature. |
| 1142 | */ | 1104 | */ |
| 1143 | int | 1105 | int |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0cb233116855..5b1cd8d6e971 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid) | |||
| 692 | /* | 692 | /* |
| 693 | * Generate device unique id that specifies the physical device. | 693 | * Generate device unique id that specifies the physical device. |
| 694 | */ | 694 | */ |
| 695 | static int dasd_eckd_generate_uid(struct dasd_device *device, | 695 | static int dasd_eckd_generate_uid(struct dasd_device *device) |
| 696 | struct dasd_uid *uid) | ||
| 697 | { | 696 | { |
| 698 | struct dasd_eckd_private *private; | 697 | struct dasd_eckd_private *private; |
| 698 | struct dasd_uid *uid; | ||
| 699 | int count; | 699 | int count; |
| 700 | unsigned long flags; | ||
| 700 | 701 | ||
| 701 | private = (struct dasd_eckd_private *) device->private; | 702 | private = (struct dasd_eckd_private *) device->private; |
| 702 | if (!private) | 703 | if (!private) |
| 703 | return -ENODEV; | 704 | return -ENODEV; |
| 704 | if (!private->ned || !private->gneq) | 705 | if (!private->ned || !private->gneq) |
| 705 | return -ENODEV; | 706 | return -ENODEV; |
| 706 | 707 | uid = &private->uid; | |
| 708 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 707 | memset(uid, 0, sizeof(struct dasd_uid)); | 709 | memset(uid, 0, sizeof(struct dasd_uid)); |
| 708 | memcpy(uid->vendor, private->ned->HDA_manufacturer, | 710 | memcpy(uid->vendor, private->ned->HDA_manufacturer, |
| 709 | sizeof(uid->vendor) - 1); | 711 | sizeof(uid->vendor) - 1); |
| @@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device, | |||
| 726 | private->vdsneq->uit[count]); | 728 | private->vdsneq->uit[count]); |
| 727 | } | 729 | } |
| 728 | } | 730 | } |
| 731 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 729 | return 0; | 732 | return 0; |
| 730 | } | 733 | } |
| 731 | 734 | ||
| 735 | static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) | ||
| 736 | { | ||
| 737 | struct dasd_eckd_private *private; | ||
| 738 | unsigned long flags; | ||
| 739 | |||
| 740 | if (device->private) { | ||
| 741 | private = (struct dasd_eckd_private *)device->private; | ||
| 742 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 743 | *uid = private->uid; | ||
| 744 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 745 | return 0; | ||
| 746 | } | ||
| 747 | return -EINVAL; | ||
| 748 | } | ||
| 749 | |||
| 732 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, | 750 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, |
| 733 | void *rcd_buffer, | 751 | void *rcd_buffer, |
| 734 | struct ciw *ciw, __u8 lpm) | 752 | struct ciw *ciw, __u8 lpm) |
| @@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1088 | { | 1106 | { |
| 1089 | struct dasd_eckd_private *private; | 1107 | struct dasd_eckd_private *private; |
| 1090 | struct dasd_block *block; | 1108 | struct dasd_block *block; |
| 1109 | struct dasd_uid temp_uid; | ||
| 1091 | int is_known, rc; | 1110 | int is_known, rc; |
| 1092 | int readonly; | 1111 | int readonly; |
| 1093 | 1112 | ||
| @@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1124 | if (rc) | 1143 | if (rc) |
| 1125 | goto out_err1; | 1144 | goto out_err1; |
| 1126 | 1145 | ||
| 1127 | /* Generate device unique id and register in devmap */ | 1146 | /* Generate device unique id */ |
| 1128 | rc = dasd_eckd_generate_uid(device, &private->uid); | 1147 | rc = dasd_eckd_generate_uid(device); |
| 1129 | if (rc) | 1148 | if (rc) |
| 1130 | goto out_err1; | 1149 | goto out_err1; |
| 1131 | dasd_set_uid(device->cdev, &private->uid); | ||
| 1132 | 1150 | ||
| 1133 | if (private->uid.type == UA_BASE_DEVICE) { | 1151 | dasd_eckd_get_uid(device, &temp_uid); |
| 1152 | if (temp_uid.type == UA_BASE_DEVICE) { | ||
| 1134 | block = dasd_alloc_block(); | 1153 | block = dasd_alloc_block(); |
| 1135 | if (IS_ERR(block)) { | 1154 | if (IS_ERR(block)) { |
| 1136 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | 1155 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
| @@ -1451,6 +1470,7 @@ static int dasd_eckd_ready_to_online(struct dasd_device *device) | |||
| 1451 | 1470 | ||
| 1452 | static int dasd_eckd_online_to_ready(struct dasd_device *device) | 1471 | static int dasd_eckd_online_to_ready(struct dasd_device *device) |
| 1453 | { | 1472 | { |
| 1473 | cancel_work_sync(&device->reload_device); | ||
| 1454 | return dasd_alias_remove_device(device); | 1474 | return dasd_alias_remove_device(device); |
| 1455 | }; | 1475 | }; |
| 1456 | 1476 | ||
| @@ -1709,10 +1729,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
| 1709 | { | 1729 | { |
| 1710 | char mask; | 1730 | char mask; |
| 1711 | char *sense = NULL; | 1731 | char *sense = NULL; |
| 1732 | struct dasd_eckd_private *private; | ||
| 1712 | 1733 | ||
| 1734 | private = (struct dasd_eckd_private *) device->private; | ||
| 1713 | /* first of all check for state change pending interrupt */ | 1735 | /* first of all check for state change pending interrupt */ |
| 1714 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; | 1736 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; |
| 1715 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { | 1737 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { |
| 1738 | /* for alias only and not in offline processing*/ | ||
| 1739 | if (!device->block && private->lcu && | ||
| 1740 | !test_bit(DASD_FLAG_OFFLINE, &device->flags)) { | ||
| 1741 | /* | ||
| 1742 | * the state change could be caused by an alias | ||
| 1743 | * reassignment remove device from alias handling | ||
| 1744 | * to prevent new requests from being scheduled on | ||
| 1745 | * the wrong alias device | ||
| 1746 | */ | ||
| 1747 | dasd_alias_remove_device(device); | ||
| 1748 | |||
| 1749 | /* schedule worker to reload device */ | ||
| 1750 | dasd_reload_device(device); | ||
| 1751 | } | ||
| 1752 | |||
| 1716 | dasd_generic_handle_state_change(device); | 1753 | dasd_generic_handle_state_change(device); |
| 1717 | return; | 1754 | return; |
| 1718 | } | 1755 | } |
| @@ -3259,7 +3296,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, | |||
| 3259 | dasd_eckd_dump_sense_ccw(device, req, irb); | 3296 | dasd_eckd_dump_sense_ccw(device, req, irb); |
| 3260 | } | 3297 | } |
| 3261 | 3298 | ||
| 3262 | int dasd_eckd_pm_freeze(struct dasd_device *device) | 3299 | static int dasd_eckd_pm_freeze(struct dasd_device *device) |
| 3263 | { | 3300 | { |
| 3264 | /* | 3301 | /* |
| 3265 | * the device should be disconnected from our LCU structure | 3302 | * the device should be disconnected from our LCU structure |
| @@ -3272,7 +3309,7 @@ int dasd_eckd_pm_freeze(struct dasd_device *device) | |||
| 3272 | return 0; | 3309 | return 0; |
| 3273 | } | 3310 | } |
| 3274 | 3311 | ||
| 3275 | int dasd_eckd_restore_device(struct dasd_device *device) | 3312 | static int dasd_eckd_restore_device(struct dasd_device *device) |
| 3276 | { | 3313 | { |
| 3277 | struct dasd_eckd_private *private; | 3314 | struct dasd_eckd_private *private; |
| 3278 | struct dasd_eckd_characteristics temp_rdc_data; | 3315 | struct dasd_eckd_characteristics temp_rdc_data; |
| @@ -3287,15 +3324,16 @@ int dasd_eckd_restore_device(struct dasd_device *device) | |||
| 3287 | if (rc) | 3324 | if (rc) |
| 3288 | goto out_err; | 3325 | goto out_err; |
| 3289 | 3326 | ||
| 3290 | /* Generate device unique id and register in devmap */ | 3327 | dasd_eckd_get_uid(device, &temp_uid); |
| 3291 | rc = dasd_eckd_generate_uid(device, &private->uid); | 3328 | /* Generate device unique id */ |
| 3292 | dasd_get_uid(device->cdev, &temp_uid); | 3329 | rc = dasd_eckd_generate_uid(device); |
| 3330 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 3293 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) | 3331 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) |
| 3294 | dev_err(&device->cdev->dev, "The UID of the DASD has " | 3332 | dev_err(&device->cdev->dev, "The UID of the DASD has " |
| 3295 | "changed\n"); | 3333 | "changed\n"); |
| 3334 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 3296 | if (rc) | 3335 | if (rc) |
| 3297 | goto out_err; | 3336 | goto out_err; |
| 3298 | dasd_set_uid(device->cdev, &private->uid); | ||
| 3299 | 3337 | ||
| 3300 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 3338 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
| 3301 | is_known = dasd_alias_make_device_known_to_lcu(device); | 3339 | is_known = dasd_alias_make_device_known_to_lcu(device); |
| @@ -3336,6 +3374,56 @@ out_err: | |||
| 3336 | return -1; | 3374 | return -1; |
| 3337 | } | 3375 | } |
| 3338 | 3376 | ||
| 3377 | static int dasd_eckd_reload_device(struct dasd_device *device) | ||
| 3378 | { | ||
| 3379 | struct dasd_eckd_private *private; | ||
| 3380 | int rc, old_base; | ||
| 3381 | char print_uid[60]; | ||
| 3382 | struct dasd_uid uid; | ||
| 3383 | unsigned long flags; | ||
| 3384 | |||
| 3385 | private = (struct dasd_eckd_private *) device->private; | ||
| 3386 | |||
| 3387 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 3388 | old_base = private->uid.base_unit_addr; | ||
| 3389 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 3390 | |||
| 3391 | /* Read Configuration Data */ | ||
| 3392 | rc = dasd_eckd_read_conf(device); | ||
| 3393 | if (rc) | ||
| 3394 | goto out_err; | ||
| 3395 | |||
| 3396 | rc = dasd_eckd_generate_uid(device); | ||
| 3397 | if (rc) | ||
| 3398 | goto out_err; | ||
| 3399 | /* | ||
| 3400 | * update unit address configuration and | ||
| 3401 | * add device to alias management | ||
| 3402 | */ | ||
| 3403 | dasd_alias_update_add_device(device); | ||
| 3404 | |||
| 3405 | dasd_eckd_get_uid(device, &uid); | ||
| 3406 | |||
| 3407 | if (old_base != uid.base_unit_addr) { | ||
| 3408 | if (strlen(uid.vduit) > 0) | ||
| 3409 | snprintf(print_uid, sizeof(print_uid), | ||
| 3410 | "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial, | ||
| 3411 | uid.ssid, uid.base_unit_addr, uid.vduit); | ||
| 3412 | else | ||
| 3413 | snprintf(print_uid, sizeof(print_uid), | ||
| 3414 | "%s.%s.%04x.%02x", uid.vendor, uid.serial, | ||
| 3415 | uid.ssid, uid.base_unit_addr); | ||
| 3416 | |||
| 3417 | dev_info(&device->cdev->dev, | ||
| 3418 | "An Alias device was reassigned to a new base device " | ||
| 3419 | "with UID: %s\n", print_uid); | ||
| 3420 | } | ||
| 3421 | return 0; | ||
| 3422 | |||
| 3423 | out_err: | ||
| 3424 | return -1; | ||
| 3425 | } | ||
| 3426 | |||
| 3339 | static struct ccw_driver dasd_eckd_driver = { | 3427 | static struct ccw_driver dasd_eckd_driver = { |
| 3340 | .name = "dasd-eckd", | 3428 | .name = "dasd-eckd", |
| 3341 | .owner = THIS_MODULE, | 3429 | .owner = THIS_MODULE, |
| @@ -3389,6 +3477,8 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
| 3389 | .ioctl = dasd_eckd_ioctl, | 3477 | .ioctl = dasd_eckd_ioctl, |
| 3390 | .freeze = dasd_eckd_pm_freeze, | 3478 | .freeze = dasd_eckd_pm_freeze, |
| 3391 | .restore = dasd_eckd_restore_device, | 3479 | .restore = dasd_eckd_restore_device, |
| 3480 | .reload = dasd_eckd_reload_device, | ||
| 3481 | .get_uid = dasd_eckd_get_uid, | ||
| 3392 | }; | 3482 | }; |
| 3393 | 3483 | ||
| 3394 | static int __init | 3484 | static int __init |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 864d53c04201..dd6385a5af14 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
| @@ -426,7 +426,6 @@ struct alias_pav_group { | |||
| 426 | struct dasd_device *next; | 426 | struct dasd_device *next; |
| 427 | }; | 427 | }; |
| 428 | 428 | ||
| 429 | |||
| 430 | struct dasd_eckd_private { | 429 | struct dasd_eckd_private { |
| 431 | struct dasd_eckd_characteristics rdc_data; | 430 | struct dasd_eckd_characteristics rdc_data; |
| 432 | u8 *conf_data; | 431 | u8 *conf_data; |
| @@ -463,4 +462,5 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *); | |||
| 463 | void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); | 462 | void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); |
| 464 | void dasd_alias_lcu_setup_complete(struct dasd_device *); | 463 | void dasd_alias_lcu_setup_complete(struct dasd_device *); |
| 465 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *); | 464 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *); |
| 465 | int dasd_alias_update_add_device(struct dasd_device *); | ||
| 466 | #endif /* DASD_ECKD_H */ | 466 | #endif /* DASD_ECKD_H */ |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a91d4a97d4f2..32fac186ba3f 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -81,6 +81,10 @@ struct dasd_block; | |||
| 81 | #define DASD_SIM_MSG_TO_OP 0x03 | 81 | #define DASD_SIM_MSG_TO_OP 0x03 |
| 82 | #define DASD_SIM_LOG 0x0C | 82 | #define DASD_SIM_LOG 0x0C |
| 83 | 83 | ||
| 84 | /* lock class for nested cdev lock */ | ||
| 85 | #define CDEV_NESTED_FIRST 1 | ||
| 86 | #define CDEV_NESTED_SECOND 2 | ||
| 87 | |||
| 84 | /* | 88 | /* |
| 85 | * SECTION: MACROs for klogd and s390 debug feature (dbf) | 89 | * SECTION: MACROs for klogd and s390 debug feature (dbf) |
| 86 | */ | 90 | */ |
| @@ -229,6 +233,24 @@ struct dasd_ccw_req { | |||
| 229 | typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); | 233 | typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); |
| 230 | 234 | ||
| 231 | /* | 235 | /* |
| 236 | * Unique identifier for dasd device. | ||
| 237 | */ | ||
| 238 | #define UA_NOT_CONFIGURED 0x00 | ||
| 239 | #define UA_BASE_DEVICE 0x01 | ||
| 240 | #define UA_BASE_PAV_ALIAS 0x02 | ||
| 241 | #define UA_HYPER_PAV_ALIAS 0x03 | ||
| 242 | |||
| 243 | struct dasd_uid { | ||
| 244 | __u8 type; | ||
| 245 | char vendor[4]; | ||
| 246 | char serial[15]; | ||
| 247 | __u16 ssid; | ||
| 248 | __u8 real_unit_addr; | ||
| 249 | __u8 base_unit_addr; | ||
| 250 | char vduit[33]; | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* | ||
| 232 | * the struct dasd_discipline is | 254 | * the struct dasd_discipline is |
| 233 | * sth like a table of virtual functions, if you think of dasd_eckd | 255 | * sth like a table of virtual functions, if you think of dasd_eckd |
| 234 | * inheriting dasd... | 256 | * inheriting dasd... |
| @@ -312,28 +334,15 @@ struct dasd_discipline { | |||
| 312 | /* suspend/resume functions */ | 334 | /* suspend/resume functions */ |
| 313 | int (*freeze) (struct dasd_device *); | 335 | int (*freeze) (struct dasd_device *); |
| 314 | int (*restore) (struct dasd_device *); | 336 | int (*restore) (struct dasd_device *); |
| 315 | }; | ||
| 316 | 337 | ||
| 317 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 338 | /* reload device after state change */ |
| 318 | 339 | int (*reload) (struct dasd_device *); | |
| 319 | /* | ||
| 320 | * Unique identifier for dasd device. | ||
| 321 | */ | ||
| 322 | #define UA_NOT_CONFIGURED 0x00 | ||
| 323 | #define UA_BASE_DEVICE 0x01 | ||
| 324 | #define UA_BASE_PAV_ALIAS 0x02 | ||
| 325 | #define UA_HYPER_PAV_ALIAS 0x03 | ||
| 326 | 340 | ||
| 327 | struct dasd_uid { | 341 | int (*get_uid) (struct dasd_device *, struct dasd_uid *); |
| 328 | __u8 type; | ||
| 329 | char vendor[4]; | ||
| 330 | char serial[15]; | ||
| 331 | __u16 ssid; | ||
| 332 | __u8 real_unit_addr; | ||
| 333 | __u8 base_unit_addr; | ||
| 334 | char vduit[33]; | ||
| 335 | }; | 342 | }; |
| 336 | 343 | ||
| 344 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | ||
| 345 | |||
| 337 | /* | 346 | /* |
| 338 | * Notification numbers for extended error reporting notifications: | 347 | * Notification numbers for extended error reporting notifications: |
| 339 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's | 348 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's |
| @@ -386,6 +395,7 @@ struct dasd_device { | |||
| 386 | struct tasklet_struct tasklet; | 395 | struct tasklet_struct tasklet; |
| 387 | struct work_struct kick_work; | 396 | struct work_struct kick_work; |
| 388 | struct work_struct restore_device; | 397 | struct work_struct restore_device; |
| 398 | struct work_struct reload_device; | ||
| 389 | struct timer_list timer; | 399 | struct timer_list timer; |
| 390 | 400 | ||
| 391 | debug_info_t *debug_area; | 401 | debug_info_t *debug_area; |
| @@ -582,6 +592,7 @@ void dasd_enable_device(struct dasd_device *); | |||
| 582 | void dasd_set_target_state(struct dasd_device *, int); | 592 | void dasd_set_target_state(struct dasd_device *, int); |
| 583 | void dasd_kick_device(struct dasd_device *); | 593 | void dasd_kick_device(struct dasd_device *); |
| 584 | void dasd_restore_device(struct dasd_device *); | 594 | void dasd_restore_device(struct dasd_device *); |
| 595 | void dasd_reload_device(struct dasd_device *); | ||
| 585 | 596 | ||
| 586 | void dasd_add_request_head(struct dasd_ccw_req *); | 597 | void dasd_add_request_head(struct dasd_ccw_req *); |
| 587 | void dasd_add_request_tail(struct dasd_ccw_req *); | 598 | void dasd_add_request_tail(struct dasd_ccw_req *); |
| @@ -629,8 +640,6 @@ void dasd_devmap_exit(void); | |||
| 629 | struct dasd_device *dasd_create_device(struct ccw_device *); | 640 | struct dasd_device *dasd_create_device(struct ccw_device *); |
| 630 | void dasd_delete_device(struct dasd_device *); | 641 | void dasd_delete_device(struct dasd_device *); |
| 631 | 642 | ||
| 632 | int dasd_get_uid(struct ccw_device *, struct dasd_uid *); | ||
| 633 | int dasd_set_uid(struct ccw_device *, struct dasd_uid *); | ||
| 634 | int dasd_get_feature(struct ccw_device *, int); | 643 | int dasd_get_feature(struct ccw_device *, int); |
| 635 | int dasd_set_feature(struct ccw_device *, int, int); | 644 | int dasd_set_feature(struct ccw_device *, int, int); |
| 636 | 645 | ||
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 4e34d3686c23..40834f18754c 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig | |||
| @@ -148,13 +148,12 @@ config VMLOGRDR | |||
| 148 | This driver depends on the IUCV support driver. | 148 | This driver depends on the IUCV support driver. |
| 149 | 149 | ||
| 150 | config VMCP | 150 | config VMCP |
| 151 | tristate "Support for the z/VM CP interface (VM only)" | 151 | bool "Support for the z/VM CP interface" |
| 152 | depends on S390 | 152 | depends on S390 |
| 153 | help | 153 | help |
| 154 | Select this option if you want to be able to interact with the control | 154 | Select this option if you want to be able to interact with the control |
| 155 | program on z/VM | 155 | program on z/VM |
| 156 | 156 | ||
| 157 | |||
| 158 | config MONREADER | 157 | config MONREADER |
| 159 | tristate "API for reading z/VM monitor service records" | 158 | tristate "API for reading z/VM monitor service records" |
| 160 | depends on IUCV | 159 | depends on IUCV |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 0eabcca3c92d..857dfcb7b359 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
| @@ -484,6 +484,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
| 484 | raw3270_del_view(&fp->view); | 484 | raw3270_del_view(&fp->view); |
| 485 | goto out; | 485 | goto out; |
| 486 | } | 486 | } |
| 487 | nonseekable_open(inode, filp); | ||
| 487 | filp->private_data = fp; | 488 | filp->private_data = fp; |
| 488 | out: | 489 | out: |
| 489 | mutex_unlock(&fs3270_mutex); | 490 | mutex_unlock(&fs3270_mutex); |
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index cb6bffe7141a..18d9a497863b 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
| @@ -49,7 +49,7 @@ static unsigned char ret_diacr[NR_DEAD] = { | |||
| 49 | struct kbd_data * | 49 | struct kbd_data * |
| 50 | kbd_alloc(void) { | 50 | kbd_alloc(void) { |
| 51 | struct kbd_data *kbd; | 51 | struct kbd_data *kbd; |
| 52 | int i, len; | 52 | int i; |
| 53 | 53 | ||
| 54 | kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); | 54 | kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); |
| 55 | if (!kbd) | 55 | if (!kbd) |
| @@ -59,12 +59,11 @@ kbd_alloc(void) { | |||
| 59 | goto out_kbd; | 59 | goto out_kbd; |
| 60 | for (i = 0; i < ARRAY_SIZE(key_maps); i++) { | 60 | for (i = 0; i < ARRAY_SIZE(key_maps); i++) { |
| 61 | if (key_maps[i]) { | 61 | if (key_maps[i]) { |
| 62 | kbd->key_maps[i] = | 62 | kbd->key_maps[i] = kmemdup(key_maps[i], |
| 63 | kmalloc(sizeof(u_short)*NR_KEYS, GFP_KERNEL); | 63 | sizeof(u_short) * NR_KEYS, |
| 64 | GFP_KERNEL); | ||
| 64 | if (!kbd->key_maps[i]) | 65 | if (!kbd->key_maps[i]) |
| 65 | goto out_maps; | 66 | goto out_maps; |
| 66 | memcpy(kbd->key_maps[i], key_maps[i], | ||
| 67 | sizeof(u_short)*NR_KEYS); | ||
| 68 | } | 67 | } |
| 69 | } | 68 | } |
| 70 | kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); | 69 | kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); |
| @@ -72,23 +71,21 @@ kbd_alloc(void) { | |||
| 72 | goto out_maps; | 71 | goto out_maps; |
| 73 | for (i = 0; i < ARRAY_SIZE(func_table); i++) { | 72 | for (i = 0; i < ARRAY_SIZE(func_table); i++) { |
| 74 | if (func_table[i]) { | 73 | if (func_table[i]) { |
| 75 | len = strlen(func_table[i]) + 1; | 74 | kbd->func_table[i] = kstrdup(func_table[i], |
| 76 | kbd->func_table[i] = kmalloc(len, GFP_KERNEL); | 75 | GFP_KERNEL); |
| 77 | if (!kbd->func_table[i]) | 76 | if (!kbd->func_table[i]) |
| 78 | goto out_func; | 77 | goto out_func; |
| 79 | memcpy(kbd->func_table[i], func_table[i], len); | ||
| 80 | } | 78 | } |
| 81 | } | 79 | } |
| 82 | kbd->fn_handler = | 80 | kbd->fn_handler = |
| 83 | kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); | 81 | kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); |
| 84 | if (!kbd->fn_handler) | 82 | if (!kbd->fn_handler) |
| 85 | goto out_func; | 83 | goto out_func; |
| 86 | kbd->accent_table = | 84 | kbd->accent_table = kmemdup(accent_table, |
| 87 | kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL); | 85 | sizeof(struct kbdiacruc) * MAX_DIACR, |
| 86 | GFP_KERNEL); | ||
| 88 | if (!kbd->accent_table) | 87 | if (!kbd->accent_table) |
| 89 | goto out_fn_handler; | 88 | goto out_fn_handler; |
| 90 | memcpy(kbd->accent_table, accent_table, | ||
| 91 | sizeof(struct kbdiacruc)*MAX_DIACR); | ||
| 92 | kbd->accent_table_size = accent_table_size; | 89 | kbd->accent_table_size = accent_table_size; |
| 93 | return kbd; | 90 | return kbd; |
| 94 | 91 | ||
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 5bb59d36a6d4..04e532eec032 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c | |||
| @@ -1,24 +1,20 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright IBM Corp. 2004,2007 | 2 | * Copyright IBM Corp. 2004,2010 |
| 3 | * Interface implementation for communication with the z/VM control program | 3 | * Interface implementation for communication with the z/VM control program |
| 4 | * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> | ||
| 5 | * | 4 | * |
| 5 | * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> | ||
| 6 | * | 6 | * |
| 7 | * z/VMs CP offers the possibility to issue commands via the diagnose code 8 | 7 | * z/VMs CP offers the possibility to issue commands via the diagnose code 8 |
| 8 | * this driver implements a character device that issues these commands and | 8 | * this driver implements a character device that issues these commands and |
| 9 | * returns the answer of CP. | 9 | * returns the answer of CP. |
| 10 | 10 | * | |
| 11 | * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS | 11 | * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #define KMSG_COMPONENT "vmcp" | ||
| 15 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
| 16 | |||
| 17 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
| 18 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 19 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 20 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 23 | #include <asm/compat.h> | 19 | #include <asm/compat.h> |
| 24 | #include <asm/cpcmd.h> | 20 | #include <asm/cpcmd.h> |
| @@ -26,10 +22,6 @@ | |||
| 26 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 27 | #include "vmcp.h" | 23 | #include "vmcp.h" |
| 28 | 24 | ||
| 29 | MODULE_LICENSE("GPL"); | ||
| 30 | MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>"); | ||
| 31 | MODULE_DESCRIPTION("z/VM CP interface"); | ||
| 32 | |||
| 33 | static debug_info_t *vmcp_debug; | 25 | static debug_info_t *vmcp_debug; |
| 34 | 26 | ||
| 35 | static int vmcp_open(struct inode *inode, struct file *file) | 27 | static int vmcp_open(struct inode *inode, struct file *file) |
| @@ -197,11 +189,8 @@ static int __init vmcp_init(void) | |||
| 197 | { | 189 | { |
| 198 | int ret; | 190 | int ret; |
| 199 | 191 | ||
| 200 | if (!MACHINE_IS_VM) { | 192 | if (!MACHINE_IS_VM) |
| 201 | pr_warning("The z/VM CP interface device driver cannot be " | 193 | return 0; |
| 202 | "loaded without z/VM\n"); | ||
| 203 | return -ENODEV; | ||
| 204 | } | ||
| 205 | 194 | ||
| 206 | vmcp_debug = debug_register("vmcp", 1, 1, 240); | 195 | vmcp_debug = debug_register("vmcp", 1, 1, 240); |
| 207 | if (!vmcp_debug) | 196 | if (!vmcp_debug) |
| @@ -214,19 +203,8 @@ static int __init vmcp_init(void) | |||
| 214 | } | 203 | } |
| 215 | 204 | ||
| 216 | ret = misc_register(&vmcp_dev); | 205 | ret = misc_register(&vmcp_dev); |
| 217 | if (ret) { | 206 | if (ret) |
| 218 | debug_unregister(vmcp_debug); | 207 | debug_unregister(vmcp_debug); |
| 219 | return ret; | 208 | return ret; |
| 220 | } | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static void __exit vmcp_exit(void) | ||
| 226 | { | ||
| 227 | misc_deregister(&vmcp_dev); | ||
| 228 | debug_unregister(vmcp_debug); | ||
| 229 | } | 209 | } |
| 230 | 210 | device_initcall(vmcp_init); | |
| 231 | module_init(vmcp_init); | ||
| 232 | module_exit(vmcp_exit); | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 7217966f7d31..f5ea3384a4b9 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
| @@ -445,7 +445,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp) | |||
| 445 | } | 445 | } |
| 446 | kfree(chunk_array); | 446 | kfree(chunk_array); |
| 447 | filp->private_data = buf; | 447 | filp->private_data = buf; |
| 448 | return 0; | 448 | return nonseekable_open(inode, filp); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | static int zcore_memmap_release(struct inode *inode, struct file *filp) | 451 | static int zcore_memmap_release(struct inode *inode, struct file *filp) |
| @@ -473,7 +473,7 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, | |||
| 473 | 473 | ||
| 474 | static int zcore_reipl_open(struct inode *inode, struct file *filp) | 474 | static int zcore_reipl_open(struct inode *inode, struct file *filp) |
| 475 | { | 475 | { |
| 476 | return 0; | 476 | return nonseekable_open(inode, filp); |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | static int zcore_reipl_release(struct inode *inode, struct file *filp) | 479 | static int zcore_reipl_release(struct inode *inode, struct file *filp) |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 3b6f4adc5094..a83877c664a6 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
| @@ -803,6 +803,7 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd, | |||
| 803 | 803 | ||
| 804 | static const struct file_operations chsc_fops = { | 804 | static const struct file_operations chsc_fops = { |
| 805 | .owner = THIS_MODULE, | 805 | .owner = THIS_MODULE, |
| 806 | .open = nonseekable_open, | ||
| 806 | .unlocked_ioctl = chsc_ioctl, | 807 | .unlocked_ioctl = chsc_ioctl, |
| 807 | .compat_ioctl = chsc_ioctl, | 808 | .compat_ioctl = chsc_ioctl, |
| 808 | }; | 809 | }; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5feea1a371e1..f4e6cf3aceb8 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
| @@ -616,7 +616,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 616 | struct pt_regs *old_regs; | 616 | struct pt_regs *old_regs; |
| 617 | 617 | ||
| 618 | old_regs = set_irq_regs(regs); | 618 | old_regs = set_irq_regs(regs); |
| 619 | s390_idle_check(); | 619 | s390_idle_check(regs, S390_lowcore.int_clock, |
| 620 | S390_lowcore.async_enter_timer); | ||
| 620 | irq_enter(); | 621 | irq_enter(); |
| 621 | __get_cpu_var(s390_idle).nohz_delay = 1; | 622 | __get_cpu_var(s390_idle).nohz_delay = 1; |
| 622 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | 623 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 511649115bd7..ac94ac751459 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
| @@ -648,6 +648,8 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
| 648 | static void __init | 648 | static void __init |
| 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) |
| 650 | { | 650 | { |
| 651 | struct cpuid cpu_id; | ||
| 652 | |||
| 651 | if (css_general_characteristics.mcss) { | 653 | if (css_general_characteristics.mcss) { |
| 652 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; | 654 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; |
| 653 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 655 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; |
| @@ -658,8 +660,9 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
| 658 | css->global_pgid.pgid_high.cpu_addr = 0; | 660 | css->global_pgid.pgid_high.cpu_addr = 0; |
| 659 | #endif | 661 | #endif |
| 660 | } | 662 | } |
| 661 | css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; | 663 | get_cpu_id(&cpu_id); |
| 662 | css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; | 664 | css->global_pgid.cpu_id = cpu_id.ident; |
| 665 | css->global_pgid.cpu_model = cpu_id.machine; | ||
| 663 | css->global_pgid.tod_high = tod_high; | 666 | css->global_pgid.tod_high = tod_high; |
| 664 | 667 | ||
| 665 | } | 668 | } |
| @@ -1062,6 +1065,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, | |||
| 1062 | } | 1065 | } |
| 1063 | 1066 | ||
| 1064 | static const struct file_operations cio_settle_proc_fops = { | 1067 | static const struct file_operations cio_settle_proc_fops = { |
| 1068 | .open = nonseekable_open, | ||
| 1065 | .write = cio_settle_write, | 1069 | .write = cio_settle_write, |
| 1066 | }; | 1070 | }; |
| 1067 | 1071 | ||
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 48aa0647432b..f0037eefd44e 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include <asm/debug.h> | 13 | #include <asm/debug.h> |
| 14 | #include "chsc.h" | 14 | #include "chsc.h" |
| 15 | 15 | ||
| 16 | #define QDIO_BUSY_BIT_PATIENCE 100 /* 100 microseconds */ | 16 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
| 17 | #define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */ | 17 | #define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait | 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait |
| @@ -296,10 +296,8 @@ struct qdio_q { | |||
| 296 | struct qdio_irq *irq_ptr; | 296 | struct qdio_irq *irq_ptr; |
| 297 | struct sl *sl; | 297 | struct sl *sl; |
| 298 | /* | 298 | /* |
| 299 | * Warning: Leave this member at the end so it won't be cleared in | 299 | * A page is allocated under this pointer and used for slib and sl. |
| 300 | * qdio_fill_qs. A page is allocated under this pointer and used for | 300 | * slib is 2048 bytes big and sl points to offset PAGE_SIZE / 2. |
| 301 | * slib and sl. slib is 2048 bytes big and sl points to offset | ||
| 302 | * PAGE_SIZE / 2. | ||
| 303 | */ | 301 | */ |
| 304 | struct slib *slib; | 302 | struct slib *slib; |
| 305 | } __attribute__ ((aligned(256))); | 303 | } __attribute__ ((aligned(256))); |
| @@ -372,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q) | |||
| 372 | (q->nr == q->irq_ptr->nr_output_qs - 1); | 370 | (q->nr == q->irq_ptr->nr_output_qs - 1); |
| 373 | } | 371 | } |
| 374 | 372 | ||
| 375 | static inline unsigned long long get_usecs(void) | ||
| 376 | { | ||
| 377 | return monotonic_clock() >> 12; | ||
| 378 | } | ||
| 379 | |||
| 380 | #define pci_out_supported(q) \ | 373 | #define pci_out_supported(q) \ |
| 381 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) | 374 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
| 382 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) | 375 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 88be7b9ea6e1..00520f9a7a8e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -336,10 +336,10 @@ again: | |||
| 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); | 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); |
| 337 | 337 | ||
| 338 | if (!start_time) { | 338 | if (!start_time) { |
| 339 | start_time = get_usecs(); | 339 | start_time = get_clock(); |
| 340 | goto again; | 340 | goto again; |
| 341 | } | 341 | } |
| 342 | if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) | 342 | if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE) |
| 343 | goto again; | 343 | goto again; |
| 344 | } | 344 | } |
| 345 | return cc; | 345 | return cc; |
| @@ -536,7 +536,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) | |||
| 536 | if ((bufnr != q->last_move) || q->qdio_error) { | 536 | if ((bufnr != q->last_move) || q->qdio_error) { |
| 537 | q->last_move = bufnr; | 537 | q->last_move = bufnr; |
| 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) | 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) |
| 539 | q->u.in.timestamp = get_usecs(); | 539 | q->u.in.timestamp = get_clock(); |
| 540 | return 1; | 540 | return 1; |
| 541 | } else | 541 | } else |
| 542 | return 0; | 542 | return 0; |
| @@ -567,7 +567,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
| 567 | * At this point we know, that inbound first_to_check | 567 | * At this point we know, that inbound first_to_check |
| 568 | * has (probably) not moved (see qdio_inbound_processing). | 568 | * has (probably) not moved (see qdio_inbound_processing). |
| 569 | */ | 569 | */ |
| 570 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | 570 | if (get_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { |
| 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", | 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", |
| 572 | q->first_to_check); | 572 | q->first_to_check); |
| 573 | return 1; | 573 | return 1; |
| @@ -606,7 +606,7 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
| 606 | static void __qdio_inbound_processing(struct qdio_q *q) | 606 | static void __qdio_inbound_processing(struct qdio_q *q) |
| 607 | { | 607 | { |
| 608 | qperf_inc(q, tasklet_inbound); | 608 | qperf_inc(q, tasklet_inbound); |
| 609 | again: | 609 | |
| 610 | if (!qdio_inbound_q_moved(q)) | 610 | if (!qdio_inbound_q_moved(q)) |
| 611 | return; | 611 | return; |
| 612 | 612 | ||
| @@ -615,7 +615,10 @@ again: | |||
| 615 | if (!qdio_inbound_q_done(q)) { | 615 | if (!qdio_inbound_q_done(q)) { |
| 616 | /* means poll time is not yet over */ | 616 | /* means poll time is not yet over */ |
| 617 | qperf_inc(q, tasklet_inbound_resched); | 617 | qperf_inc(q, tasklet_inbound_resched); |
| 618 | goto again; | 618 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { |
| 619 | tasklet_schedule(&q->tasklet); | ||
| 620 | return; | ||
| 621 | } | ||
| 619 | } | 622 | } |
| 620 | 623 | ||
| 621 | qdio_stop_polling(q); | 624 | qdio_stop_polling(q); |
| @@ -625,7 +628,8 @@ again: | |||
| 625 | */ | 628 | */ |
| 626 | if (!qdio_inbound_q_done(q)) { | 629 | if (!qdio_inbound_q_done(q)) { |
| 627 | qperf_inc(q, tasklet_inbound_resched2); | 630 | qperf_inc(q, tasklet_inbound_resched2); |
| 628 | goto again; | 631 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) |
| 632 | tasklet_schedule(&q->tasklet); | ||
| 629 | } | 633 | } |
| 630 | } | 634 | } |
| 631 | 635 | ||
| @@ -955,6 +959,9 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
| 955 | return; | 959 | return; |
| 956 | } | 960 | } |
| 957 | 961 | ||
| 962 | if (irq_ptr->perf_stat_enabled) | ||
| 963 | irq_ptr->perf_stat.qdio_int++; | ||
| 964 | |||
| 958 | if (IS_ERR(irb)) { | 965 | if (IS_ERR(irb)) { |
| 959 | switch (PTR_ERR(irb)) { | 966 | switch (PTR_ERR(irb)) { |
| 960 | case -EIO: | 967 | case -EIO: |
| @@ -1016,30 +1023,6 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev, | |||
| 1016 | } | 1023 | } |
| 1017 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | 1024 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); |
| 1018 | 1025 | ||
| 1019 | /** | ||
| 1020 | * qdio_cleanup - shutdown queues and free data structures | ||
| 1021 | * @cdev: associated ccw device | ||
| 1022 | * @how: use halt or clear to shutdown | ||
| 1023 | * | ||
| 1024 | * This function calls qdio_shutdown() for @cdev with method @how. | ||
| 1025 | * and qdio_free(). The qdio_free() return value is ignored since | ||
| 1026 | * !irq_ptr is already checked. | ||
| 1027 | */ | ||
| 1028 | int qdio_cleanup(struct ccw_device *cdev, int how) | ||
| 1029 | { | ||
| 1030 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
| 1031 | int rc; | ||
| 1032 | |||
| 1033 | if (!irq_ptr) | ||
| 1034 | return -ENODEV; | ||
| 1035 | |||
| 1036 | rc = qdio_shutdown(cdev, how); | ||
| 1037 | |||
| 1038 | qdio_free(cdev); | ||
| 1039 | return rc; | ||
| 1040 | } | ||
| 1041 | EXPORT_SYMBOL_GPL(qdio_cleanup); | ||
| 1042 | |||
| 1043 | static void qdio_shutdown_queues(struct ccw_device *cdev) | 1026 | static void qdio_shutdown_queues(struct ccw_device *cdev) |
| 1044 | { | 1027 | { |
| 1045 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1028 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
| @@ -1157,28 +1140,6 @@ int qdio_free(struct ccw_device *cdev) | |||
| 1157 | EXPORT_SYMBOL_GPL(qdio_free); | 1140 | EXPORT_SYMBOL_GPL(qdio_free); |
| 1158 | 1141 | ||
| 1159 | /** | 1142 | /** |
| 1160 | * qdio_initialize - allocate and establish queues for a qdio subchannel | ||
| 1161 | * @init_data: initialization data | ||
| 1162 | * | ||
| 1163 | * This function first allocates queues via qdio_allocate() and on success | ||
| 1164 | * establishes them via qdio_establish(). | ||
| 1165 | */ | ||
| 1166 | int qdio_initialize(struct qdio_initialize *init_data) | ||
| 1167 | { | ||
| 1168 | int rc; | ||
| 1169 | |||
| 1170 | rc = qdio_allocate(init_data); | ||
| 1171 | if (rc) | ||
| 1172 | return rc; | ||
| 1173 | |||
| 1174 | rc = qdio_establish(init_data); | ||
| 1175 | if (rc) | ||
| 1176 | qdio_free(init_data->cdev); | ||
| 1177 | return rc; | ||
| 1178 | } | ||
| 1179 | EXPORT_SYMBOL_GPL(qdio_initialize); | ||
| 1180 | |||
| 1181 | /** | ||
| 1182 | * qdio_allocate - allocate qdio queues and associated data | 1143 | * qdio_allocate - allocate qdio queues and associated data |
| 1183 | * @init_data: initialization data | 1144 | * @init_data: initialization data |
| 1184 | */ | 1145 | */ |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 7f4a75465140..6326b67c45d2 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
| @@ -106,10 +106,12 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs | |||
| 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, | 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, |
| 107 | qdio_handler_t *handler, int i) | 107 | qdio_handler_t *handler, int i) |
| 108 | { | 108 | { |
| 109 | /* must be cleared by every qdio_establish */ | 109 | struct slib *slib = q->slib; |
| 110 | memset(q, 0, ((char *)&q->slib) - ((char *)q)); | ||
| 111 | memset(q->slib, 0, PAGE_SIZE); | ||
| 112 | 110 | ||
| 111 | /* queue must be cleared for qdio_establish */ | ||
| 112 | memset(q, 0, sizeof(*q)); | ||
| 113 | memset(slib, 0, PAGE_SIZE); | ||
| 114 | q->slib = slib; | ||
| 113 | q->irq_ptr = irq_ptr; | 115 | q->irq_ptr = irq_ptr; |
| 114 | q->mask = 1 << (31 - i); | 116 | q->mask = 1 << (31 - i); |
| 115 | q->nr = i; | 117 | q->nr = i; |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index ce5f8910ff83..8daf1b99f153 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
| @@ -95,7 +95,7 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
| 95 | for_each_input_queue(irq_ptr, q, i) | 95 | for_each_input_queue(irq_ptr, q, i) |
| 96 | list_add_rcu(&q->entry, &tiq_list); | 96 | list_add_rcu(&q->entry, &tiq_list); |
| 97 | mutex_unlock(&tiq_list_lock); | 97 | mutex_unlock(&tiq_list_lock); |
| 98 | xchg(irq_ptr->dsci, 1); | 98 | xchg(irq_ptr->dsci, 1 << 7); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) |
| @@ -173,7 +173,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) | |||
| 173 | 173 | ||
| 174 | /* prevent racing */ | 174 | /* prevent racing */ |
| 175 | if (*tiqdio_alsi) | 175 | if (*tiqdio_alsi) |
| 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); | 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7); |
| 177 | } | 177 | } |
| 178 | } | 178 | } |
| 179 | 179 | ||
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 304caf549973..41e0aaefafd5 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
| @@ -302,7 +302,7 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf, | |||
| 302 | static int zcrypt_open(struct inode *inode, struct file *filp) | 302 | static int zcrypt_open(struct inode *inode, struct file *filp) |
| 303 | { | 303 | { |
| 304 | atomic_inc(&zcrypt_open_count); | 304 | atomic_inc(&zcrypt_open_count); |
| 305 | return 0; | 305 | return nonseekable_open(inode, filp); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /** | 308 | /** |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3ba738b2e271..28f71349fdec 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
| @@ -1292,13 +1292,14 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) | |||
| 1292 | QETH_QDIO_CLEANING)) { | 1292 | QETH_QDIO_CLEANING)) { |
| 1293 | case QETH_QDIO_ESTABLISHED: | 1293 | case QETH_QDIO_ESTABLISHED: |
| 1294 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1294 | if (card->info.type == QETH_CARD_TYPE_IQD) |
| 1295 | rc = qdio_cleanup(CARD_DDEV(card), | 1295 | rc = qdio_shutdown(CARD_DDEV(card), |
| 1296 | QDIO_FLAG_CLEANUP_USING_HALT); | 1296 | QDIO_FLAG_CLEANUP_USING_HALT); |
| 1297 | else | 1297 | else |
| 1298 | rc = qdio_cleanup(CARD_DDEV(card), | 1298 | rc = qdio_shutdown(CARD_DDEV(card), |
| 1299 | QDIO_FLAG_CLEANUP_USING_CLEAR); | 1299 | QDIO_FLAG_CLEANUP_USING_CLEAR); |
| 1300 | if (rc) | 1300 | if (rc) |
| 1301 | QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); | 1301 | QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); |
| 1302 | qdio_free(CARD_DDEV(card)); | ||
| 1302 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | 1303 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 1303 | break; | 1304 | break; |
| 1304 | case QETH_QDIO_CLEANING: | 1305 | case QETH_QDIO_CLEANING: |
| @@ -3810,10 +3811,18 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
| 3810 | 3811 | ||
| 3811 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, | 3812 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, |
| 3812 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { | 3813 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { |
| 3813 | rc = qdio_initialize(&init_data); | 3814 | rc = qdio_allocate(&init_data); |
| 3814 | if (rc) | 3815 | if (rc) { |
| 3816 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | ||
| 3817 | goto out; | ||
| 3818 | } | ||
| 3819 | rc = qdio_establish(&init_data); | ||
| 3820 | if (rc) { | ||
| 3815 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | 3821 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 3822 | qdio_free(CARD_DDEV(card)); | ||
| 3823 | } | ||
| 3816 | } | 3824 | } |
| 3825 | out: | ||
| 3817 | kfree(out_sbal_ptrs); | 3826 | kfree(out_sbal_ptrs); |
| 3818 | kfree(in_sbal_ptrs); | 3827 | kfree(in_sbal_ptrs); |
| 3819 | kfree(qib_param_field); | 3828 | kfree(qib_param_field); |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 25d9e0ae9c57..1a2db0a35737 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
| @@ -254,6 +254,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static const struct file_operations zfcp_cfdc_fops = { | 256 | static const struct file_operations zfcp_cfdc_fops = { |
| 257 | .open = nonseekable_open, | ||
| 257 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, | 258 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, |
| 258 | #ifdef CONFIG_COMPAT | 259 | #ifdef CONFIG_COMPAT |
| 259 | .compat_ioctl = zfcp_cfdc_dev_ioctl | 260 | .compat_ioctl = zfcp_cfdc_dev_ioctl |
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 105449c15fa9..e17764d71476 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c | |||
| @@ -69,6 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { | |||
| 69 | }, | 69 | }, |
| 70 | { 0 } | 70 | { 0 } |
| 71 | }; | 71 | }; |
| 72 | MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); | ||
| 72 | 73 | ||
| 73 | static int __devinit zorro7xx_init_one(struct zorro_dev *z, | 74 | static int __devinit zorro7xx_init_one(struct zorro_dev *z, |
| 74 | const struct zorro_device_id *ent) | 75 | const struct zorro_device_id *ent) |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f55c49475a8c..5f3f03df92e3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -518,12 +518,13 @@ config SERIAL_S3C2412 | |||
| 518 | Serial port support for the Samsung S3C2412 and S3C2413 SoC | 518 | Serial port support for the Samsung S3C2412 and S3C2413 SoC |
| 519 | 519 | ||
| 520 | config SERIAL_S3C2440 | 520 | config SERIAL_S3C2440 |
| 521 | tristate "Samsung S3C2440/S3C2442 Serial port support" | 521 | tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support" |
| 522 | depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442) | 522 | depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416) |
| 523 | default y if CPU_S3C2440 | 523 | default y if CPU_S3C2440 |
| 524 | default y if CPU_S3C2442 | 524 | default y if CPU_S3C2442 |
| 525 | select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416 | ||
| 525 | help | 526 | help |
| 526 | Serial port support for the Samsung S3C2440 and S3C2442 SoC | 527 | Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC |
| 527 | 528 | ||
| 528 | config SERIAL_S3C24A0 | 529 | config SERIAL_S3C24A0 |
| 529 | tristate "Samsung S3C24A0 Serial port support" | 530 | tristate "Samsung S3C24A0 Serial port support" |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 2c9bf9b68327..eed3c2d8dd1c 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
| 39 | #include <linux/atmel_pdc.h> | 39 | #include <linux/atmel_pdc.h> |
| 40 | #include <linux/atmel_serial.h> | 40 | #include <linux/atmel_serial.h> |
| 41 | #include <linux/uaccess.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 43 | 44 | ||
| @@ -59,6 +60,9 @@ | |||
| 59 | 60 | ||
| 60 | #include <linux/serial_core.h> | 61 | #include <linux/serial_core.h> |
| 61 | 62 | ||
| 63 | static void atmel_start_rx(struct uart_port *port); | ||
| 64 | static void atmel_stop_rx(struct uart_port *port); | ||
| 65 | |||
| 62 | #ifdef CONFIG_SERIAL_ATMEL_TTYAT | 66 | #ifdef CONFIG_SERIAL_ATMEL_TTYAT |
| 63 | 67 | ||
| 64 | /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we | 68 | /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we |
| @@ -93,6 +97,7 @@ | |||
| 93 | #define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR) | 97 | #define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR) |
| 94 | #define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) | 98 | #define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) |
| 95 | #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) | 99 | #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) |
| 100 | #define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR) | ||
| 96 | 101 | ||
| 97 | /* PDC registers */ | 102 | /* PDC registers */ |
| 98 | #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) | 103 | #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) |
| @@ -147,6 +152,9 @@ struct atmel_uart_port { | |||
| 147 | unsigned int irq_status_prev; | 152 | unsigned int irq_status_prev; |
| 148 | 153 | ||
| 149 | struct circ_buf rx_ring; | 154 | struct circ_buf rx_ring; |
| 155 | |||
| 156 | struct serial_rs485 rs485; /* rs485 settings */ | ||
| 157 | unsigned int tx_done_mask; | ||
| 150 | }; | 158 | }; |
| 151 | 159 | ||
| 152 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 160 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
| @@ -187,6 +195,46 @@ static bool atmel_use_dma_tx(struct uart_port *port) | |||
| 187 | } | 195 | } |
| 188 | #endif | 196 | #endif |
| 189 | 197 | ||
| 198 | /* Enable or disable the rs485 support */ | ||
| 199 | void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | ||
| 200 | { | ||
| 201 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 202 | unsigned int mode; | ||
| 203 | |||
| 204 | spin_lock(&port->lock); | ||
| 205 | |||
| 206 | /* Disable interrupts */ | ||
| 207 | UART_PUT_IDR(port, atmel_port->tx_done_mask); | ||
| 208 | |||
| 209 | mode = UART_GET_MR(port); | ||
| 210 | |||
| 211 | /* Resetting serial mode to RS232 (0x0) */ | ||
| 212 | mode &= ~ATMEL_US_USMODE; | ||
| 213 | |||
| 214 | atmel_port->rs485 = *rs485conf; | ||
| 215 | |||
| 216 | if (rs485conf->flags & SER_RS485_ENABLED) { | ||
| 217 | dev_dbg(port->dev, "Setting UART to RS485\n"); | ||
| 218 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | ||
| 219 | UART_PUT_TTGR(port, rs485conf->delay_rts_before_send); | ||
| 220 | mode |= ATMEL_US_USMODE_RS485; | ||
| 221 | } else { | ||
| 222 | dev_dbg(port->dev, "Setting UART to RS232\n"); | ||
| 223 | if (atmel_use_dma_tx(port)) | ||
| 224 | atmel_port->tx_done_mask = ATMEL_US_ENDTX | | ||
| 225 | ATMEL_US_TXBUFE; | ||
| 226 | else | ||
| 227 | atmel_port->tx_done_mask = ATMEL_US_TXRDY; | ||
| 228 | } | ||
| 229 | UART_PUT_MR(port, mode); | ||
| 230 | |||
| 231 | /* Enable interrupts */ | ||
| 232 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 233 | |||
| 234 | spin_unlock(&port->lock); | ||
| 235 | |||
| 236 | } | ||
| 237 | |||
| 190 | /* | 238 | /* |
| 191 | * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. | 239 | * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. |
| 192 | */ | 240 | */ |
| @@ -202,6 +250,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
| 202 | { | 250 | { |
| 203 | unsigned int control = 0; | 251 | unsigned int control = 0; |
| 204 | unsigned int mode; | 252 | unsigned int mode; |
| 253 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 205 | 254 | ||
| 206 | #ifdef CONFIG_ARCH_AT91RM9200 | 255 | #ifdef CONFIG_ARCH_AT91RM9200 |
| 207 | if (cpu_is_at91rm9200()) { | 256 | if (cpu_is_at91rm9200()) { |
| @@ -236,6 +285,17 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
| 236 | mode |= ATMEL_US_CHMODE_LOC_LOOP; | 285 | mode |= ATMEL_US_CHMODE_LOC_LOOP; |
| 237 | else | 286 | else |
| 238 | mode |= ATMEL_US_CHMODE_NORMAL; | 287 | mode |= ATMEL_US_CHMODE_NORMAL; |
| 288 | |||
| 289 | /* Resetting serial mode to RS232 (0x0) */ | ||
| 290 | mode &= ~ATMEL_US_USMODE; | ||
| 291 | |||
| 292 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | ||
| 293 | dev_dbg(port->dev, "Setting UART to RS485\n"); | ||
| 294 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | ||
| 295 | mode |= ATMEL_US_USMODE_RS485; | ||
| 296 | } else { | ||
| 297 | dev_dbg(port->dev, "Setting UART to RS232\n"); | ||
| 298 | } | ||
| 239 | UART_PUT_MR(port, mode); | 299 | UART_PUT_MR(port, mode); |
| 240 | } | 300 | } |
| 241 | 301 | ||
| @@ -268,12 +328,17 @@ static u_int atmel_get_mctrl(struct uart_port *port) | |||
| 268 | */ | 328 | */ |
| 269 | static void atmel_stop_tx(struct uart_port *port) | 329 | static void atmel_stop_tx(struct uart_port *port) |
| 270 | { | 330 | { |
| 331 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 332 | |||
| 271 | if (atmel_use_dma_tx(port)) { | 333 | if (atmel_use_dma_tx(port)) { |
| 272 | /* disable PDC transmit */ | 334 | /* disable PDC transmit */ |
| 273 | UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); | 335 | UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); |
| 274 | UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 336 | } |
| 275 | } else | 337 | /* Disable interrupts */ |
| 276 | UART_PUT_IDR(port, ATMEL_US_TXRDY); | 338 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
| 339 | |||
| 340 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | ||
| 341 | atmel_start_rx(port); | ||
| 277 | } | 342 | } |
| 278 | 343 | ||
| 279 | /* | 344 | /* |
| @@ -281,17 +346,39 @@ static void atmel_stop_tx(struct uart_port *port) | |||
| 281 | */ | 346 | */ |
| 282 | static void atmel_start_tx(struct uart_port *port) | 347 | static void atmel_start_tx(struct uart_port *port) |
| 283 | { | 348 | { |
| 349 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 350 | |||
| 284 | if (atmel_use_dma_tx(port)) { | 351 | if (atmel_use_dma_tx(port)) { |
| 285 | if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) | 352 | if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) |
| 286 | /* The transmitter is already running. Yes, we | 353 | /* The transmitter is already running. Yes, we |
| 287 | really need this.*/ | 354 | really need this.*/ |
| 288 | return; | 355 | return; |
| 289 | 356 | ||
| 290 | UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 357 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) |
| 358 | atmel_stop_rx(port); | ||
| 359 | |||
| 291 | /* re-enable PDC transmit */ | 360 | /* re-enable PDC transmit */ |
| 292 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); | 361 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); |
| 293 | } else | 362 | } |
| 294 | UART_PUT_IER(port, ATMEL_US_TXRDY); | 363 | /* Enable interrupts */ |
| 364 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 365 | } | ||
| 366 | |||
| 367 | /* | ||
| 368 | * start receiving - port is in process of being opened. | ||
| 369 | */ | ||
| 370 | static void atmel_start_rx(struct uart_port *port) | ||
| 371 | { | ||
| 372 | UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */ | ||
| 373 | |||
| 374 | if (atmel_use_dma_rx(port)) { | ||
| 375 | /* enable PDC controller */ | ||
| 376 | UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | | ||
| 377 | port->read_status_mask); | ||
| 378 | UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); | ||
| 379 | } else { | ||
| 380 | UART_PUT_IER(port, ATMEL_US_RXRDY); | ||
| 381 | } | ||
| 295 | } | 382 | } |
| 296 | 383 | ||
| 297 | /* | 384 | /* |
| @@ -302,9 +389,11 @@ static void atmel_stop_rx(struct uart_port *port) | |||
| 302 | if (atmel_use_dma_rx(port)) { | 389 | if (atmel_use_dma_rx(port)) { |
| 303 | /* disable PDC receive */ | 390 | /* disable PDC receive */ |
| 304 | UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); | 391 | UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); |
| 305 | UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); | 392 | UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | |
| 306 | } else | 393 | port->read_status_mask); |
| 394 | } else { | ||
| 307 | UART_PUT_IDR(port, ATMEL_US_RXRDY); | 395 | UART_PUT_IDR(port, ATMEL_US_RXRDY); |
| 396 | } | ||
| 308 | } | 397 | } |
| 309 | 398 | ||
| 310 | /* | 399 | /* |
| @@ -428,8 +517,9 @@ static void atmel_rx_chars(struct uart_port *port) | |||
| 428 | static void atmel_tx_chars(struct uart_port *port) | 517 | static void atmel_tx_chars(struct uart_port *port) |
| 429 | { | 518 | { |
| 430 | struct circ_buf *xmit = &port->state->xmit; | 519 | struct circ_buf *xmit = &port->state->xmit; |
| 520 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 431 | 521 | ||
| 432 | if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) { | 522 | if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) { |
| 433 | UART_PUT_CHAR(port, port->x_char); | 523 | UART_PUT_CHAR(port, port->x_char); |
| 434 | port->icount.tx++; | 524 | port->icount.tx++; |
| 435 | port->x_char = 0; | 525 | port->x_char = 0; |
| @@ -437,7 +527,7 @@ static void atmel_tx_chars(struct uart_port *port) | |||
| 437 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | 527 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) |
| 438 | return; | 528 | return; |
| 439 | 529 | ||
| 440 | while (UART_GET_CSR(port) & ATMEL_US_TXRDY) { | 530 | while (UART_GET_CSR(port) & atmel_port->tx_done_mask) { |
| 441 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); | 531 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); |
| 442 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 532 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| 443 | port->icount.tx++; | 533 | port->icount.tx++; |
| @@ -449,7 +539,8 @@ static void atmel_tx_chars(struct uart_port *port) | |||
| 449 | uart_write_wakeup(port); | 539 | uart_write_wakeup(port); |
| 450 | 540 | ||
| 451 | if (!uart_circ_empty(xmit)) | 541 | if (!uart_circ_empty(xmit)) |
| 452 | UART_PUT_IER(port, ATMEL_US_TXRDY); | 542 | /* Enable interrupts */ |
| 543 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 453 | } | 544 | } |
| 454 | 545 | ||
| 455 | /* | 546 | /* |
| @@ -501,18 +592,10 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) | |||
| 501 | { | 592 | { |
| 502 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 593 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
| 503 | 594 | ||
| 504 | if (atmel_use_dma_tx(port)) { | 595 | if (pending & atmel_port->tx_done_mask) { |
| 505 | /* PDC transmit */ | 596 | /* Either PDC or interrupt transmission */ |
| 506 | if (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) { | 597 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
| 507 | UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 598 | tasklet_schedule(&atmel_port->tasklet); |
| 508 | tasklet_schedule(&atmel_port->tasklet); | ||
| 509 | } | ||
| 510 | } else { | ||
| 511 | /* Interrupt transmit */ | ||
| 512 | if (pending & ATMEL_US_TXRDY) { | ||
| 513 | UART_PUT_IDR(port, ATMEL_US_TXRDY); | ||
| 514 | tasklet_schedule(&atmel_port->tasklet); | ||
| 515 | } | ||
| 516 | } | 599 | } |
| 517 | } | 600 | } |
| 518 | 601 | ||
| @@ -590,9 +673,15 @@ static void atmel_tx_dma(struct uart_port *port) | |||
| 590 | 673 | ||
| 591 | UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); | 674 | UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); |
| 592 | UART_PUT_TCR(port, count); | 675 | UART_PUT_TCR(port, count); |
| 593 | /* re-enable PDC transmit and interrupts */ | 676 | /* re-enable PDC transmit */ |
| 594 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); | 677 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); |
| 595 | UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 678 | /* Enable interrupts */ |
| 679 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 680 | } else { | ||
| 681 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | ||
| 682 | /* DMA done, stop TX, start RX for RS485 */ | ||
| 683 | atmel_start_rx(port); | ||
| 684 | } | ||
| 596 | } | 685 | } |
| 597 | 686 | ||
| 598 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 687 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| @@ -1017,6 +1106,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1017 | { | 1106 | { |
| 1018 | unsigned long flags; | 1107 | unsigned long flags; |
| 1019 | unsigned int mode, imr, quot, baud; | 1108 | unsigned int mode, imr, quot, baud; |
| 1109 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 1020 | 1110 | ||
| 1021 | /* Get current mode register */ | 1111 | /* Get current mode register */ |
| 1022 | mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | 1112 | mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL |
| @@ -1115,6 +1205,17 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1115 | /* disable receiver and transmitter */ | 1205 | /* disable receiver and transmitter */ |
| 1116 | UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); | 1206 | UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); |
| 1117 | 1207 | ||
| 1208 | /* Resetting serial mode to RS232 (0x0) */ | ||
| 1209 | mode &= ~ATMEL_US_USMODE; | ||
| 1210 | |||
| 1211 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | ||
| 1212 | dev_dbg(port->dev, "Setting UART to RS485\n"); | ||
| 1213 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | ||
| 1214 | mode |= ATMEL_US_USMODE_RS485; | ||
| 1215 | } else { | ||
| 1216 | dev_dbg(port->dev, "Setting UART to RS232\n"); | ||
| 1217 | } | ||
| 1218 | |||
| 1118 | /* set the parity, stop bits and data size */ | 1219 | /* set the parity, stop bits and data size */ |
| 1119 | UART_PUT_MR(port, mode); | 1220 | UART_PUT_MR(port, mode); |
| 1120 | 1221 | ||
| @@ -1231,6 +1332,35 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) | |||
| 1231 | } | 1332 | } |
| 1232 | #endif | 1333 | #endif |
| 1233 | 1334 | ||
| 1335 | static int | ||
| 1336 | atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) | ||
| 1337 | { | ||
| 1338 | struct serial_rs485 rs485conf; | ||
| 1339 | |||
| 1340 | switch (cmd) { | ||
| 1341 | case TIOCSRS485: | ||
| 1342 | if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg, | ||
| 1343 | sizeof(rs485conf))) | ||
| 1344 | return -EFAULT; | ||
| 1345 | |||
| 1346 | atmel_config_rs485(port, &rs485conf); | ||
| 1347 | break; | ||
| 1348 | |||
| 1349 | case TIOCGRS485: | ||
| 1350 | if (copy_to_user((struct serial_rs485 *) arg, | ||
| 1351 | &(to_atmel_uart_port(port)->rs485), | ||
| 1352 | sizeof(rs485conf))) | ||
| 1353 | return -EFAULT; | ||
| 1354 | break; | ||
| 1355 | |||
| 1356 | default: | ||
| 1357 | return -ENOIOCTLCMD; | ||
| 1358 | } | ||
| 1359 | return 0; | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | |||
| 1363 | |||
| 1234 | static struct uart_ops atmel_pops = { | 1364 | static struct uart_ops atmel_pops = { |
| 1235 | .tx_empty = atmel_tx_empty, | 1365 | .tx_empty = atmel_tx_empty, |
| 1236 | .set_mctrl = atmel_set_mctrl, | 1366 | .set_mctrl = atmel_set_mctrl, |
| @@ -1250,6 +1380,7 @@ static struct uart_ops atmel_pops = { | |||
| 1250 | .config_port = atmel_config_port, | 1380 | .config_port = atmel_config_port, |
| 1251 | .verify_port = atmel_verify_port, | 1381 | .verify_port = atmel_verify_port, |
| 1252 | .pm = atmel_serial_pm, | 1382 | .pm = atmel_serial_pm, |
| 1383 | .ioctl = atmel_ioctl, | ||
| 1253 | #ifdef CONFIG_CONSOLE_POLL | 1384 | #ifdef CONFIG_CONSOLE_POLL |
| 1254 | .poll_get_char = atmel_poll_get_char, | 1385 | .poll_get_char = atmel_poll_get_char, |
| 1255 | .poll_put_char = atmel_poll_put_char, | 1386 | .poll_put_char = atmel_poll_put_char, |
| @@ -1265,13 +1396,12 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
| 1265 | struct uart_port *port = &atmel_port->uart; | 1396 | struct uart_port *port = &atmel_port->uart; |
| 1266 | struct atmel_uart_data *data = pdev->dev.platform_data; | 1397 | struct atmel_uart_data *data = pdev->dev.platform_data; |
| 1267 | 1398 | ||
| 1268 | port->iotype = UPIO_MEM; | 1399 | port->iotype = UPIO_MEM; |
| 1269 | port->flags = UPF_BOOT_AUTOCONF; | 1400 | port->flags = UPF_BOOT_AUTOCONF; |
| 1270 | port->ops = &atmel_pops; | 1401 | port->ops = &atmel_pops; |
| 1271 | port->fifosize = 1; | 1402 | port->fifosize = 1; |
| 1272 | port->line = pdev->id; | 1403 | port->line = pdev->id; |
| 1273 | port->dev = &pdev->dev; | 1404 | port->dev = &pdev->dev; |
| 1274 | |||
| 1275 | port->mapbase = pdev->resource[0].start; | 1405 | port->mapbase = pdev->resource[0].start; |
| 1276 | port->irq = pdev->resource[1].start; | 1406 | port->irq = pdev->resource[1].start; |
| 1277 | 1407 | ||
| @@ -1299,8 +1429,16 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
| 1299 | 1429 | ||
| 1300 | atmel_port->use_dma_rx = data->use_dma_rx; | 1430 | atmel_port->use_dma_rx = data->use_dma_rx; |
| 1301 | atmel_port->use_dma_tx = data->use_dma_tx; | 1431 | atmel_port->use_dma_tx = data->use_dma_tx; |
| 1302 | if (atmel_use_dma_tx(port)) | 1432 | atmel_port->rs485 = data->rs485; |
| 1433 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ | ||
| 1434 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | ||
| 1435 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | ||
| 1436 | else if (atmel_use_dma_tx(port)) { | ||
| 1303 | port->fifosize = PDC_BUFFER_SIZE; | 1437 | port->fifosize = PDC_BUFFER_SIZE; |
| 1438 | atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE; | ||
| 1439 | } else { | ||
| 1440 | atmel_port->tx_done_mask = ATMEL_US_TXRDY; | ||
| 1441 | } | ||
| 1304 | } | 1442 | } |
| 1305 | 1443 | ||
| 1306 | /* | 1444 | /* |
| @@ -1334,6 +1472,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch) | |||
| 1334 | static void atmel_console_write(struct console *co, const char *s, u_int count) | 1472 | static void atmel_console_write(struct console *co, const char *s, u_int count) |
| 1335 | { | 1473 | { |
| 1336 | struct uart_port *port = &atmel_ports[co->index].uart; | 1474 | struct uart_port *port = &atmel_ports[co->index].uart; |
| 1475 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 1337 | unsigned int status, imr; | 1476 | unsigned int status, imr; |
| 1338 | unsigned int pdc_tx; | 1477 | unsigned int pdc_tx; |
| 1339 | 1478 | ||
| @@ -1341,7 +1480,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) | |||
| 1341 | * First, save IMR and then disable interrupts | 1480 | * First, save IMR and then disable interrupts |
| 1342 | */ | 1481 | */ |
| 1343 | imr = UART_GET_IMR(port); | 1482 | imr = UART_GET_IMR(port); |
| 1344 | UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY); | 1483 | UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask); |
| 1345 | 1484 | ||
| 1346 | /* Store PDC transmit status and disable it */ | 1485 | /* Store PDC transmit status and disable it */ |
| 1347 | pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; | 1486 | pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 8eb094c1f61b..8d993c4cceac 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -83,16 +83,16 @@ struct sci_port { | |||
| 83 | 83 | ||
| 84 | /* Interface clock */ | 84 | /* Interface clock */ |
| 85 | struct clk *iclk; | 85 | struct clk *iclk; |
| 86 | /* Data clock */ | 86 | /* Function clock */ |
| 87 | struct clk *dclk; | 87 | struct clk *fclk; |
| 88 | 88 | ||
| 89 | struct list_head node; | 89 | struct list_head node; |
| 90 | struct dma_chan *chan_tx; | 90 | struct dma_chan *chan_tx; |
| 91 | struct dma_chan *chan_rx; | 91 | struct dma_chan *chan_rx; |
| 92 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 92 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 93 | struct device *dma_dev; | 93 | struct device *dma_dev; |
| 94 | enum sh_dmae_slave_chan_id slave_tx; | 94 | unsigned int slave_tx; |
| 95 | enum sh_dmae_slave_chan_id slave_rx; | 95 | unsigned int slave_rx; |
| 96 | struct dma_async_tx_descriptor *desc_tx; | 96 | struct dma_async_tx_descriptor *desc_tx; |
| 97 | struct dma_async_tx_descriptor *desc_rx[2]; | 97 | struct dma_async_tx_descriptor *desc_rx[2]; |
| 98 | dma_cookie_t cookie_tx; | 98 | dma_cookie_t cookie_tx; |
| @@ -107,6 +107,7 @@ struct sci_port { | |||
| 107 | struct work_struct work_tx; | 107 | struct work_struct work_tx; |
| 108 | struct work_struct work_rx; | 108 | struct work_struct work_rx; |
| 109 | struct timer_list rx_timer; | 109 | struct timer_list rx_timer; |
| 110 | unsigned int rx_timeout; | ||
| 110 | #endif | 111 | #endif |
| 111 | }; | 112 | }; |
| 112 | 113 | ||
| @@ -674,22 +675,22 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
| 674 | struct sci_port *s = to_sci_port(port); | 675 | struct sci_port *s = to_sci_port(port); |
| 675 | 676 | ||
| 676 | if (s->chan_rx) { | 677 | if (s->chan_rx) { |
| 677 | unsigned long tout; | ||
| 678 | u16 scr = sci_in(port, SCSCR); | 678 | u16 scr = sci_in(port, SCSCR); |
| 679 | u16 ssr = sci_in(port, SCxSR); | 679 | u16 ssr = sci_in(port, SCxSR); |
| 680 | 680 | ||
| 681 | /* Disable future Rx interrupts */ | 681 | /* Disable future Rx interrupts */ |
| 682 | sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE); | 682 | if (port->type == PORT_SCIFA) { |
| 683 | disable_irq_nosync(irq); | ||
| 684 | scr |= 0x4000; | ||
| 685 | } else { | ||
| 686 | scr &= ~SCI_CTRL_FLAGS_RIE; | ||
| 687 | } | ||
| 688 | sci_out(port, SCSCR, scr); | ||
| 683 | /* Clear current interrupt */ | 689 | /* Clear current interrupt */ |
| 684 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); | 690 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); |
| 685 | /* Calculate delay for 1.5 DMA buffers */ | 691 | dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", |
| 686 | tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | 692 | jiffies, s->rx_timeout); |
| 687 | port->fifosize / 2; | 693 | mod_timer(&s->rx_timer, jiffies + s->rx_timeout); |
| 688 | dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n", | ||
| 689 | tout * 1000 / HZ); | ||
| 690 | if (tout < 2) | ||
| 691 | tout = 2; | ||
| 692 | mod_timer(&s->rx_timer, jiffies + tout); | ||
| 693 | 694 | ||
| 694 | return IRQ_HANDLED; | 695 | return IRQ_HANDLED; |
| 695 | } | 696 | } |
| @@ -799,7 +800,7 @@ static int sci_notifier(struct notifier_block *self, | |||
| 799 | (phase == CPUFREQ_RESUMECHANGE)) { | 800 | (phase == CPUFREQ_RESUMECHANGE)) { |
| 800 | spin_lock_irqsave(&priv->lock, flags); | 801 | spin_lock_irqsave(&priv->lock, flags); |
| 801 | list_for_each_entry(sci_port, &priv->ports, node) | 802 | list_for_each_entry(sci_port, &priv->ports, node) |
| 802 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | 803 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
| 803 | spin_unlock_irqrestore(&priv->lock, flags); | 804 | spin_unlock_irqrestore(&priv->lock, flags); |
| 804 | } | 805 | } |
| 805 | 806 | ||
| @@ -810,21 +811,17 @@ static void sci_clk_enable(struct uart_port *port) | |||
| 810 | { | 811 | { |
| 811 | struct sci_port *sci_port = to_sci_port(port); | 812 | struct sci_port *sci_port = to_sci_port(port); |
| 812 | 813 | ||
| 813 | clk_enable(sci_port->dclk); | 814 | clk_enable(sci_port->iclk); |
| 814 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | 815 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
| 815 | 816 | clk_enable(sci_port->fclk); | |
| 816 | if (sci_port->iclk) | ||
| 817 | clk_enable(sci_port->iclk); | ||
| 818 | } | 817 | } |
| 819 | 818 | ||
| 820 | static void sci_clk_disable(struct uart_port *port) | 819 | static void sci_clk_disable(struct uart_port *port) |
| 821 | { | 820 | { |
| 822 | struct sci_port *sci_port = to_sci_port(port); | 821 | struct sci_port *sci_port = to_sci_port(port); |
| 823 | 822 | ||
| 824 | if (sci_port->iclk) | 823 | clk_disable(sci_port->fclk); |
| 825 | clk_disable(sci_port->iclk); | 824 | clk_disable(sci_port->iclk); |
| 826 | |||
| 827 | clk_disable(sci_port->dclk); | ||
| 828 | } | 825 | } |
| 829 | 826 | ||
| 830 | static int sci_request_irq(struct sci_port *port) | 827 | static int sci_request_irq(struct sci_port *port) |
| @@ -913,22 +910,26 @@ static void sci_dma_tx_complete(void *arg) | |||
| 913 | 910 | ||
| 914 | spin_lock_irqsave(&port->lock, flags); | 911 | spin_lock_irqsave(&port->lock, flags); |
| 915 | 912 | ||
| 916 | xmit->tail += s->sg_tx.length; | 913 | xmit->tail += sg_dma_len(&s->sg_tx); |
| 917 | xmit->tail &= UART_XMIT_SIZE - 1; | 914 | xmit->tail &= UART_XMIT_SIZE - 1; |
| 918 | 915 | ||
| 919 | port->icount.tx += s->sg_tx.length; | 916 | port->icount.tx += sg_dma_len(&s->sg_tx); |
| 920 | 917 | ||
| 921 | async_tx_ack(s->desc_tx); | 918 | async_tx_ack(s->desc_tx); |
| 922 | s->cookie_tx = -EINVAL; | 919 | s->cookie_tx = -EINVAL; |
| 923 | s->desc_tx = NULL; | 920 | s->desc_tx = NULL; |
| 924 | 921 | ||
| 925 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 926 | |||
| 927 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 922 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 928 | uart_write_wakeup(port); | 923 | uart_write_wakeup(port); |
| 929 | 924 | ||
| 930 | if (uart_circ_chars_pending(xmit)) | 925 | if (!uart_circ_empty(xmit)) { |
| 931 | schedule_work(&s->work_tx); | 926 | schedule_work(&s->work_tx); |
| 927 | } else if (port->type == PORT_SCIFA) { | ||
| 928 | u16 ctrl = sci_in(port, SCSCR); | ||
| 929 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | ||
| 930 | } | ||
| 931 | |||
| 932 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 932 | } | 933 | } |
| 933 | 934 | ||
| 934 | /* Locking: called with port lock held */ | 935 | /* Locking: called with port lock held */ |
| @@ -972,13 +973,13 @@ static void sci_dma_rx_complete(void *arg) | |||
| 972 | unsigned long flags; | 973 | unsigned long flags; |
| 973 | int count; | 974 | int count; |
| 974 | 975 | ||
| 975 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | 976 | dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx); |
| 976 | 977 | ||
| 977 | spin_lock_irqsave(&port->lock, flags); | 978 | spin_lock_irqsave(&port->lock, flags); |
| 978 | 979 | ||
| 979 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); | 980 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); |
| 980 | 981 | ||
| 981 | mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5)); | 982 | mod_timer(&s->rx_timer, jiffies + s->rx_timeout); |
| 982 | 983 | ||
| 983 | spin_unlock_irqrestore(&port->lock, flags); | 984 | spin_unlock_irqrestore(&port->lock, flags); |
| 984 | 985 | ||
| @@ -1050,6 +1051,8 @@ static void sci_submit_rx(struct sci_port *s) | |||
| 1050 | sci_rx_dma_release(s, true); | 1051 | sci_rx_dma_release(s, true); |
| 1051 | return; | 1052 | return; |
| 1052 | } | 1053 | } |
| 1054 | dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__, | ||
| 1055 | s->cookie_rx[i], i); | ||
| 1053 | } | 1056 | } |
| 1054 | 1057 | ||
| 1055 | s->active_rx = s->cookie_rx[0]; | 1058 | s->active_rx = s->cookie_rx[0]; |
| @@ -1107,10 +1110,10 @@ static void work_fn_rx(struct work_struct *work) | |||
| 1107 | return; | 1110 | return; |
| 1108 | } | 1111 | } |
| 1109 | 1112 | ||
| 1110 | dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__, | ||
| 1111 | s->cookie_rx[new], new); | ||
| 1112 | |||
| 1113 | s->active_rx = s->cookie_rx[!new]; | 1113 | s->active_rx = s->cookie_rx[!new]; |
| 1114 | |||
| 1115 | dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__, | ||
| 1116 | s->cookie_rx[new], new, s->active_rx); | ||
| 1114 | } | 1117 | } |
| 1115 | 1118 | ||
| 1116 | static void work_fn_tx(struct work_struct *work) | 1119 | static void work_fn_tx(struct work_struct *work) |
| @@ -1131,14 +1134,13 @@ static void work_fn_tx(struct work_struct *work) | |||
| 1131 | */ | 1134 | */ |
| 1132 | spin_lock_irq(&port->lock); | 1135 | spin_lock_irq(&port->lock); |
| 1133 | sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); | 1136 | sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); |
| 1134 | sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + | 1137 | sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + |
| 1135 | sg->offset; | 1138 | sg->offset; |
| 1136 | sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), | 1139 | sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), |
| 1137 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); | 1140 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); |
| 1138 | sg->dma_length = sg->length; | ||
| 1139 | spin_unlock_irq(&port->lock); | 1141 | spin_unlock_irq(&port->lock); |
| 1140 | 1142 | ||
| 1141 | BUG_ON(!sg->length); | 1143 | BUG_ON(!sg_dma_len(sg)); |
| 1142 | 1144 | ||
| 1143 | desc = chan->device->device_prep_slave_sg(chan, | 1145 | desc = chan->device->device_prep_slave_sg(chan, |
| 1144 | sg, s->sg_len_tx, DMA_TO_DEVICE, | 1146 | sg, s->sg_len_tx, DMA_TO_DEVICE, |
| @@ -1173,23 +1175,28 @@ static void work_fn_tx(struct work_struct *work) | |||
| 1173 | 1175 | ||
| 1174 | static void sci_start_tx(struct uart_port *port) | 1176 | static void sci_start_tx(struct uart_port *port) |
| 1175 | { | 1177 | { |
| 1178 | struct sci_port *s = to_sci_port(port); | ||
| 1176 | unsigned short ctrl; | 1179 | unsigned short ctrl; |
| 1177 | 1180 | ||
| 1178 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1181 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 1179 | struct sci_port *s = to_sci_port(port); | 1182 | if (port->type == PORT_SCIFA) { |
| 1180 | 1183 | u16 new, scr = sci_in(port, SCSCR); | |
| 1181 | if (s->chan_tx) { | 1184 | if (s->chan_tx) |
| 1182 | if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0) | 1185 | new = scr | 0x8000; |
| 1183 | schedule_work(&s->work_tx); | 1186 | else |
| 1184 | 1187 | new = scr & ~0x8000; | |
| 1185 | return; | 1188 | if (new != scr) |
| 1189 | sci_out(port, SCSCR, new); | ||
| 1186 | } | 1190 | } |
| 1191 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && | ||
| 1192 | s->cookie_tx < 0) | ||
| 1193 | schedule_work(&s->work_tx); | ||
| 1187 | #endif | 1194 | #endif |
| 1188 | 1195 | if (!s->chan_tx || port->type == PORT_SCIFA) { | |
| 1189 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1196 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 1190 | ctrl = sci_in(port, SCSCR); | 1197 | ctrl = sci_in(port, SCSCR); |
| 1191 | ctrl |= SCI_CTRL_FLAGS_TIE; | 1198 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); |
| 1192 | sci_out(port, SCSCR, ctrl); | 1199 | } |
| 1193 | } | 1200 | } |
| 1194 | 1201 | ||
| 1195 | static void sci_stop_tx(struct uart_port *port) | 1202 | static void sci_stop_tx(struct uart_port *port) |
| @@ -1198,6 +1205,8 @@ static void sci_stop_tx(struct uart_port *port) | |||
| 1198 | 1205 | ||
| 1199 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1206 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 1200 | ctrl = sci_in(port, SCSCR); | 1207 | ctrl = sci_in(port, SCSCR); |
| 1208 | if (port->type == PORT_SCIFA) | ||
| 1209 | ctrl &= ~0x8000; | ||
| 1201 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1210 | ctrl &= ~SCI_CTRL_FLAGS_TIE; |
| 1202 | sci_out(port, SCSCR, ctrl); | 1211 | sci_out(port, SCSCR, ctrl); |
| 1203 | } | 1212 | } |
| @@ -1208,6 +1217,8 @@ static void sci_start_rx(struct uart_port *port) | |||
| 1208 | 1217 | ||
| 1209 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | 1218 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ |
| 1210 | ctrl |= sci_in(port, SCSCR); | 1219 | ctrl |= sci_in(port, SCSCR); |
| 1220 | if (port->type == PORT_SCIFA) | ||
| 1221 | ctrl &= ~0x4000; | ||
| 1211 | sci_out(port, SCSCR, ctrl); | 1222 | sci_out(port, SCSCR, ctrl); |
| 1212 | } | 1223 | } |
| 1213 | 1224 | ||
| @@ -1217,6 +1228,8 @@ static void sci_stop_rx(struct uart_port *port) | |||
| 1217 | 1228 | ||
| 1218 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | 1229 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ |
| 1219 | ctrl = sci_in(port, SCSCR); | 1230 | ctrl = sci_in(port, SCSCR); |
| 1231 | if (port->type == PORT_SCIFA) | ||
| 1232 | ctrl &= ~0x4000; | ||
| 1220 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1233 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); |
| 1221 | sci_out(port, SCSCR, ctrl); | 1234 | sci_out(port, SCSCR, ctrl); |
| 1222 | } | 1235 | } |
| @@ -1251,8 +1264,12 @@ static void rx_timer_fn(unsigned long arg) | |||
| 1251 | { | 1264 | { |
| 1252 | struct sci_port *s = (struct sci_port *)arg; | 1265 | struct sci_port *s = (struct sci_port *)arg; |
| 1253 | struct uart_port *port = &s->port; | 1266 | struct uart_port *port = &s->port; |
| 1254 | |||
| 1255 | u16 scr = sci_in(port, SCSCR); | 1267 | u16 scr = sci_in(port, SCSCR); |
| 1268 | |||
| 1269 | if (port->type == PORT_SCIFA) { | ||
| 1270 | scr &= ~0x4000; | ||
| 1271 | enable_irq(s->irqs[1]); | ||
| 1272 | } | ||
| 1256 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); | 1273 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); |
| 1257 | dev_dbg(port->dev, "DMA Rx timed out\n"); | 1274 | dev_dbg(port->dev, "DMA Rx timed out\n"); |
| 1258 | schedule_work(&s->work_rx); | 1275 | schedule_work(&s->work_rx); |
| @@ -1339,8 +1356,7 @@ static void sci_request_dma(struct uart_port *port) | |||
| 1339 | sg_init_table(sg, 1); | 1356 | sg_init_table(sg, 1); |
| 1340 | sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, | 1357 | sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, |
| 1341 | (int)buf[i] & ~PAGE_MASK); | 1358 | (int)buf[i] & ~PAGE_MASK); |
| 1342 | sg->dma_address = dma[i]; | 1359 | sg_dma_address(sg) = dma[i]; |
| 1343 | sg->dma_length = sg->length; | ||
| 1344 | } | 1360 | } |
| 1345 | 1361 | ||
| 1346 | INIT_WORK(&s->work_rx, work_fn_rx); | 1362 | INIT_WORK(&s->work_rx, work_fn_rx); |
| @@ -1403,8 +1419,12 @@ static void sci_shutdown(struct uart_port *port) | |||
| 1403 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 1419 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| 1404 | struct ktermios *old) | 1420 | struct ktermios *old) |
| 1405 | { | 1421 | { |
| 1422 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
| 1423 | struct sci_port *s = to_sci_port(port); | ||
| 1424 | #endif | ||
| 1406 | unsigned int status, baud, smr_val, max_baud; | 1425 | unsigned int status, baud, smr_val, max_baud; |
| 1407 | int t = -1; | 1426 | int t = -1; |
| 1427 | u16 scfcr = 0; | ||
| 1408 | 1428 | ||
| 1409 | /* | 1429 | /* |
| 1410 | * earlyprintk comes here early on with port->uartclk set to zero. | 1430 | * earlyprintk comes here early on with port->uartclk set to zero. |
| @@ -1427,7 +1447,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1427 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | 1447 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ |
| 1428 | 1448 | ||
| 1429 | if (port->type != PORT_SCI) | 1449 | if (port->type != PORT_SCI) |
| 1430 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | 1450 | sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); |
| 1431 | 1451 | ||
| 1432 | smr_val = sci_in(port, SCSMR) & 3; | 1452 | smr_val = sci_in(port, SCSMR) & 3; |
| 1433 | if ((termios->c_cflag & CSIZE) == CS7) | 1453 | if ((termios->c_cflag & CSIZE) == CS7) |
| @@ -1458,10 +1478,32 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1458 | } | 1478 | } |
| 1459 | 1479 | ||
| 1460 | sci_init_pins(port, termios->c_cflag); | 1480 | sci_init_pins(port, termios->c_cflag); |
| 1461 | sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0); | 1481 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); |
| 1462 | 1482 | ||
| 1463 | sci_out(port, SCSCR, SCSCR_INIT(port)); | 1483 | sci_out(port, SCSCR, SCSCR_INIT(port)); |
| 1464 | 1484 | ||
| 1485 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
| 1486 | /* | ||
| 1487 | * Calculate delay for 1.5 DMA buffers: see | ||
| 1488 | * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits | ||
| 1489 | * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function | ||
| 1490 | * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)." | ||
| 1491 | * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO | ||
| 1492 | * sizes), but it has been found out experimentally, that this is not | ||
| 1493 | * enough: the driver too often needlessly runs on a DMA timeout. 20ms | ||
| 1494 | * as a minimum seem to work perfectly. | ||
| 1495 | */ | ||
| 1496 | if (s->chan_rx) { | ||
| 1497 | s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | ||
| 1498 | port->fifosize / 2; | ||
| 1499 | dev_dbg(port->dev, | ||
| 1500 | "DMA Rx t-out %ums, tty t-out %u jiffies\n", | ||
| 1501 | s->rx_timeout * 1000 / HZ, port->timeout); | ||
| 1502 | if (s->rx_timeout < msecs_to_jiffies(20)) | ||
| 1503 | s->rx_timeout = msecs_to_jiffies(20); | ||
| 1504 | } | ||
| 1505 | #endif | ||
| 1506 | |||
| 1465 | if ((termios->c_cflag & CREAD) != 0) | 1507 | if ((termios->c_cflag & CREAD) != 0) |
| 1466 | sci_start_rx(port); | 1508 | sci_start_rx(port); |
| 1467 | } | 1509 | } |
| @@ -1553,10 +1595,10 @@ static struct uart_ops sci_uart_ops = { | |||
| 1553 | #endif | 1595 | #endif |
| 1554 | }; | 1596 | }; |
| 1555 | 1597 | ||
| 1556 | static void __devinit sci_init_single(struct platform_device *dev, | 1598 | static int __devinit sci_init_single(struct platform_device *dev, |
| 1557 | struct sci_port *sci_port, | 1599 | struct sci_port *sci_port, |
| 1558 | unsigned int index, | 1600 | unsigned int index, |
| 1559 | struct plat_sci_port *p) | 1601 | struct plat_sci_port *p) |
| 1560 | { | 1602 | { |
| 1561 | struct uart_port *port = &sci_port->port; | 1603 | struct uart_port *port = &sci_port->port; |
| 1562 | 1604 | ||
| @@ -1577,8 +1619,23 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
| 1577 | } | 1619 | } |
| 1578 | 1620 | ||
| 1579 | if (dev) { | 1621 | if (dev) { |
| 1580 | sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; | 1622 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); |
| 1581 | sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); | 1623 | if (IS_ERR(sci_port->iclk)) { |
| 1624 | sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); | ||
| 1625 | if (IS_ERR(sci_port->iclk)) { | ||
| 1626 | dev_err(&dev->dev, "can't get iclk\n"); | ||
| 1627 | return PTR_ERR(sci_port->iclk); | ||
| 1628 | } | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | /* | ||
| 1632 | * The function clock is optional, ignore it if we can't | ||
| 1633 | * find it. | ||
| 1634 | */ | ||
| 1635 | sci_port->fclk = clk_get(&dev->dev, "sci_fck"); | ||
| 1636 | if (IS_ERR(sci_port->fclk)) | ||
| 1637 | sci_port->fclk = NULL; | ||
| 1638 | |||
| 1582 | sci_port->enable = sci_clk_enable; | 1639 | sci_port->enable = sci_clk_enable; |
| 1583 | sci_port->disable = sci_clk_disable; | 1640 | sci_port->disable = sci_clk_disable; |
| 1584 | port->dev = &dev->dev; | 1641 | port->dev = &dev->dev; |
| @@ -1605,6 +1662,7 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
| 1605 | #endif | 1662 | #endif |
| 1606 | 1663 | ||
| 1607 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); | 1664 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
| 1665 | return 0; | ||
| 1608 | } | 1666 | } |
| 1609 | 1667 | ||
| 1610 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 1668 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
| @@ -1754,8 +1812,11 @@ static int sci_remove(struct platform_device *dev) | |||
| 1754 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | 1812 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); |
| 1755 | 1813 | ||
| 1756 | spin_lock_irqsave(&priv->lock, flags); | 1814 | spin_lock_irqsave(&priv->lock, flags); |
| 1757 | list_for_each_entry(p, &priv->ports, node) | 1815 | list_for_each_entry(p, &priv->ports, node) { |
| 1758 | uart_remove_one_port(&sci_uart_driver, &p->port); | 1816 | uart_remove_one_port(&sci_uart_driver, &p->port); |
| 1817 | clk_put(p->iclk); | ||
| 1818 | clk_put(p->fclk); | ||
| 1819 | } | ||
| 1759 | spin_unlock_irqrestore(&priv->lock, flags); | 1820 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1760 | 1821 | ||
| 1761 | kfree(priv); | 1822 | kfree(priv); |
| @@ -1781,7 +1842,9 @@ static int __devinit sci_probe_single(struct platform_device *dev, | |||
| 1781 | return 0; | 1842 | return 0; |
| 1782 | } | 1843 | } |
| 1783 | 1844 | ||
| 1784 | sci_init_single(dev, sciport, index, p); | 1845 | ret = sci_init_single(dev, sciport, index, p); |
| 1846 | if (ret) | ||
| 1847 | return ret; | ||
| 1785 | 1848 | ||
| 1786 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); | 1849 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); |
| 1787 | if (ret) | 1850 | if (ret) |
diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig new file mode 100644 index 000000000000..a54de0b9b3df --- /dev/null +++ b/drivers/sh/Kconfig | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | config INTC_USERIMASK | ||
| 2 | bool "Userspace interrupt masking support" | ||
| 3 | depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A) | ||
| 4 | help | ||
| 5 | This enables support for hardware-assisted userspace hardirq | ||
| 6 | masking. | ||
| 7 | |||
| 8 | SH-4A and newer interrupt blocks all support a special shadowed | ||
| 9 | page with all non-masking registers obscured when mapped in to | ||
| 10 | userspace. This is primarily for use by userspace device | ||
| 11 | drivers that are using special priority levels. | ||
| 12 | |||
| 13 | If in doubt, say N. | ||
| 14 | |||
| 15 | config INTC_BALANCING | ||
| 16 | bool "Hardware IRQ balancing support" | ||
| 17 | depends on SMP && SUPERH && CPU_SUBTYPE_SH7786 | ||
| 18 | help | ||
| 19 | This enables support for IRQ auto-distribution mode on SH-X3 | ||
| 20 | SMP parts. All of the balancing and CPU wakeup decisions are | ||
| 21 | taken care of automatically by hardware for distributed | ||
| 22 | vectors. | ||
| 23 | |||
| 24 | If in doubt, say N. | ||
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 4956bf1f2134..78bb5127abd0 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
| @@ -4,4 +4,6 @@ | |||
| 4 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 4 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
| 5 | obj-$(CONFIG_MAPLE) += maple/ | 5 | obj-$(CONFIG_MAPLE) += maple/ |
| 6 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o | 6 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o |
| 7 | obj-$(CONFIG_SUPERH) += clk.o | ||
| 8 | obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o | ||
| 7 | obj-y += intc.o | 9 | obj-y += intc.o |
diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c new file mode 100644 index 000000000000..f5c80ba9ab1c --- /dev/null +++ b/drivers/sh/clk-cpg.c | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | #include <linux/clk.h> | ||
| 2 | #include <linux/compiler.h> | ||
| 3 | #include <linux/slab.h> | ||
| 4 | #include <linux/io.h> | ||
| 5 | #include <linux/sh_clk.h> | ||
| 6 | |||
| 7 | static int sh_clk_mstp32_enable(struct clk *clk) | ||
| 8 | { | ||
| 9 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), | ||
| 10 | clk->enable_reg); | ||
| 11 | return 0; | ||
| 12 | } | ||
| 13 | |||
| 14 | static void sh_clk_mstp32_disable(struct clk *clk) | ||
| 15 | { | ||
| 16 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), | ||
| 17 | clk->enable_reg); | ||
| 18 | } | ||
| 19 | |||
| 20 | static struct clk_ops sh_clk_mstp32_clk_ops = { | ||
| 21 | .enable = sh_clk_mstp32_enable, | ||
| 22 | .disable = sh_clk_mstp32_disable, | ||
| 23 | .recalc = followparent_recalc, | ||
| 24 | }; | ||
| 25 | |||
| 26 | int __init sh_clk_mstp32_register(struct clk *clks, int nr) | ||
| 27 | { | ||
| 28 | struct clk *clkp; | ||
| 29 | int ret = 0; | ||
| 30 | int k; | ||
| 31 | |||
| 32 | for (k = 0; !ret && (k < nr); k++) { | ||
| 33 | clkp = clks + k; | ||
| 34 | clkp->ops = &sh_clk_mstp32_clk_ops; | ||
| 35 | ret |= clk_register(clkp); | ||
| 36 | } | ||
| 37 | |||
| 38 | return ret; | ||
| 39 | } | ||
| 40 | |||
| 41 | static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) | ||
| 42 | { | ||
| 43 | return clk_rate_table_round(clk, clk->freq_table, rate); | ||
| 44 | } | ||
| 45 | |||
| 46 | static int sh_clk_div6_divisors[64] = { | ||
| 47 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, | ||
| 48 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, | ||
| 49 | 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | ||
| 50 | 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 | ||
| 51 | }; | ||
| 52 | |||
| 53 | static struct clk_div_mult_table sh_clk_div6_table = { | ||
| 54 | .divisors = sh_clk_div6_divisors, | ||
| 55 | .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), | ||
| 56 | }; | ||
| 57 | |||
| 58 | static unsigned long sh_clk_div6_recalc(struct clk *clk) | ||
| 59 | { | ||
| 60 | struct clk_div_mult_table *table = &sh_clk_div6_table; | ||
| 61 | unsigned int idx; | ||
| 62 | |||
| 63 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
| 64 | table, NULL); | ||
| 65 | |||
| 66 | idx = __raw_readl(clk->enable_reg) & 0x003f; | ||
| 67 | |||
| 68 | return clk->freq_table[idx].frequency; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int sh_clk_div6_set_rate(struct clk *clk, | ||
| 72 | unsigned long rate, int algo_id) | ||
| 73 | { | ||
| 74 | unsigned long value; | ||
| 75 | int idx; | ||
| 76 | |||
| 77 | idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
| 78 | if (idx < 0) | ||
| 79 | return idx; | ||
| 80 | |||
| 81 | value = __raw_readl(clk->enable_reg); | ||
| 82 | value &= ~0x3f; | ||
| 83 | value |= idx; | ||
| 84 | __raw_writel(value, clk->enable_reg); | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int sh_clk_div6_enable(struct clk *clk) | ||
| 89 | { | ||
| 90 | unsigned long value; | ||
| 91 | int ret; | ||
| 92 | |||
| 93 | ret = sh_clk_div6_set_rate(clk, clk->rate, 0); | ||
| 94 | if (ret == 0) { | ||
| 95 | value = __raw_readl(clk->enable_reg); | ||
| 96 | value &= ~0x100; /* clear stop bit to enable clock */ | ||
| 97 | __raw_writel(value, clk->enable_reg); | ||
| 98 | } | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | static void sh_clk_div6_disable(struct clk *clk) | ||
| 103 | { | ||
| 104 | unsigned long value; | ||
| 105 | |||
| 106 | value = __raw_readl(clk->enable_reg); | ||
| 107 | value |= 0x100; /* stop clock */ | ||
| 108 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ | ||
| 109 | __raw_writel(value, clk->enable_reg); | ||
| 110 | } | ||
| 111 | |||
| 112 | static struct clk_ops sh_clk_div6_clk_ops = { | ||
| 113 | .recalc = sh_clk_div6_recalc, | ||
| 114 | .round_rate = sh_clk_div_round_rate, | ||
| 115 | .set_rate = sh_clk_div6_set_rate, | ||
| 116 | .enable = sh_clk_div6_enable, | ||
| 117 | .disable = sh_clk_div6_disable, | ||
| 118 | }; | ||
| 119 | |||
| 120 | int __init sh_clk_div6_register(struct clk *clks, int nr) | ||
| 121 | { | ||
| 122 | struct clk *clkp; | ||
| 123 | void *freq_table; | ||
| 124 | int nr_divs = sh_clk_div6_table.nr_divisors; | ||
| 125 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
| 126 | int ret = 0; | ||
| 127 | int k; | ||
| 128 | |||
| 129 | freq_table_size *= (nr_divs + 1); | ||
| 130 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
| 131 | if (!freq_table) { | ||
| 132 | pr_err("sh_clk_div6_register: unable to alloc memory\n"); | ||
| 133 | return -ENOMEM; | ||
| 134 | } | ||
| 135 | |||
| 136 | for (k = 0; !ret && (k < nr); k++) { | ||
| 137 | clkp = clks + k; | ||
| 138 | |||
| 139 | clkp->ops = &sh_clk_div6_clk_ops; | ||
| 140 | clkp->id = -1; | ||
| 141 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
| 142 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
| 143 | |||
| 144 | ret = clk_register(clkp); | ||
| 145 | } | ||
| 146 | |||
| 147 | return ret; | ||
| 148 | } | ||
| 149 | |||
| 150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | ||
| 151 | { | ||
| 152 | struct clk_div4_table *d4t = clk->priv; | ||
| 153 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
| 154 | unsigned int idx; | ||
| 155 | |||
| 156 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
| 157 | table, &clk->arch_flags); | ||
| 158 | |||
| 159 | idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; | ||
| 160 | |||
| 161 | return clk->freq_table[idx].frequency; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) | ||
| 165 | { | ||
| 166 | struct clk_div4_table *d4t = clk->priv; | ||
| 167 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
| 168 | u32 value; | ||
| 169 | int ret; | ||
| 170 | |||
| 171 | /* we really need a better way to determine parent index, but for | ||
| 172 | * now assume internal parent comes with CLK_ENABLE_ON_INIT set, | ||
| 173 | * no CLK_ENABLE_ON_INIT means external clock... | ||
| 174 | */ | ||
| 175 | |||
| 176 | if (parent->flags & CLK_ENABLE_ON_INIT) | ||
| 177 | value = __raw_readl(clk->enable_reg) & ~(1 << 7); | ||
| 178 | else | ||
| 179 | value = __raw_readl(clk->enable_reg) | (1 << 7); | ||
| 180 | |||
| 181 | ret = clk_reparent(clk, parent); | ||
| 182 | if (ret < 0) | ||
| 183 | return ret; | ||
| 184 | |||
| 185 | __raw_writel(value, clk->enable_reg); | ||
| 186 | |||
| 187 | /* Rebiuld the frequency table */ | ||
| 188 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
| 189 | table, &clk->arch_flags); | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id) | ||
| 195 | { | ||
| 196 | struct clk_div4_table *d4t = clk->priv; | ||
| 197 | unsigned long value; | ||
| 198 | int idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
| 199 | if (idx < 0) | ||
| 200 | return idx; | ||
| 201 | |||
| 202 | value = __raw_readl(clk->enable_reg); | ||
| 203 | value &= ~(0xf << clk->enable_bit); | ||
| 204 | value |= (idx << clk->enable_bit); | ||
| 205 | __raw_writel(value, clk->enable_reg); | ||
| 206 | |||
| 207 | if (d4t->kick) | ||
| 208 | d4t->kick(clk); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int sh_clk_div4_enable(struct clk *clk) | ||
| 214 | { | ||
| 215 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static void sh_clk_div4_disable(struct clk *clk) | ||
| 220 | { | ||
| 221 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); | ||
| 222 | } | ||
| 223 | |||
| 224 | static struct clk_ops sh_clk_div4_clk_ops = { | ||
| 225 | .recalc = sh_clk_div4_recalc, | ||
| 226 | .set_rate = sh_clk_div4_set_rate, | ||
| 227 | .round_rate = sh_clk_div_round_rate, | ||
| 228 | }; | ||
| 229 | |||
| 230 | static struct clk_ops sh_clk_div4_enable_clk_ops = { | ||
| 231 | .recalc = sh_clk_div4_recalc, | ||
| 232 | .set_rate = sh_clk_div4_set_rate, | ||
| 233 | .round_rate = sh_clk_div_round_rate, | ||
| 234 | .enable = sh_clk_div4_enable, | ||
| 235 | .disable = sh_clk_div4_disable, | ||
| 236 | }; | ||
| 237 | |||
| 238 | static struct clk_ops sh_clk_div4_reparent_clk_ops = { | ||
| 239 | .recalc = sh_clk_div4_recalc, | ||
| 240 | .set_rate = sh_clk_div4_set_rate, | ||
| 241 | .round_rate = sh_clk_div_round_rate, | ||
| 242 | .enable = sh_clk_div4_enable, | ||
| 243 | .disable = sh_clk_div4_disable, | ||
| 244 | .set_parent = sh_clk_div4_set_parent, | ||
| 245 | }; | ||
| 246 | |||
| 247 | static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, | ||
| 248 | struct clk_div4_table *table, struct clk_ops *ops) | ||
| 249 | { | ||
| 250 | struct clk *clkp; | ||
| 251 | void *freq_table; | ||
| 252 | int nr_divs = table->div_mult_table->nr_divisors; | ||
| 253 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
| 254 | int ret = 0; | ||
| 255 | int k; | ||
| 256 | |||
| 257 | freq_table_size *= (nr_divs + 1); | ||
| 258 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
| 259 | if (!freq_table) { | ||
| 260 | pr_err("sh_clk_div4_register: unable to alloc memory\n"); | ||
| 261 | return -ENOMEM; | ||
| 262 | } | ||
| 263 | |||
| 264 | for (k = 0; !ret && (k < nr); k++) { | ||
| 265 | clkp = clks + k; | ||
| 266 | |||
| 267 | clkp->ops = ops; | ||
| 268 | clkp->id = -1; | ||
| 269 | clkp->priv = table; | ||
| 270 | |||
| 271 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
| 272 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
| 273 | |||
| 274 | ret = clk_register(clkp); | ||
| 275 | } | ||
| 276 | |||
| 277 | return ret; | ||
| 278 | } | ||
| 279 | |||
| 280 | int __init sh_clk_div4_register(struct clk *clks, int nr, | ||
| 281 | struct clk_div4_table *table) | ||
| 282 | { | ||
| 283 | return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); | ||
| 284 | } | ||
| 285 | |||
| 286 | int __init sh_clk_div4_enable_register(struct clk *clks, int nr, | ||
| 287 | struct clk_div4_table *table) | ||
| 288 | { | ||
| 289 | return sh_clk_div4_register_ops(clks, nr, table, | ||
| 290 | &sh_clk_div4_enable_clk_ops); | ||
| 291 | } | ||
| 292 | |||
| 293 | int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | ||
| 294 | struct clk_div4_table *table) | ||
| 295 | { | ||
| 296 | return sh_clk_div4_register_ops(clks, nr, table, | ||
| 297 | &sh_clk_div4_reparent_clk_ops); | ||
| 298 | } | ||
diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c new file mode 100644 index 000000000000..5d84adac9ec4 --- /dev/null +++ b/drivers/sh/clk.c | |||
| @@ -0,0 +1,545 @@ | |||
| 1 | /* | ||
| 2 | * drivers/sh/clk.c - SuperH clock framework | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 - 2009 Paul Mundt | ||
| 5 | * | ||
| 6 | * This clock framework is derived from the OMAP version by: | ||
| 7 | * | ||
| 8 | * Copyright (C) 2004 - 2008 Nokia Corporation | ||
| 9 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
| 10 | * | ||
| 11 | * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> | ||
| 12 | * | ||
| 13 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 14 | * License. See the file "COPYING" in the main directory of this archive | ||
| 15 | * for more details. | ||
| 16 | */ | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/mutex.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/kobject.h> | ||
| 23 | #include <linux/sysdev.h> | ||
| 24 | #include <linux/seq_file.h> | ||
| 25 | #include <linux/err.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | #include <linux/debugfs.h> | ||
| 28 | #include <linux/cpufreq.h> | ||
| 29 | #include <linux/clk.h> | ||
| 30 | #include <linux/sh_clk.h> | ||
| 31 | |||
| 32 | static LIST_HEAD(clock_list); | ||
| 33 | static DEFINE_SPINLOCK(clock_lock); | ||
| 34 | static DEFINE_MUTEX(clock_list_sem); | ||
| 35 | |||
| 36 | void clk_rate_table_build(struct clk *clk, | ||
| 37 | struct cpufreq_frequency_table *freq_table, | ||
| 38 | int nr_freqs, | ||
| 39 | struct clk_div_mult_table *src_table, | ||
| 40 | unsigned long *bitmap) | ||
| 41 | { | ||
| 42 | unsigned long mult, div; | ||
| 43 | unsigned long freq; | ||
| 44 | int i; | ||
| 45 | |||
| 46 | for (i = 0; i < nr_freqs; i++) { | ||
| 47 | div = 1; | ||
| 48 | mult = 1; | ||
| 49 | |||
| 50 | if (src_table->divisors && i < src_table->nr_divisors) | ||
| 51 | div = src_table->divisors[i]; | ||
| 52 | |||
| 53 | if (src_table->multipliers && i < src_table->nr_multipliers) | ||
| 54 | mult = src_table->multipliers[i]; | ||
| 55 | |||
| 56 | if (!div || !mult || (bitmap && !test_bit(i, bitmap))) | ||
| 57 | freq = CPUFREQ_ENTRY_INVALID; | ||
| 58 | else | ||
| 59 | freq = clk->parent->rate * mult / div; | ||
| 60 | |||
| 61 | freq_table[i].index = i; | ||
| 62 | freq_table[i].frequency = freq; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* Termination entry */ | ||
| 66 | freq_table[i].index = i; | ||
| 67 | freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
| 68 | } | ||
| 69 | |||
| 70 | long clk_rate_table_round(struct clk *clk, | ||
| 71 | struct cpufreq_frequency_table *freq_table, | ||
| 72 | unsigned long rate) | ||
| 73 | { | ||
| 74 | unsigned long rate_error, rate_error_prev = ~0UL; | ||
| 75 | unsigned long rate_best_fit = rate; | ||
| 76 | unsigned long highest, lowest; | ||
| 77 | int i; | ||
| 78 | |||
| 79 | highest = lowest = 0; | ||
| 80 | |||
| 81 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||
| 82 | unsigned long freq = freq_table[i].frequency; | ||
| 83 | |||
| 84 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
| 85 | continue; | ||
| 86 | |||
| 87 | if (freq > highest) | ||
| 88 | highest = freq; | ||
| 89 | if (freq < lowest) | ||
| 90 | lowest = freq; | ||
| 91 | |||
| 92 | rate_error = abs(freq - rate); | ||
| 93 | if (rate_error < rate_error_prev) { | ||
| 94 | rate_best_fit = freq; | ||
| 95 | rate_error_prev = rate_error; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (rate_error == 0) | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (rate >= highest) | ||
| 103 | rate_best_fit = highest; | ||
| 104 | if (rate <= lowest) | ||
| 105 | rate_best_fit = lowest; | ||
| 106 | |||
| 107 | return rate_best_fit; | ||
| 108 | } | ||
| 109 | |||
| 110 | int clk_rate_table_find(struct clk *clk, | ||
| 111 | struct cpufreq_frequency_table *freq_table, | ||
| 112 | unsigned long rate) | ||
| 113 | { | ||
| 114 | int i; | ||
| 115 | |||
| 116 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||
| 117 | unsigned long freq = freq_table[i].frequency; | ||
| 118 | |||
| 119 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
| 120 | continue; | ||
| 121 | |||
| 122 | if (freq == rate) | ||
| 123 | return i; | ||
| 124 | } | ||
| 125 | |||
| 126 | return -ENOENT; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* Used for clocks that always have same value as the parent clock */ | ||
| 130 | unsigned long followparent_recalc(struct clk *clk) | ||
| 131 | { | ||
| 132 | return clk->parent ? clk->parent->rate : 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | int clk_reparent(struct clk *child, struct clk *parent) | ||
| 136 | { | ||
| 137 | list_del_init(&child->sibling); | ||
| 138 | if (parent) | ||
| 139 | list_add(&child->sibling, &parent->children); | ||
| 140 | child->parent = parent; | ||
| 141 | |||
| 142 | /* now do the debugfs renaming to reattach the child | ||
| 143 | to the proper parent */ | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* Propagate rate to children */ | ||
| 149 | void propagate_rate(struct clk *tclk) | ||
| 150 | { | ||
| 151 | struct clk *clkp; | ||
| 152 | |||
| 153 | list_for_each_entry(clkp, &tclk->children, sibling) { | ||
| 154 | if (clkp->ops && clkp->ops->recalc) | ||
| 155 | clkp->rate = clkp->ops->recalc(clkp); | ||
| 156 | |||
| 157 | propagate_rate(clkp); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | static void __clk_disable(struct clk *clk) | ||
| 162 | { | ||
| 163 | if (WARN(!clk->usecount, "Trying to disable clock %s with 0 usecount\n", | ||
| 164 | clk->name)) | ||
| 165 | return; | ||
| 166 | |||
| 167 | if (!(--clk->usecount)) { | ||
| 168 | if (likely(clk->ops && clk->ops->disable)) | ||
| 169 | clk->ops->disable(clk); | ||
| 170 | if (likely(clk->parent)) | ||
| 171 | __clk_disable(clk->parent); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | void clk_disable(struct clk *clk) | ||
| 176 | { | ||
| 177 | unsigned long flags; | ||
| 178 | |||
| 179 | if (!clk) | ||
| 180 | return; | ||
| 181 | |||
| 182 | spin_lock_irqsave(&clock_lock, flags); | ||
| 183 | __clk_disable(clk); | ||
| 184 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 185 | } | ||
| 186 | EXPORT_SYMBOL_GPL(clk_disable); | ||
| 187 | |||
| 188 | static int __clk_enable(struct clk *clk) | ||
| 189 | { | ||
| 190 | int ret = 0; | ||
| 191 | |||
| 192 | if (clk->usecount++ == 0) { | ||
| 193 | if (clk->parent) { | ||
| 194 | ret = __clk_enable(clk->parent); | ||
| 195 | if (unlikely(ret)) | ||
| 196 | goto err; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (clk->ops && clk->ops->enable) { | ||
| 200 | ret = clk->ops->enable(clk); | ||
| 201 | if (ret) { | ||
| 202 | if (clk->parent) | ||
| 203 | __clk_disable(clk->parent); | ||
| 204 | goto err; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | return ret; | ||
| 210 | err: | ||
| 211 | clk->usecount--; | ||
| 212 | return ret; | ||
| 213 | } | ||
| 214 | |||
| 215 | int clk_enable(struct clk *clk) | ||
| 216 | { | ||
| 217 | unsigned long flags; | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | if (!clk) | ||
| 221 | return -EINVAL; | ||
| 222 | |||
| 223 | spin_lock_irqsave(&clock_lock, flags); | ||
| 224 | ret = __clk_enable(clk); | ||
| 225 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 226 | |||
| 227 | return ret; | ||
| 228 | } | ||
| 229 | EXPORT_SYMBOL_GPL(clk_enable); | ||
| 230 | |||
| 231 | static LIST_HEAD(root_clks); | ||
| 232 | |||
| 233 | /** | ||
| 234 | * recalculate_root_clocks - recalculate and propagate all root clocks | ||
| 235 | * | ||
| 236 | * Recalculates all root clocks (clocks with no parent), which if the | ||
| 237 | * clock's .recalc is set correctly, should also propagate their rates. | ||
| 238 | * Called at init. | ||
| 239 | */ | ||
| 240 | void recalculate_root_clocks(void) | ||
| 241 | { | ||
| 242 | struct clk *clkp; | ||
| 243 | |||
| 244 | list_for_each_entry(clkp, &root_clks, sibling) { | ||
| 245 | if (clkp->ops && clkp->ops->recalc) | ||
| 246 | clkp->rate = clkp->ops->recalc(clkp); | ||
| 247 | propagate_rate(clkp); | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | int clk_register(struct clk *clk) | ||
| 252 | { | ||
| 253 | if (clk == NULL || IS_ERR(clk)) | ||
| 254 | return -EINVAL; | ||
| 255 | |||
| 256 | /* | ||
| 257 | * trap out already registered clocks | ||
| 258 | */ | ||
| 259 | if (clk->node.next || clk->node.prev) | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | mutex_lock(&clock_list_sem); | ||
| 263 | |||
| 264 | INIT_LIST_HEAD(&clk->children); | ||
| 265 | clk->usecount = 0; | ||
| 266 | |||
| 267 | if (clk->parent) | ||
| 268 | list_add(&clk->sibling, &clk->parent->children); | ||
| 269 | else | ||
| 270 | list_add(&clk->sibling, &root_clks); | ||
| 271 | |||
| 272 | list_add(&clk->node, &clock_list); | ||
| 273 | if (clk->ops && clk->ops->init) | ||
| 274 | clk->ops->init(clk); | ||
| 275 | mutex_unlock(&clock_list_sem); | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | EXPORT_SYMBOL_GPL(clk_register); | ||
| 280 | |||
| 281 | void clk_unregister(struct clk *clk) | ||
| 282 | { | ||
| 283 | mutex_lock(&clock_list_sem); | ||
| 284 | list_del(&clk->sibling); | ||
| 285 | list_del(&clk->node); | ||
| 286 | mutex_unlock(&clock_list_sem); | ||
| 287 | } | ||
| 288 | EXPORT_SYMBOL_GPL(clk_unregister); | ||
| 289 | |||
| 290 | void clk_enable_init_clocks(void) | ||
| 291 | { | ||
| 292 | struct clk *clkp; | ||
| 293 | |||
| 294 | list_for_each_entry(clkp, &clock_list, node) | ||
| 295 | if (clkp->flags & CLK_ENABLE_ON_INIT) | ||
| 296 | clk_enable(clkp); | ||
| 297 | } | ||
| 298 | |||
| 299 | unsigned long clk_get_rate(struct clk *clk) | ||
| 300 | { | ||
| 301 | return clk->rate; | ||
| 302 | } | ||
| 303 | EXPORT_SYMBOL_GPL(clk_get_rate); | ||
| 304 | |||
| 305 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
| 306 | { | ||
| 307 | return clk_set_rate_ex(clk, rate, 0); | ||
| 308 | } | ||
| 309 | EXPORT_SYMBOL_GPL(clk_set_rate); | ||
| 310 | |||
| 311 | int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) | ||
| 312 | { | ||
| 313 | int ret = -EOPNOTSUPP; | ||
| 314 | unsigned long flags; | ||
| 315 | |||
| 316 | spin_lock_irqsave(&clock_lock, flags); | ||
| 317 | |||
| 318 | if (likely(clk->ops && clk->ops->set_rate)) { | ||
| 319 | ret = clk->ops->set_rate(clk, rate, algo_id); | ||
| 320 | if (ret != 0) | ||
| 321 | goto out_unlock; | ||
| 322 | } else { | ||
| 323 | clk->rate = rate; | ||
| 324 | ret = 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | if (clk->ops && clk->ops->recalc) | ||
| 328 | clk->rate = clk->ops->recalc(clk); | ||
| 329 | |||
| 330 | propagate_rate(clk); | ||
| 331 | |||
| 332 | out_unlock: | ||
| 333 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 334 | |||
| 335 | return ret; | ||
| 336 | } | ||
| 337 | EXPORT_SYMBOL_GPL(clk_set_rate_ex); | ||
| 338 | |||
| 339 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
| 340 | { | ||
| 341 | unsigned long flags; | ||
| 342 | int ret = -EINVAL; | ||
| 343 | |||
| 344 | if (!parent || !clk) | ||
| 345 | return ret; | ||
| 346 | if (clk->parent == parent) | ||
| 347 | return 0; | ||
| 348 | |||
| 349 | spin_lock_irqsave(&clock_lock, flags); | ||
| 350 | if (clk->usecount == 0) { | ||
| 351 | if (clk->ops->set_parent) | ||
| 352 | ret = clk->ops->set_parent(clk, parent); | ||
| 353 | else | ||
| 354 | ret = clk_reparent(clk, parent); | ||
| 355 | |||
| 356 | if (ret == 0) { | ||
| 357 | pr_debug("clock: set parent of %s to %s (new rate %ld)\n", | ||
| 358 | clk->name, clk->parent->name, clk->rate); | ||
| 359 | if (clk->ops->recalc) | ||
| 360 | clk->rate = clk->ops->recalc(clk); | ||
| 361 | propagate_rate(clk); | ||
| 362 | } | ||
| 363 | } else | ||
| 364 | ret = -EBUSY; | ||
| 365 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 366 | |||
| 367 | return ret; | ||
| 368 | } | ||
| 369 | EXPORT_SYMBOL_GPL(clk_set_parent); | ||
| 370 | |||
| 371 | struct clk *clk_get_parent(struct clk *clk) | ||
| 372 | { | ||
| 373 | return clk->parent; | ||
| 374 | } | ||
| 375 | EXPORT_SYMBOL_GPL(clk_get_parent); | ||
| 376 | |||
| 377 | long clk_round_rate(struct clk *clk, unsigned long rate) | ||
| 378 | { | ||
| 379 | if (likely(clk->ops && clk->ops->round_rate)) { | ||
| 380 | unsigned long flags, rounded; | ||
| 381 | |||
| 382 | spin_lock_irqsave(&clock_lock, flags); | ||
| 383 | rounded = clk->ops->round_rate(clk, rate); | ||
| 384 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 385 | |||
| 386 | return rounded; | ||
| 387 | } | ||
| 388 | |||
| 389 | return clk_get_rate(clk); | ||
| 390 | } | ||
| 391 | EXPORT_SYMBOL_GPL(clk_round_rate); | ||
| 392 | |||
| 393 | #ifdef CONFIG_PM | ||
| 394 | static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) | ||
| 395 | { | ||
| 396 | static pm_message_t prev_state; | ||
| 397 | struct clk *clkp; | ||
| 398 | |||
| 399 | switch (state.event) { | ||
| 400 | case PM_EVENT_ON: | ||
| 401 | /* Resumeing from hibernation */ | ||
| 402 | if (prev_state.event != PM_EVENT_FREEZE) | ||
| 403 | break; | ||
| 404 | |||
| 405 | list_for_each_entry(clkp, &clock_list, node) { | ||
| 406 | if (likely(clkp->ops)) { | ||
| 407 | unsigned long rate = clkp->rate; | ||
| 408 | |||
| 409 | if (likely(clkp->ops->set_parent)) | ||
| 410 | clkp->ops->set_parent(clkp, | ||
| 411 | clkp->parent); | ||
| 412 | if (likely(clkp->ops->set_rate)) | ||
| 413 | clkp->ops->set_rate(clkp, | ||
| 414 | rate, NO_CHANGE); | ||
| 415 | else if (likely(clkp->ops->recalc)) | ||
| 416 | clkp->rate = clkp->ops->recalc(clkp); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | break; | ||
| 420 | case PM_EVENT_FREEZE: | ||
| 421 | break; | ||
| 422 | case PM_EVENT_SUSPEND: | ||
| 423 | break; | ||
| 424 | } | ||
| 425 | |||
| 426 | prev_state = state; | ||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int clks_sysdev_resume(struct sys_device *dev) | ||
| 431 | { | ||
| 432 | return clks_sysdev_suspend(dev, PMSG_ON); | ||
| 433 | } | ||
| 434 | |||
| 435 | static struct sysdev_class clks_sysdev_class = { | ||
| 436 | .name = "clks", | ||
| 437 | }; | ||
| 438 | |||
| 439 | static struct sysdev_driver clks_sysdev_driver = { | ||
| 440 | .suspend = clks_sysdev_suspend, | ||
| 441 | .resume = clks_sysdev_resume, | ||
| 442 | }; | ||
| 443 | |||
| 444 | static struct sys_device clks_sysdev_dev = { | ||
| 445 | .cls = &clks_sysdev_class, | ||
| 446 | }; | ||
| 447 | |||
| 448 | static int __init clk_sysdev_init(void) | ||
| 449 | { | ||
| 450 | sysdev_class_register(&clks_sysdev_class); | ||
| 451 | sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); | ||
| 452 | sysdev_register(&clks_sysdev_dev); | ||
| 453 | |||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | subsys_initcall(clk_sysdev_init); | ||
| 457 | #endif | ||
| 458 | |||
| 459 | /* | ||
| 460 | * debugfs support to trace clock tree hierarchy and attributes | ||
| 461 | */ | ||
| 462 | static struct dentry *clk_debugfs_root; | ||
| 463 | |||
| 464 | static int clk_debugfs_register_one(struct clk *c) | ||
| 465 | { | ||
| 466 | int err; | ||
| 467 | struct dentry *d, *child, *child_tmp; | ||
| 468 | struct clk *pa = c->parent; | ||
| 469 | char s[255]; | ||
| 470 | char *p = s; | ||
| 471 | |||
| 472 | p += sprintf(p, "%s", c->name); | ||
| 473 | if (c->id >= 0) | ||
| 474 | sprintf(p, ":%d", c->id); | ||
| 475 | d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root); | ||
| 476 | if (!d) | ||
| 477 | return -ENOMEM; | ||
| 478 | c->dentry = d; | ||
| 479 | |||
| 480 | d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount); | ||
| 481 | if (!d) { | ||
| 482 | err = -ENOMEM; | ||
| 483 | goto err_out; | ||
| 484 | } | ||
| 485 | d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate); | ||
| 486 | if (!d) { | ||
| 487 | err = -ENOMEM; | ||
| 488 | goto err_out; | ||
| 489 | } | ||
| 490 | d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags); | ||
| 491 | if (!d) { | ||
| 492 | err = -ENOMEM; | ||
| 493 | goto err_out; | ||
| 494 | } | ||
| 495 | return 0; | ||
| 496 | |||
| 497 | err_out: | ||
| 498 | d = c->dentry; | ||
| 499 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
| 500 | debugfs_remove(child); | ||
| 501 | debugfs_remove(c->dentry); | ||
| 502 | return err; | ||
| 503 | } | ||
| 504 | |||
| 505 | static int clk_debugfs_register(struct clk *c) | ||
| 506 | { | ||
| 507 | int err; | ||
| 508 | struct clk *pa = c->parent; | ||
| 509 | |||
| 510 | if (pa && !pa->dentry) { | ||
| 511 | err = clk_debugfs_register(pa); | ||
| 512 | if (err) | ||
| 513 | return err; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (!c->dentry && c->name) { | ||
| 517 | err = clk_debugfs_register_one(c); | ||
| 518 | if (err) | ||
| 519 | return err; | ||
| 520 | } | ||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | static int __init clk_debugfs_init(void) | ||
| 525 | { | ||
| 526 | struct clk *c; | ||
| 527 | struct dentry *d; | ||
| 528 | int err; | ||
| 529 | |||
| 530 | d = debugfs_create_dir("clock", NULL); | ||
| 531 | if (!d) | ||
| 532 | return -ENOMEM; | ||
| 533 | clk_debugfs_root = d; | ||
| 534 | |||
| 535 | list_for_each_entry(c, &clock_list, node) { | ||
| 536 | err = clk_debugfs_register(c); | ||
| 537 | if (err) | ||
| 538 | goto err_out; | ||
| 539 | } | ||
| 540 | return 0; | ||
| 541 | err_out: | ||
| 542 | debugfs_remove_recursive(clk_debugfs_root); | ||
| 543 | return err; | ||
| 544 | } | ||
| 545 | late_initcall(clk_debugfs_init); | ||
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 94ad6bd86a00..c585574b9aed 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/topology.h> | 28 | #include <linux/topology.h> |
| 29 | #include <linux/bitmap.h> | 29 | #include <linux/bitmap.h> |
| 30 | #include <linux/cpumask.h> | 30 | #include <linux/cpumask.h> |
| 31 | #include <asm/sizes.h> | ||
| 31 | 32 | ||
| 32 | #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ | 33 | #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ |
| 33 | ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ | 34 | ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ |
| @@ -45,6 +46,12 @@ struct intc_handle_int { | |||
| 45 | unsigned long handle; | 46 | unsigned long handle; |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 49 | struct intc_window { | ||
| 50 | phys_addr_t phys; | ||
| 51 | void __iomem *virt; | ||
| 52 | unsigned long size; | ||
| 53 | }; | ||
| 54 | |||
| 48 | struct intc_desc_int { | 55 | struct intc_desc_int { |
| 49 | struct list_head list; | 56 | struct list_head list; |
| 50 | struct sys_device sysdev; | 57 | struct sys_device sysdev; |
| @@ -58,6 +65,8 @@ struct intc_desc_int { | |||
| 58 | unsigned int nr_prio; | 65 | unsigned int nr_prio; |
| 59 | struct intc_handle_int *sense; | 66 | struct intc_handle_int *sense; |
| 60 | unsigned int nr_sense; | 67 | unsigned int nr_sense; |
| 68 | struct intc_window *window; | ||
| 69 | unsigned int nr_windows; | ||
| 61 | struct irq_chip chip; | 70 | struct irq_chip chip; |
| 62 | }; | 71 | }; |
| 63 | 72 | ||
| @@ -87,8 +96,12 @@ static DEFINE_SPINLOCK(vector_lock); | |||
| 87 | #define SMP_NR(d, x) 1 | 96 | #define SMP_NR(d, x) 1 |
| 88 | #endif | 97 | #endif |
| 89 | 98 | ||
| 90 | static unsigned int intc_prio_level[NR_IRQS]; /* for now */ | 99 | static unsigned int intc_prio_level[NR_IRQS]; /* for now */ |
| 100 | static unsigned int default_prio_level = 2; /* 2 - 16 */ | ||
| 91 | static unsigned long ack_handle[NR_IRQS]; | 101 | static unsigned long ack_handle[NR_IRQS]; |
| 102 | #ifdef CONFIG_INTC_BALANCING | ||
| 103 | static unsigned long dist_handle[NR_IRQS]; | ||
| 104 | #endif | ||
| 92 | 105 | ||
| 93 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | 106 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) |
| 94 | { | 107 | { |
| @@ -96,6 +109,47 @@ static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | |||
| 96 | return container_of(chip, struct intc_desc_int, chip); | 109 | return container_of(chip, struct intc_desc_int, chip); |
| 97 | } | 110 | } |
| 98 | 111 | ||
| 112 | static unsigned long intc_phys_to_virt(struct intc_desc_int *d, | ||
| 113 | unsigned long address) | ||
| 114 | { | ||
| 115 | struct intc_window *window; | ||
| 116 | int k; | ||
| 117 | |||
| 118 | /* scan through physical windows and convert address */ | ||
| 119 | for (k = 0; k < d->nr_windows; k++) { | ||
| 120 | window = d->window + k; | ||
| 121 | |||
| 122 | if (address < window->phys) | ||
| 123 | continue; | ||
| 124 | |||
| 125 | if (address >= (window->phys + window->size)) | ||
| 126 | continue; | ||
| 127 | |||
| 128 | address -= window->phys; | ||
| 129 | address += (unsigned long)window->virt; | ||
| 130 | |||
| 131 | return address; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* no windows defined, register must be 1:1 mapped virt:phys */ | ||
| 135 | return address; | ||
| 136 | } | ||
| 137 | |||
| 138 | static unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address) | ||
| 139 | { | ||
| 140 | unsigned int k; | ||
| 141 | |||
| 142 | address = intc_phys_to_virt(d, address); | ||
| 143 | |||
| 144 | for (k = 0; k < d->nr_reg; k++) { | ||
| 145 | if (d->reg[k] == address) | ||
| 146 | return k; | ||
| 147 | } | ||
| 148 | |||
| 149 | BUG(); | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 99 | static inline unsigned int set_field(unsigned int value, | 153 | static inline unsigned int set_field(unsigned int value, |
| 100 | unsigned int field_value, | 154 | unsigned int field_value, |
| 101 | unsigned int handle) | 155 | unsigned int handle) |
| @@ -229,6 +283,85 @@ static void (*intc_disable_fns[])(unsigned long addr, | |||
| 229 | [MODE_PCLR_REG] = intc_mode_field, | 283 | [MODE_PCLR_REG] = intc_mode_field, |
| 230 | }; | 284 | }; |
| 231 | 285 | ||
| 286 | #ifdef CONFIG_INTC_BALANCING | ||
| 287 | static inline void intc_balancing_enable(unsigned int irq) | ||
| 288 | { | ||
| 289 | struct intc_desc_int *d = get_intc_desc(irq); | ||
| 290 | unsigned long handle = dist_handle[irq]; | ||
| 291 | unsigned long addr; | ||
| 292 | |||
| 293 | if (irq_balancing_disabled(irq) || !handle) | ||
| 294 | return; | ||
| 295 | |||
| 296 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); | ||
| 297 | intc_reg_fns[_INTC_FN(handle)](addr, handle, 1); | ||
| 298 | } | ||
| 299 | |||
| 300 | static inline void intc_balancing_disable(unsigned int irq) | ||
| 301 | { | ||
| 302 | struct intc_desc_int *d = get_intc_desc(irq); | ||
| 303 | unsigned long handle = dist_handle[irq]; | ||
| 304 | unsigned long addr; | ||
| 305 | |||
| 306 | if (irq_balancing_disabled(irq) || !handle) | ||
| 307 | return; | ||
| 308 | |||
| 309 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); | ||
| 310 | intc_reg_fns[_INTC_FN(handle)](addr, handle, 0); | ||
| 311 | } | ||
| 312 | |||
| 313 | static unsigned int intc_dist_data(struct intc_desc *desc, | ||
| 314 | struct intc_desc_int *d, | ||
| 315 | intc_enum enum_id) | ||
| 316 | { | ||
| 317 | struct intc_mask_reg *mr = desc->hw.mask_regs; | ||
| 318 | unsigned int i, j, fn, mode; | ||
| 319 | unsigned long reg_e, reg_d; | ||
| 320 | |||
| 321 | for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) { | ||
| 322 | mr = desc->hw.mask_regs + i; | ||
| 323 | |||
| 324 | /* | ||
| 325 | * Skip this entry if there's no auto-distribution | ||
| 326 | * register associated with it. | ||
| 327 | */ | ||
| 328 | if (!mr->dist_reg) | ||
| 329 | continue; | ||
| 330 | |||
| 331 | for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { | ||
| 332 | if (mr->enum_ids[j] != enum_id) | ||
| 333 | continue; | ||
| 334 | |||
| 335 | fn = REG_FN_MODIFY_BASE; | ||
| 336 | mode = MODE_ENABLE_REG; | ||
| 337 | reg_e = mr->dist_reg; | ||
| 338 | reg_d = mr->dist_reg; | ||
| 339 | |||
| 340 | fn += (mr->reg_width >> 3) - 1; | ||
| 341 | return _INTC_MK(fn, mode, | ||
| 342 | intc_get_reg(d, reg_e), | ||
| 343 | intc_get_reg(d, reg_d), | ||
| 344 | 1, | ||
| 345 | (mr->reg_width - 1) - j); | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | /* | ||
| 350 | * It's possible we've gotten here with no distribution options | ||
| 351 | * available for the IRQ in question, so we just skip over those. | ||
| 352 | */ | ||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | #else | ||
| 356 | static inline void intc_balancing_enable(unsigned int irq) | ||
| 357 | { | ||
| 358 | } | ||
| 359 | |||
| 360 | static inline void intc_balancing_disable(unsigned int irq) | ||
| 361 | { | ||
| 362 | } | ||
| 363 | #endif | ||
| 364 | |||
| 232 | static inline void _intc_enable(unsigned int irq, unsigned long handle) | 365 | static inline void _intc_enable(unsigned int irq, unsigned long handle) |
| 233 | { | 366 | { |
| 234 | struct intc_desc_int *d = get_intc_desc(irq); | 367 | struct intc_desc_int *d = get_intc_desc(irq); |
| @@ -244,6 +377,8 @@ static inline void _intc_enable(unsigned int irq, unsigned long handle) | |||
| 244 | intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ | 377 | intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ |
| 245 | [_INTC_FN(handle)], irq); | 378 | [_INTC_FN(handle)], irq); |
| 246 | } | 379 | } |
| 380 | |||
| 381 | intc_balancing_enable(irq); | ||
| 247 | } | 382 | } |
| 248 | 383 | ||
| 249 | static void intc_enable(unsigned int irq) | 384 | static void intc_enable(unsigned int irq) |
| @@ -254,10 +389,12 @@ static void intc_enable(unsigned int irq) | |||
| 254 | static void intc_disable(unsigned int irq) | 389 | static void intc_disable(unsigned int irq) |
| 255 | { | 390 | { |
| 256 | struct intc_desc_int *d = get_intc_desc(irq); | 391 | struct intc_desc_int *d = get_intc_desc(irq); |
| 257 | unsigned long handle = (unsigned long) get_irq_chip_data(irq); | 392 | unsigned long handle = (unsigned long)get_irq_chip_data(irq); |
| 258 | unsigned long addr; | 393 | unsigned long addr; |
| 259 | unsigned int cpu; | 394 | unsigned int cpu; |
| 260 | 395 | ||
| 396 | intc_balancing_disable(irq); | ||
| 397 | |||
| 261 | for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { | 398 | for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { |
| 262 | #ifdef CONFIG_SMP | 399 | #ifdef CONFIG_SMP |
| 263 | if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity)) | 400 | if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity)) |
| @@ -336,8 +473,7 @@ static void intc_mask_ack(unsigned int irq) | |||
| 336 | 473 | ||
| 337 | intc_disable(irq); | 474 | intc_disable(irq); |
| 338 | 475 | ||
| 339 | /* read register and write zero only to the assocaited bit */ | 476 | /* read register and write zero only to the associated bit */ |
| 340 | |||
| 341 | if (handle) { | 477 | if (handle) { |
| 342 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); | 478 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); |
| 343 | switch (_INTC_FN(handle)) { | 479 | switch (_INTC_FN(handle)) { |
| @@ -366,7 +502,8 @@ static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, | |||
| 366 | { | 502 | { |
| 367 | int i; | 503 | int i; |
| 368 | 504 | ||
| 369 | /* this doesn't scale well, but... | 505 | /* |
| 506 | * this doesn't scale well, but... | ||
| 370 | * | 507 | * |
| 371 | * this function should only be used for cerain uncommon | 508 | * this function should only be used for cerain uncommon |
| 372 | * operations such as intc_set_priority() and intc_set_sense() | 509 | * operations such as intc_set_priority() and intc_set_sense() |
| @@ -377,7 +514,6 @@ static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, | |||
| 377 | * memory footprint down is to make sure the array is sorted | 514 | * memory footprint down is to make sure the array is sorted |
| 378 | * and then perform a bisect to lookup the irq. | 515 | * and then perform a bisect to lookup the irq. |
| 379 | */ | 516 | */ |
| 380 | |||
| 381 | for (i = 0; i < nr_hp; i++) { | 517 | for (i = 0; i < nr_hp; i++) { |
| 382 | if ((hp + i)->irq != irq) | 518 | if ((hp + i)->irq != irq) |
| 383 | continue; | 519 | continue; |
| @@ -408,7 +544,6 @@ int intc_set_priority(unsigned int irq, unsigned int prio) | |||
| 408 | * primary masking method is using intc_prio_level[irq] | 544 | * primary masking method is using intc_prio_level[irq] |
| 409 | * priority level will be set during next enable() | 545 | * priority level will be set during next enable() |
| 410 | */ | 546 | */ |
| 411 | |||
| 412 | if (_INTC_FN(ihp->handle) != REG_FN_ERR) | 547 | if (_INTC_FN(ihp->handle) != REG_FN_ERR) |
| 413 | _intc_enable(irq, ihp->handle); | 548 | _intc_enable(irq, ihp->handle); |
| 414 | } | 549 | } |
| @@ -447,20 +582,6 @@ static int intc_set_sense(unsigned int irq, unsigned int type) | |||
| 447 | return 0; | 582 | return 0; |
| 448 | } | 583 | } |
| 449 | 584 | ||
| 450 | static unsigned int __init intc_get_reg(struct intc_desc_int *d, | ||
| 451 | unsigned long address) | ||
| 452 | { | ||
| 453 | unsigned int k; | ||
| 454 | |||
| 455 | for (k = 0; k < d->nr_reg; k++) { | ||
| 456 | if (d->reg[k] == address) | ||
| 457 | return k; | ||
| 458 | } | ||
| 459 | |||
| 460 | BUG(); | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static intc_enum __init intc_grp_id(struct intc_desc *desc, | 585 | static intc_enum __init intc_grp_id(struct intc_desc *desc, |
| 465 | intc_enum enum_id) | 586 | intc_enum enum_id) |
| 466 | { | 587 | { |
| @@ -718,13 +839,14 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 718 | */ | 839 | */ |
| 719 | set_bit(irq, intc_irq_map); | 840 | set_bit(irq, intc_irq_map); |
| 720 | 841 | ||
| 721 | /* Prefer single interrupt source bitmap over other combinations: | 842 | /* |
| 843 | * Prefer single interrupt source bitmap over other combinations: | ||
| 844 | * | ||
| 722 | * 1. bitmap, single interrupt source | 845 | * 1. bitmap, single interrupt source |
| 723 | * 2. priority, single interrupt source | 846 | * 2. priority, single interrupt source |
| 724 | * 3. bitmap, multiple interrupt sources (groups) | 847 | * 3. bitmap, multiple interrupt sources (groups) |
| 725 | * 4. priority, multiple interrupt sources (groups) | 848 | * 4. priority, multiple interrupt sources (groups) |
| 726 | */ | 849 | */ |
| 727 | |||
| 728 | data[0] = intc_mask_data(desc, d, enum_id, 0); | 850 | data[0] = intc_mask_data(desc, d, enum_id, 0); |
| 729 | data[1] = intc_prio_data(desc, d, enum_id, 0); | 851 | data[1] = intc_prio_data(desc, d, enum_id, 0); |
| 730 | 852 | ||
| @@ -749,10 +871,11 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 749 | handle_level_irq, "level"); | 871 | handle_level_irq, "level"); |
| 750 | set_irq_chip_data(irq, (void *)data[primary]); | 872 | set_irq_chip_data(irq, (void *)data[primary]); |
| 751 | 873 | ||
| 752 | /* set priority level | 874 | /* |
| 875 | * set priority level | ||
| 753 | * - this needs to be at least 2 for 5-bit priorities on 7780 | 876 | * - this needs to be at least 2 for 5-bit priorities on 7780 |
| 754 | */ | 877 | */ |
| 755 | intc_prio_level[irq] = 2; | 878 | intc_prio_level[irq] = default_prio_level; |
| 756 | 879 | ||
| 757 | /* enable secondary masking method if present */ | 880 | /* enable secondary masking method if present */ |
| 758 | if (data[!primary]) | 881 | if (data[!primary]) |
| @@ -769,7 +892,6 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 769 | * only secondary priority should access registers, so | 892 | * only secondary priority should access registers, so |
| 770 | * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() | 893 | * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() |
| 771 | */ | 894 | */ |
| 772 | |||
| 773 | hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); | 895 | hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); |
| 774 | hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); | 896 | hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); |
| 775 | } | 897 | } |
| @@ -790,6 +912,11 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 790 | if (desc->hw.ack_regs) | 912 | if (desc->hw.ack_regs) |
| 791 | ack_handle[irq] = intc_ack_data(desc, d, enum_id); | 913 | ack_handle[irq] = intc_ack_data(desc, d, enum_id); |
| 792 | 914 | ||
| 915 | #ifdef CONFIG_INTC_BALANCING | ||
| 916 | if (desc->hw.mask_regs) | ||
| 917 | dist_handle[irq] = intc_dist_data(desc, d, enum_id); | ||
| 918 | #endif | ||
| 919 | |||
| 793 | #ifdef CONFIG_ARM | 920 | #ifdef CONFIG_ARM |
| 794 | set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ | 921 | set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ |
| 795 | #endif | 922 | #endif |
| @@ -801,6 +928,8 @@ static unsigned int __init save_reg(struct intc_desc_int *d, | |||
| 801 | unsigned int smp) | 928 | unsigned int smp) |
| 802 | { | 929 | { |
| 803 | if (value) { | 930 | if (value) { |
| 931 | value = intc_phys_to_virt(d, value); | ||
| 932 | |||
| 804 | d->reg[cnt] = value; | 933 | d->reg[cnt] = value; |
| 805 | #ifdef CONFIG_SMP | 934 | #ifdef CONFIG_SMP |
| 806 | d->smp[cnt] = smp; | 935 | d->smp[cnt] = smp; |
| @@ -816,25 +945,59 @@ static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) | |||
| 816 | generic_handle_irq((unsigned int)get_irq_data(irq)); | 945 | generic_handle_irq((unsigned int)get_irq_data(irq)); |
| 817 | } | 946 | } |
| 818 | 947 | ||
| 819 | void __init register_intc_controller(struct intc_desc *desc) | 948 | int __init register_intc_controller(struct intc_desc *desc) |
| 820 | { | 949 | { |
| 821 | unsigned int i, k, smp; | 950 | unsigned int i, k, smp; |
| 822 | struct intc_hw_desc *hw = &desc->hw; | 951 | struct intc_hw_desc *hw = &desc->hw; |
| 823 | struct intc_desc_int *d; | 952 | struct intc_desc_int *d; |
| 953 | struct resource *res; | ||
| 954 | |||
| 955 | pr_info("intc: Registered controller '%s' with %u IRQs\n", | ||
| 956 | desc->name, hw->nr_vectors); | ||
| 824 | 957 | ||
| 825 | d = kzalloc(sizeof(*d), GFP_NOWAIT); | 958 | d = kzalloc(sizeof(*d), GFP_NOWAIT); |
| 959 | if (!d) | ||
| 960 | goto err0; | ||
| 826 | 961 | ||
| 827 | INIT_LIST_HEAD(&d->list); | 962 | INIT_LIST_HEAD(&d->list); |
| 828 | list_add(&d->list, &intc_list); | 963 | list_add(&d->list, &intc_list); |
| 829 | 964 | ||
| 965 | if (desc->num_resources) { | ||
| 966 | d->nr_windows = desc->num_resources; | ||
| 967 | d->window = kzalloc(d->nr_windows * sizeof(*d->window), | ||
| 968 | GFP_NOWAIT); | ||
| 969 | if (!d->window) | ||
| 970 | goto err1; | ||
| 971 | |||
| 972 | for (k = 0; k < d->nr_windows; k++) { | ||
| 973 | res = desc->resource + k; | ||
| 974 | WARN_ON(resource_type(res) != IORESOURCE_MEM); | ||
| 975 | d->window[k].phys = res->start; | ||
| 976 | d->window[k].size = resource_size(res); | ||
| 977 | d->window[k].virt = ioremap_nocache(res->start, | ||
| 978 | resource_size(res)); | ||
| 979 | if (!d->window[k].virt) | ||
| 980 | goto err2; | ||
| 981 | } | ||
| 982 | } | ||
| 983 | |||
| 830 | d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; | 984 | d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; |
| 985 | #ifdef CONFIG_INTC_BALANCING | ||
| 986 | if (d->nr_reg) | ||
| 987 | d->nr_reg += hw->nr_mask_regs; | ||
| 988 | #endif | ||
| 831 | d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; | 989 | d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; |
| 832 | d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; | 990 | d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; |
| 833 | d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; | 991 | d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; |
| 834 | 992 | ||
| 835 | d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); | 993 | d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); |
| 994 | if (!d->reg) | ||
| 995 | goto err2; | ||
| 996 | |||
| 836 | #ifdef CONFIG_SMP | 997 | #ifdef CONFIG_SMP |
| 837 | d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); | 998 | d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); |
| 999 | if (!d->smp) | ||
| 1000 | goto err3; | ||
| 838 | #endif | 1001 | #endif |
| 839 | k = 0; | 1002 | k = 0; |
| 840 | 1003 | ||
| @@ -843,12 +1006,17 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 843 | smp = IS_SMP(hw->mask_regs[i]); | 1006 | smp = IS_SMP(hw->mask_regs[i]); |
| 844 | k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); | 1007 | k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); |
| 845 | k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); | 1008 | k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); |
| 1009 | #ifdef CONFIG_INTC_BALANCING | ||
| 1010 | k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0); | ||
| 1011 | #endif | ||
| 846 | } | 1012 | } |
| 847 | } | 1013 | } |
| 848 | 1014 | ||
| 849 | if (hw->prio_regs) { | 1015 | if (hw->prio_regs) { |
| 850 | d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), | 1016 | d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), |
| 851 | GFP_NOWAIT); | 1017 | GFP_NOWAIT); |
| 1018 | if (!d->prio) | ||
| 1019 | goto err4; | ||
| 852 | 1020 | ||
| 853 | for (i = 0; i < hw->nr_prio_regs; i++) { | 1021 | for (i = 0; i < hw->nr_prio_regs; i++) { |
| 854 | smp = IS_SMP(hw->prio_regs[i]); | 1022 | smp = IS_SMP(hw->prio_regs[i]); |
| @@ -860,6 +1028,8 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 860 | if (hw->sense_regs) { | 1028 | if (hw->sense_regs) { |
| 861 | d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), | 1029 | d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), |
| 862 | GFP_NOWAIT); | 1030 | GFP_NOWAIT); |
| 1031 | if (!d->sense) | ||
| 1032 | goto err5; | ||
| 863 | 1033 | ||
| 864 | for (i = 0; i < hw->nr_sense_regs; i++) | 1034 | for (i = 0; i < hw->nr_sense_regs; i++) |
| 865 | k += save_reg(d, k, hw->sense_regs[i].reg, 0); | 1035 | k += save_reg(d, k, hw->sense_regs[i].reg, 0); |
| @@ -906,7 +1076,7 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 906 | 1076 | ||
| 907 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); | 1077 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); |
| 908 | if (unlikely(!irq_desc)) { | 1078 | if (unlikely(!irq_desc)) { |
| 909 | pr_info("can't get irq_desc for %d\n", irq); | 1079 | pr_err("can't get irq_desc for %d\n", irq); |
| 910 | continue; | 1080 | continue; |
| 911 | } | 1081 | } |
| 912 | 1082 | ||
| @@ -926,7 +1096,7 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 926 | */ | 1096 | */ |
| 927 | irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id()); | 1097 | irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id()); |
| 928 | if (unlikely(!irq_desc)) { | 1098 | if (unlikely(!irq_desc)) { |
| 929 | pr_info("can't get irq_desc for %d\n", irq2); | 1099 | pr_err("can't get irq_desc for %d\n", irq2); |
| 930 | continue; | 1100 | continue; |
| 931 | } | 1101 | } |
| 932 | 1102 | ||
| @@ -942,8 +1112,100 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 942 | /* enable bits matching force_enable after registering irqs */ | 1112 | /* enable bits matching force_enable after registering irqs */ |
| 943 | if (desc->force_enable) | 1113 | if (desc->force_enable) |
| 944 | intc_enable_disable_enum(desc, d, desc->force_enable, 1); | 1114 | intc_enable_disable_enum(desc, d, desc->force_enable, 1); |
| 1115 | |||
| 1116 | return 0; | ||
| 1117 | err5: | ||
| 1118 | kfree(d->prio); | ||
| 1119 | err4: | ||
| 1120 | #ifdef CONFIG_SMP | ||
| 1121 | kfree(d->smp); | ||
| 1122 | err3: | ||
| 1123 | #endif | ||
| 1124 | kfree(d->reg); | ||
| 1125 | err2: | ||
| 1126 | for (k = 0; k < d->nr_windows; k++) | ||
| 1127 | if (d->window[k].virt) | ||
| 1128 | iounmap(d->window[k].virt); | ||
| 1129 | |||
| 1130 | kfree(d->window); | ||
| 1131 | err1: | ||
| 1132 | kfree(d); | ||
| 1133 | err0: | ||
| 1134 | pr_err("unable to allocate INTC memory\n"); | ||
| 1135 | |||
| 1136 | return -ENOMEM; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | #ifdef CONFIG_INTC_USERIMASK | ||
| 1140 | static void __iomem *uimask; | ||
| 1141 | |||
| 1142 | int register_intc_userimask(unsigned long addr) | ||
| 1143 | { | ||
| 1144 | if (unlikely(uimask)) | ||
| 1145 | return -EBUSY; | ||
| 1146 | |||
| 1147 | uimask = ioremap_nocache(addr, SZ_4K); | ||
| 1148 | if (unlikely(!uimask)) | ||
| 1149 | return -ENOMEM; | ||
| 1150 | |||
| 1151 | pr_info("intc: userimask support registered for levels 0 -> %d\n", | ||
| 1152 | default_prio_level - 1); | ||
| 1153 | |||
| 1154 | return 0; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | static ssize_t | ||
| 1158 | show_intc_userimask(struct sysdev_class *cls, | ||
| 1159 | struct sysdev_class_attribute *attr, char *buf) | ||
| 1160 | { | ||
| 1161 | return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static ssize_t | ||
| 1165 | store_intc_userimask(struct sysdev_class *cls, | ||
| 1166 | struct sysdev_class_attribute *attr, | ||
| 1167 | const char *buf, size_t count) | ||
| 1168 | { | ||
| 1169 | unsigned long level; | ||
| 1170 | |||
| 1171 | level = simple_strtoul(buf, NULL, 10); | ||
| 1172 | |||
| 1173 | /* | ||
| 1174 | * Minimal acceptable IRQ levels are in the 2 - 16 range, but | ||
| 1175 | * these are chomped so as to not interfere with normal IRQs. | ||
| 1176 | * | ||
| 1177 | * Level 1 is a special case on some CPUs in that it's not | ||
| 1178 | * directly settable, but given that USERIMASK cuts off below a | ||
| 1179 | * certain level, we don't care about this limitation here. | ||
| 1180 | * Level 0 on the other hand equates to user masking disabled. | ||
| 1181 | * | ||
| 1182 | * We use default_prio_level as a cut off so that only special | ||
| 1183 | * case opt-in IRQs can be mangled. | ||
| 1184 | */ | ||
| 1185 | if (level >= default_prio_level) | ||
| 1186 | return -EINVAL; | ||
| 1187 | |||
| 1188 | __raw_writel(0xa5 << 24 | level << 4, uimask); | ||
| 1189 | |||
| 1190 | return count; | ||
| 945 | } | 1191 | } |
| 946 | 1192 | ||
| 1193 | static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR, | ||
| 1194 | show_intc_userimask, store_intc_userimask); | ||
| 1195 | #endif | ||
| 1196 | |||
| 1197 | static ssize_t | ||
| 1198 | show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) | ||
| 1199 | { | ||
| 1200 | struct intc_desc_int *d; | ||
| 1201 | |||
| 1202 | d = container_of(dev, struct intc_desc_int, sysdev); | ||
| 1203 | |||
| 1204 | return sprintf(buf, "%s\n", d->chip.name); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL); | ||
| 1208 | |||
| 947 | static int intc_suspend(struct sys_device *dev, pm_message_t state) | 1209 | static int intc_suspend(struct sys_device *dev, pm_message_t state) |
| 948 | { | 1210 | { |
| 949 | struct intc_desc_int *d; | 1211 | struct intc_desc_int *d; |
| @@ -1003,19 +1265,28 @@ static int __init register_intc_sysdevs(void) | |||
| 1003 | int id = 0; | 1265 | int id = 0; |
| 1004 | 1266 | ||
| 1005 | error = sysdev_class_register(&intc_sysdev_class); | 1267 | error = sysdev_class_register(&intc_sysdev_class); |
| 1268 | #ifdef CONFIG_INTC_USERIMASK | ||
| 1269 | if (!error && uimask) | ||
| 1270 | error = sysdev_class_create_file(&intc_sysdev_class, | ||
| 1271 | &attr_userimask); | ||
| 1272 | #endif | ||
| 1006 | if (!error) { | 1273 | if (!error) { |
| 1007 | list_for_each_entry(d, &intc_list, list) { | 1274 | list_for_each_entry(d, &intc_list, list) { |
| 1008 | d->sysdev.id = id; | 1275 | d->sysdev.id = id; |
| 1009 | d->sysdev.cls = &intc_sysdev_class; | 1276 | d->sysdev.cls = &intc_sysdev_class; |
| 1010 | error = sysdev_register(&d->sysdev); | 1277 | error = sysdev_register(&d->sysdev); |
| 1278 | if (error == 0) | ||
| 1279 | error = sysdev_create_file(&d->sysdev, | ||
| 1280 | &attr_name); | ||
| 1011 | if (error) | 1281 | if (error) |
| 1012 | break; | 1282 | break; |
| 1283 | |||
| 1013 | id++; | 1284 | id++; |
| 1014 | } | 1285 | } |
| 1015 | } | 1286 | } |
| 1016 | 1287 | ||
| 1017 | if (error) | 1288 | if (error) |
| 1018 | pr_warning("intc: sysdev registration error\n"); | 1289 | pr_err("intc: sysdev registration error\n"); |
| 1019 | 1290 | ||
| 1020 | return error; | 1291 | return error; |
| 1021 | } | 1292 | } |
| @@ -1048,7 +1319,7 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) | |||
| 1048 | 1319 | ||
| 1049 | desc = irq_to_desc_alloc_node(new, node); | 1320 | desc = irq_to_desc_alloc_node(new, node); |
| 1050 | if (unlikely(!desc)) { | 1321 | if (unlikely(!desc)) { |
| 1051 | pr_info("can't get irq_desc for %d\n", new); | 1322 | pr_err("can't get irq_desc for %d\n", new); |
| 1052 | goto out_unlock; | 1323 | goto out_unlock; |
| 1053 | } | 1324 | } |
| 1054 | 1325 | ||
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 36828358a4d8..e76b1afafe07 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
| @@ -36,8 +36,7 @@ | |||
| 36 | #include <asm/delay.h> | 36 | #include <asm/delay.h> |
| 37 | 37 | ||
| 38 | #include <mach/dma.h> | 38 | #include <mach/dma.h> |
| 39 | #include <mach/regs-ssp.h> | 39 | #include <plat/ssp.h> |
| 40 | #include <mach/ssp.h> | ||
| 41 | #include <mach/pxa2xx_spi.h> | 40 | #include <mach/pxa2xx_spi.h> |
| 42 | 41 | ||
| 43 | MODULE_AUTHOR("Stephen Street"); | 42 | MODULE_AUTHOR("Stephen Street"); |
| @@ -1318,14 +1317,14 @@ static int setup(struct spi_device *spi) | |||
| 1318 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ | 1317 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ |
| 1319 | if (drv_data->ssp_type != PXA25x_SSP) | 1318 | if (drv_data->ssp_type != PXA25x_SSP) |
| 1320 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", | 1319 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", |
| 1321 | clk_get_rate(ssp->clk) | 1320 | clk_get_rate(ssp->clk) |
| 1322 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1321 | / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)), |
| 1323 | chip->enable_dma ? "DMA" : "PIO"); | 1322 | chip->enable_dma ? "DMA" : "PIO"); |
| 1324 | else | 1323 | else |
| 1325 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", | 1324 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", |
| 1326 | clk_get_rate(ssp->clk) / 2 | 1325 | clk_get_rate(ssp->clk) / 2 |
| 1327 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1326 | / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)), |
| 1328 | chip->enable_dma ? "DMA" : "PIO"); | 1327 | chip->enable_dma ? "DMA" : "PIO"); |
| 1329 | 1328 | ||
| 1330 | if (spi->bits_per_word <= 8) { | 1329 | if (spi->bits_per_word <= 8) { |
| 1331 | chip->n_bytes = 1; | 1330 | chip->n_bytes = 1; |
| @@ -1466,7 +1465,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
| 1466 | 1465 | ||
| 1467 | platform_info = dev->platform_data; | 1466 | platform_info = dev->platform_data; |
| 1468 | 1467 | ||
| 1469 | ssp = ssp_request(pdev->id, pdev->name); | 1468 | ssp = pxa_ssp_request(pdev->id, pdev->name); |
| 1470 | if (ssp == NULL) { | 1469 | if (ssp == NULL) { |
| 1471 | dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); | 1470 | dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); |
| 1472 | return -ENODEV; | 1471 | return -ENODEV; |
| @@ -1476,7 +1475,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
| 1476 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); | 1475 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); |
| 1477 | if (!master) { | 1476 | if (!master) { |
| 1478 | dev_err(&pdev->dev, "cannot alloc spi_master\n"); | 1477 | dev_err(&pdev->dev, "cannot alloc spi_master\n"); |
| 1479 | ssp_free(ssp); | 1478 | pxa_ssp_free(ssp); |
| 1480 | return -ENOMEM; | 1479 | return -ENOMEM; |
| 1481 | } | 1480 | } |
| 1482 | drv_data = spi_master_get_devdata(master); | 1481 | drv_data = spi_master_get_devdata(master); |
| @@ -1558,7 +1557,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
| 1558 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | | 1557 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | |
| 1559 | SSCR1_TxTresh(TX_THRESH_DFLT), | 1558 | SSCR1_TxTresh(TX_THRESH_DFLT), |
| 1560 | drv_data->ioaddr); | 1559 | drv_data->ioaddr); |
| 1561 | write_SSCR0(SSCR0_SerClkDiv(2) | 1560 | write_SSCR0(SSCR0_SCR(2) |
| 1562 | | SSCR0_Motorola | 1561 | | SSCR0_Motorola |
| 1563 | | SSCR0_DataSize(8), | 1562 | | SSCR0_DataSize(8), |
| 1564 | drv_data->ioaddr); | 1563 | drv_data->ioaddr); |
| @@ -1605,7 +1604,7 @@ out_error_irq_alloc: | |||
| 1605 | 1604 | ||
| 1606 | out_error_master_alloc: | 1605 | out_error_master_alloc: |
| 1607 | spi_master_put(master); | 1606 | spi_master_put(master); |
| 1608 | ssp_free(ssp); | 1607 | pxa_ssp_free(ssp); |
| 1609 | return status; | 1608 | return status; |
| 1610 | } | 1609 | } |
| 1611 | 1610 | ||
| @@ -1649,7 +1648,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) | |||
| 1649 | free_irq(ssp->irq, drv_data); | 1648 | free_irq(ssp->irq, drv_data); |
| 1650 | 1649 | ||
| 1651 | /* Release SSP */ | 1650 | /* Release SSP */ |
| 1652 | ssp_free(ssp); | 1651 | pxa_ssp_free(ssp); |
| 1653 | 1652 | ||
| 1654 | /* Disconnect from the SPI framework */ | 1653 | /* Disconnect from the SPI framework */ |
| 1655 | spi_unregister_master(drv_data->master); | 1654 | spi_unregister_master(drv_data->master); |
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index df1bae9b048e..eaa79c8a9b8c 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
| @@ -366,6 +366,13 @@ rescan: | |||
| 366 | if (is_done) | 366 | if (is_done) |
| 367 | done(ep, req, 0); | 367 | done(ep, req, 0); |
| 368 | else if (ep->is_pingpong) { | 368 | else if (ep->is_pingpong) { |
| 369 | /* | ||
| 370 | * One dummy read to delay the code because of a HW glitch: | ||
| 371 | * CSR returns bad RXCOUNT when read too soon after updating | ||
| 372 | * RX_DATA_BK flags. | ||
| 373 | */ | ||
| 374 | csr = __raw_readl(creg); | ||
| 375 | |||
| 369 | bufferspace -= count; | 376 | bufferspace -= count; |
| 370 | buf += count; | 377 | buf += count; |
| 371 | goto rescan; | 378 | goto rescan; |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index dca48df98444..e5d6b56d4447 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
| @@ -50,8 +50,9 @@ | |||
| 50 | #include <linux/fb.h> | 50 | #include <linux/fb.h> |
| 51 | #include <linux/init.h> | 51 | #include <linux/init.h> |
| 52 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
| 53 | 53 | #include <linux/platform_device.h> | |
| 54 | #include <linux/uaccess.h> | 54 | #include <linux/uaccess.h> |
| 55 | |||
| 55 | #include <asm/system.h> | 56 | #include <asm/system.h> |
| 56 | #include <asm/irq.h> | 57 | #include <asm/irq.h> |
| 57 | #include <asm/amigahw.h> | 58 | #include <asm/amigahw.h> |
| @@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg | |||
| 1135 | * Interface to the low level console driver | 1136 | * Interface to the low level console driver |
| 1136 | */ | 1137 | */ |
| 1137 | 1138 | ||
| 1138 | static void amifb_deinit(void); | 1139 | static void amifb_deinit(struct platform_device *pdev); |
| 1139 | 1140 | ||
| 1140 | /* | 1141 | /* |
| 1141 | * Internal routines | 1142 | * Internal routines |
| @@ -2246,7 +2247,7 @@ static inline void chipfree(void) | |||
| 2246 | * Initialisation | 2247 | * Initialisation |
| 2247 | */ | 2248 | */ |
| 2248 | 2249 | ||
| 2249 | static int __init amifb_init(void) | 2250 | static int __init amifb_probe(struct platform_device *pdev) |
| 2250 | { | 2251 | { |
| 2251 | int tag, i, err = 0; | 2252 | int tag, i, err = 0; |
| 2252 | u_long chipptr; | 2253 | u_long chipptr; |
| @@ -2261,16 +2262,6 @@ static int __init amifb_init(void) | |||
| 2261 | } | 2262 | } |
| 2262 | amifb_setup(option); | 2263 | amifb_setup(option); |
| 2263 | #endif | 2264 | #endif |
| 2264 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) | ||
| 2265 | return -ENODEV; | ||
| 2266 | |||
| 2267 | /* | ||
| 2268 | * We request all registers starting from bplpt[0] | ||
| 2269 | */ | ||
| 2270 | if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, | ||
| 2271 | "amifb [Denise/Lisa]")) | ||
| 2272 | return -EBUSY; | ||
| 2273 | |||
| 2274 | custom.dmacon = DMAF_ALL | DMAF_MASTER; | 2265 | custom.dmacon = DMAF_ALL | DMAF_MASTER; |
| 2275 | 2266 | ||
| 2276 | switch (amiga_chipset) { | 2267 | switch (amiga_chipset) { |
| @@ -2377,6 +2368,7 @@ default_chipset: | |||
| 2377 | fb_info.fbops = &amifb_ops; | 2368 | fb_info.fbops = &amifb_ops; |
| 2378 | fb_info.par = ¤tpar; | 2369 | fb_info.par = ¤tpar; |
| 2379 | fb_info.flags = FBINFO_DEFAULT; | 2370 | fb_info.flags = FBINFO_DEFAULT; |
| 2371 | fb_info.device = &pdev->dev; | ||
| 2380 | 2372 | ||
| 2381 | if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, | 2373 | if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, |
| 2382 | NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { | 2374 | NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { |
| @@ -2451,18 +2443,18 @@ default_chipset: | |||
| 2451 | return 0; | 2443 | return 0; |
| 2452 | 2444 | ||
| 2453 | amifb_error: | 2445 | amifb_error: |
| 2454 | amifb_deinit(); | 2446 | amifb_deinit(pdev); |
| 2455 | return err; | 2447 | return err; |
| 2456 | } | 2448 | } |
| 2457 | 2449 | ||
| 2458 | static void amifb_deinit(void) | 2450 | static void amifb_deinit(struct platform_device *pdev) |
| 2459 | { | 2451 | { |
| 2460 | if (fb_info.cmap.len) | 2452 | if (fb_info.cmap.len) |
| 2461 | fb_dealloc_cmap(&fb_info.cmap); | 2453 | fb_dealloc_cmap(&fb_info.cmap); |
| 2454 | fb_dealloc_cmap(&fb_info.cmap); | ||
| 2462 | chipfree(); | 2455 | chipfree(); |
| 2463 | if (videomemory) | 2456 | if (videomemory) |
| 2464 | iounmap((void*)videomemory); | 2457 | iounmap((void*)videomemory); |
| 2465 | release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); | ||
| 2466 | custom.dmacon = DMAF_ALL | DMAF_MASTER; | 2458 | custom.dmacon = DMAF_ALL | DMAF_MASTER; |
| 2467 | } | 2459 | } |
| 2468 | 2460 | ||
| @@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void) | |||
| 3794 | } | 3786 | } |
| 3795 | } | 3787 | } |
| 3796 | 3788 | ||
| 3797 | static void __exit amifb_exit(void) | 3789 | static int __exit amifb_remove(struct platform_device *pdev) |
| 3798 | { | 3790 | { |
| 3799 | unregister_framebuffer(&fb_info); | 3791 | unregister_framebuffer(&fb_info); |
| 3800 | amifb_deinit(); | 3792 | amifb_deinit(pdev); |
| 3801 | amifb_video_off(); | 3793 | amifb_video_off(); |
| 3794 | return 0; | ||
| 3795 | } | ||
| 3796 | |||
| 3797 | static struct platform_driver amifb_driver = { | ||
| 3798 | .remove = __exit_p(amifb_remove), | ||
| 3799 | .driver = { | ||
| 3800 | .name = "amiga-video", | ||
| 3801 | .owner = THIS_MODULE, | ||
| 3802 | }, | ||
| 3803 | }; | ||
| 3804 | |||
| 3805 | static int __init amifb_init(void) | ||
| 3806 | { | ||
| 3807 | return platform_driver_probe(&amifb_driver, amifb_probe); | ||
| 3802 | } | 3808 | } |
| 3803 | 3809 | ||
| 3804 | module_init(amifb_init); | 3810 | module_init(amifb_init); |
| 3811 | |||
| 3812 | static void __exit amifb_exit(void) | ||
| 3813 | { | ||
| 3814 | platform_driver_unregister(&amifb_driver); | ||
| 3815 | } | ||
| 3816 | |||
| 3805 | module_exit(amifb_exit); | 3817 | module_exit(amifb_exit); |
| 3806 | 3818 | ||
| 3807 | MODULE_LICENSE("GPL"); | 3819 | MODULE_LICENSE("GPL"); |
| 3820 | MODULE_ALIAS("platform:amiga-video"); | ||
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8d8dfda2f868..6df7c54db0a3 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
| @@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = { | |||
| 299 | }, | 299 | }, |
| 300 | { 0 } | 300 | { 0 } |
| 301 | }; | 301 | }; |
| 302 | MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); | ||
| 302 | 303 | ||
| 303 | static const struct { | 304 | static const struct { |
| 304 | zorro_id id2; | 305 | zorro_id id2; |
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61cdb63..1b0feb8e7244 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c | |||
| @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = { | |||
| 219 | { ZORRO_PROD_HELFRICH_RAINBOW_II }, | 219 | { ZORRO_PROD_HELFRICH_RAINBOW_II }, |
| 220 | { 0 } | 220 | { 0 } |
| 221 | }; | 221 | }; |
| 222 | MODULE_DEVICE_TABLE(zorro, fm2fb_devices); | ||
| 222 | 223 | ||
| 223 | static struct zorro_driver fm2fb_driver = { | 224 | static struct zorro_driver fm2fb_driver = { |
| 224 | .name = "fm2fb", | 225 | .name = "fm2fb", |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 2ac4440e7b08..8943b8ccee1a 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -80,12 +80,6 @@ static void do_suspend(void) | |||
| 80 | 80 | ||
| 81 | shutting_down = SHUTDOWN_SUSPEND; | 81 | shutting_down = SHUTDOWN_SUSPEND; |
| 82 | 82 | ||
| 83 | err = stop_machine_create(); | ||
| 84 | if (err) { | ||
| 85 | printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | |||
| 89 | #ifdef CONFIG_PREEMPT | 83 | #ifdef CONFIG_PREEMPT |
| 90 | /* If the kernel is preemptible, we need to freeze all the processes | 84 | /* If the kernel is preemptible, we need to freeze all the processes |
| 91 | to prevent them from being in the middle of a pagetable update | 85 | to prevent them from being in the middle of a pagetable update |
| @@ -93,7 +87,7 @@ static void do_suspend(void) | |||
| 93 | err = freeze_processes(); | 87 | err = freeze_processes(); |
| 94 | if (err) { | 88 | if (err) { |
| 95 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); | 89 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); |
| 96 | goto out_destroy_sm; | 90 | goto out; |
| 97 | } | 91 | } |
| 98 | #endif | 92 | #endif |
| 99 | 93 | ||
| @@ -136,12 +130,8 @@ out_resume: | |||
| 136 | out_thaw: | 130 | out_thaw: |
| 137 | #ifdef CONFIG_PREEMPT | 131 | #ifdef CONFIG_PREEMPT |
| 138 | thaw_processes(); | 132 | thaw_processes(); |
| 139 | |||
| 140 | out_destroy_sm: | ||
| 141 | #endif | ||
| 142 | stop_machine_destroy(); | ||
| 143 | |||
| 144 | out: | 133 | out: |
| 134 | #endif | ||
| 145 | shutting_down = SHUTDOWN_INVALID; | 135 | shutting_down = SHUTDOWN_INVALID; |
| 146 | } | 136 | } |
| 147 | #endif /* CONFIG_PM_SLEEP */ | 137 | #endif /* CONFIG_PM_SLEEP */ |
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index d47c47fc048f..3c7046d79654 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c | |||
| @@ -97,7 +97,7 @@ static void zorro_seq_stop(struct seq_file *m, void *v) | |||
| 97 | 97 | ||
| 98 | static int zorro_seq_show(struct seq_file *m, void *v) | 98 | static int zorro_seq_show(struct seq_file *m, void *v) |
| 99 | { | 99 | { |
| 100 | u_int slot = *(loff_t *)v; | 100 | unsigned int slot = *(loff_t *)v; |
| 101 | struct zorro_dev *z = &zorro_autocon[slot]; | 101 | struct zorro_dev *z = &zorro_autocon[slot]; |
| 102 | 102 | ||
| 103 | seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, | 103 | seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, |
| @@ -129,7 +129,7 @@ static const struct file_operations zorro_devices_proc_fops = { | |||
| 129 | 129 | ||
| 130 | static struct proc_dir_entry *proc_bus_zorro_dir; | 130 | static struct proc_dir_entry *proc_bus_zorro_dir; |
| 131 | 131 | ||
| 132 | static int __init zorro_proc_attach_device(u_int slot) | 132 | static int __init zorro_proc_attach_device(unsigned int slot) |
| 133 | { | 133 | { |
| 134 | struct proc_dir_entry *entry; | 134 | struct proc_dir_entry *entry; |
| 135 | char name[4]; | 135 | char name[4]; |
| @@ -146,7 +146,7 @@ static int __init zorro_proc_attach_device(u_int slot) | |||
| 146 | 146 | ||
| 147 | static int __init zorro_proc_init(void) | 147 | static int __init zorro_proc_init(void) |
| 148 | { | 148 | { |
| 149 | u_int slot; | 149 | unsigned int slot; |
| 150 | 150 | ||
| 151 | if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { | 151 | if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { |
| 152 | proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); | 152 | proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); |
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 53180a37cc9a..7ee2b6e71786 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c | |||
| @@ -137,10 +137,34 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) | |||
| 137 | return 0; | 137 | return 0; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 141 | { | ||
| 142 | #ifdef CONFIG_HOTPLUG | ||
| 143 | struct zorro_dev *z; | ||
| 144 | |||
| 145 | if (!dev) | ||
| 146 | return -ENODEV; | ||
| 147 | |||
| 148 | z = to_zorro_dev(dev); | ||
| 149 | if (!z) | ||
| 150 | return -ENODEV; | ||
| 151 | |||
| 152 | if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || | ||
| 153 | add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || | ||
| 154 | add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || | ||
| 155 | add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) | ||
| 156 | return -ENOMEM; | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | #else /* !CONFIG_HOTPLUG */ | ||
| 160 | return -ENODEV; | ||
| 161 | #endif /* !CONFIG_HOTPLUG */ | ||
| 162 | } | ||
| 140 | 163 | ||
| 141 | struct bus_type zorro_bus_type = { | 164 | struct bus_type zorro_bus_type = { |
| 142 | .name = "zorro", | 165 | .name = "zorro", |
| 143 | .match = zorro_bus_match, | 166 | .match = zorro_bus_match, |
| 167 | .uevent = zorro_uevent, | ||
| 144 | .probe = zorro_device_probe, | 168 | .probe = zorro_device_probe, |
| 145 | .remove = zorro_device_remove, | 169 | .remove = zorro_device_remove, |
| 146 | }; | 170 | }; |
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 1d2a772ea14c..eb924e0a64ce 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c | |||
| @@ -77,6 +77,16 @@ static struct bin_attribute zorro_config_attr = { | |||
| 77 | .read = zorro_read_config, | 77 | .read = zorro_read_config, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | ||
| 81 | char *buf) | ||
| 82 | { | ||
| 83 | struct zorro_dev *z = to_zorro_dev(dev); | ||
| 84 | |||
| 85 | return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id); | ||
| 86 | } | ||
| 87 | |||
| 88 | static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL); | ||
| 89 | |||
| 80 | int zorro_create_sysfs_dev_files(struct zorro_dev *z) | 90 | int zorro_create_sysfs_dev_files(struct zorro_dev *z) |
| 81 | { | 91 | { |
| 82 | struct device *dev = &z->dev; | 92 | struct device *dev = &z->dev; |
| @@ -89,6 +99,7 @@ int zorro_create_sysfs_dev_files(struct zorro_dev *z) | |||
| 89 | (error = device_create_file(dev, &dev_attr_slotaddr)) || | 99 | (error = device_create_file(dev, &dev_attr_slotaddr)) || |
| 90 | (error = device_create_file(dev, &dev_attr_slotsize)) || | 100 | (error = device_create_file(dev, &dev_attr_slotsize)) || |
| 91 | (error = device_create_file(dev, &dev_attr_resource)) || | 101 | (error = device_create_file(dev, &dev_attr_resource)) || |
| 102 | (error = device_create_file(dev, &dev_attr_modalias)) || | ||
| 92 | (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) | 103 | (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) |
| 93 | return error; | 104 | return error; |
| 94 | 105 | ||
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index d45fb34e2d23..6455f3a244c5 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <linux/zorro.h> | 15 | #include <linux/zorro.h> |
| 16 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
| 17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/slab.h> | ||
| 18 | 20 | ||
| 19 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
| 20 | #include <asm/amigahw.h> | 22 | #include <asm/amigahw.h> |
| @@ -26,24 +28,17 @@ | |||
| 26 | * Zorro Expansion Devices | 28 | * Zorro Expansion Devices |
| 27 | */ | 29 | */ |
| 28 | 30 | ||
| 29 | u_int zorro_num_autocon = 0; | 31 | unsigned int zorro_num_autocon; |
| 30 | struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | 32 | struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; |
| 31 | 33 | ||
| 32 | 34 | ||
| 33 | /* | 35 | /* |
| 34 | * Single Zorro bus | 36 | * Zorro bus |
| 35 | */ | 37 | */ |
| 36 | 38 | ||
| 37 | struct zorro_bus zorro_bus = {\ | 39 | struct zorro_bus { |
| 38 | .resources = { | 40 | struct list_head devices; /* list of devices on this bus */ |
| 39 | /* Zorro II regions (on Zorro II/III) */ | 41 | struct device dev; |
| 40 | { .name = "Zorro II exp", .start = 0x00e80000, .end = 0x00efffff }, | ||
| 41 | { .name = "Zorro II mem", .start = 0x00200000, .end = 0x009fffff }, | ||
| 42 | /* Zorro III regions (on Zorro III only) */ | ||
| 43 | { .name = "Zorro III exp", .start = 0xff000000, .end = 0xffffffff }, | ||
| 44 | { .name = "Zorro III cfg", .start = 0x40000000, .end = 0x7fffffff } | ||
| 45 | }, | ||
| 46 | .name = "Zorro bus" | ||
| 47 | }; | 42 | }; |
| 48 | 43 | ||
| 49 | 44 | ||
| @@ -53,18 +48,19 @@ struct zorro_bus zorro_bus = {\ | |||
| 53 | 48 | ||
| 54 | struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) | 49 | struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) |
| 55 | { | 50 | { |
| 56 | struct zorro_dev *z; | 51 | struct zorro_dev *z; |
| 57 | 52 | ||
| 58 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) | 53 | if (!zorro_num_autocon) |
| 59 | return NULL; | 54 | return NULL; |
| 60 | 55 | ||
| 61 | for (z = from ? from+1 : &zorro_autocon[0]; | 56 | for (z = from ? from+1 : &zorro_autocon[0]; |
| 62 | z < zorro_autocon+zorro_num_autocon; | 57 | z < zorro_autocon+zorro_num_autocon; |
| 63 | z++) | 58 | z++) |
| 64 | if (id == ZORRO_WILDCARD || id == z->id) | 59 | if (id == ZORRO_WILDCARD || id == z->id) |
| 65 | return z; | 60 | return z; |
| 66 | return NULL; | 61 | return NULL; |
| 67 | } | 62 | } |
| 63 | EXPORT_SYMBOL(zorro_find_device); | ||
| 68 | 64 | ||
| 69 | 65 | ||
| 70 | /* | 66 | /* |
| @@ -83,121 +79,138 @@ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) | |||
| 83 | */ | 79 | */ |
| 84 | 80 | ||
| 85 | DECLARE_BITMAP(zorro_unused_z2ram, 128); | 81 | DECLARE_BITMAP(zorro_unused_z2ram, 128); |
| 82 | EXPORT_SYMBOL(zorro_unused_z2ram); | ||
| 86 | 83 | ||
| 87 | 84 | ||
| 88 | static void __init mark_region(unsigned long start, unsigned long end, | 85 | static void __init mark_region(unsigned long start, unsigned long end, |
| 89 | int flag) | 86 | int flag) |
| 90 | { | 87 | { |
| 91 | if (flag) | ||
| 92 | start += Z2RAM_CHUNKMASK; | ||
| 93 | else | ||
| 94 | end += Z2RAM_CHUNKMASK; | ||
| 95 | start &= ~Z2RAM_CHUNKMASK; | ||
| 96 | end &= ~Z2RAM_CHUNKMASK; | ||
| 97 | |||
| 98 | if (end <= Z2RAM_START || start >= Z2RAM_END) | ||
| 99 | return; | ||
| 100 | start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; | ||
| 101 | end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; | ||
| 102 | while (start < end) { | ||
| 103 | u32 chunk = start>>Z2RAM_CHUNKSHIFT; | ||
| 104 | if (flag) | 88 | if (flag) |
| 105 | set_bit(chunk, zorro_unused_z2ram); | 89 | start += Z2RAM_CHUNKMASK; |
| 106 | else | 90 | else |
| 107 | clear_bit(chunk, zorro_unused_z2ram); | 91 | end += Z2RAM_CHUNKMASK; |
| 108 | start += Z2RAM_CHUNKSIZE; | 92 | start &= ~Z2RAM_CHUNKMASK; |
| 109 | } | 93 | end &= ~Z2RAM_CHUNKMASK; |
| 94 | |||
| 95 | if (end <= Z2RAM_START || start >= Z2RAM_END) | ||
| 96 | return; | ||
| 97 | start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; | ||
| 98 | end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; | ||
| 99 | while (start < end) { | ||
| 100 | u32 chunk = start>>Z2RAM_CHUNKSHIFT; | ||
| 101 | if (flag) | ||
| 102 | set_bit(chunk, zorro_unused_z2ram); | ||
| 103 | else | ||
| 104 | clear_bit(chunk, zorro_unused_z2ram); | ||
| 105 | start += Z2RAM_CHUNKSIZE; | ||
| 106 | } | ||
| 110 | } | 107 | } |
| 111 | 108 | ||
| 112 | 109 | ||
| 113 | static struct resource __init *zorro_find_parent_resource(struct zorro_dev *z) | 110 | static struct resource __init *zorro_find_parent_resource( |
| 111 | struct platform_device *bridge, struct zorro_dev *z) | ||
| 114 | { | 112 | { |
| 115 | int i; | 113 | int i; |
| 116 | 114 | ||
| 117 | for (i = 0; i < zorro_bus.num_resources; i++) | 115 | for (i = 0; i < bridge->num_resources; i++) { |
| 118 | if (zorro_resource_start(z) >= zorro_bus.resources[i].start && | 116 | struct resource *r = &bridge->resource[i]; |
| 119 | zorro_resource_end(z) <= zorro_bus.resources[i].end) | 117 | if (zorro_resource_start(z) >= r->start && |
| 120 | return &zorro_bus.resources[i]; | 118 | zorro_resource_end(z) <= r->end) |
| 121 | return &iomem_resource; | 119 | return r; |
| 120 | } | ||
| 121 | return &iomem_resource; | ||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | 124 | ||
| 125 | /* | ||
| 126 | * Initialization | ||
| 127 | */ | ||
| 128 | 125 | ||
| 129 | static int __init zorro_init(void) | 126 | static int __init amiga_zorro_probe(struct platform_device *pdev) |
| 130 | { | 127 | { |
| 131 | struct zorro_dev *z; | 128 | struct zorro_bus *bus; |
| 132 | unsigned int i; | 129 | struct zorro_dev *z; |
| 133 | int error; | 130 | struct resource *r; |
| 134 | 131 | unsigned int i; | |
| 135 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) | 132 | int error; |
| 136 | return 0; | 133 | |
| 137 | 134 | /* Initialize the Zorro bus */ | |
| 138 | pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n", | 135 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); |
| 139 | zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); | 136 | if (!bus) |
| 140 | 137 | return -ENOMEM; | |
| 141 | /* Initialize the Zorro bus */ | 138 | |
| 142 | INIT_LIST_HEAD(&zorro_bus.devices); | 139 | INIT_LIST_HEAD(&bus->devices); |
| 143 | dev_set_name(&zorro_bus.dev, "zorro"); | 140 | bus->dev.parent = &pdev->dev; |
| 144 | error = device_register(&zorro_bus.dev); | 141 | dev_set_name(&bus->dev, "zorro"); |
| 145 | if (error) { | 142 | error = device_register(&bus->dev); |
| 146 | pr_err("Zorro: Error registering zorro_bus\n"); | ||
| 147 | return error; | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Request the resources */ | ||
| 151 | zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2; | ||
| 152 | for (i = 0; i < zorro_bus.num_resources; i++) | ||
| 153 | request_resource(&iomem_resource, &zorro_bus.resources[i]); | ||
| 154 | |||
| 155 | /* Register all devices */ | ||
| 156 | for (i = 0; i < zorro_num_autocon; i++) { | ||
| 157 | z = &zorro_autocon[i]; | ||
| 158 | z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); | ||
| 159 | if (z->id == ZORRO_PROD_GVP_EPC_BASE) { | ||
| 160 | /* GVP quirk */ | ||
| 161 | unsigned long magic = zorro_resource_start(z)+0x8000; | ||
| 162 | z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; | ||
| 163 | } | ||
| 164 | sprintf(z->name, "Zorro device %08x", z->id); | ||
| 165 | zorro_name_device(z); | ||
| 166 | z->resource.name = z->name; | ||
| 167 | if (request_resource(zorro_find_parent_resource(z), &z->resource)) | ||
| 168 | pr_err("Zorro: Address space collision on device %s %pR\n", | ||
| 169 | z->name, &z->resource); | ||
| 170 | dev_set_name(&z->dev, "%02x", i); | ||
| 171 | z->dev.parent = &zorro_bus.dev; | ||
| 172 | z->dev.bus = &zorro_bus_type; | ||
| 173 | error = device_register(&z->dev); | ||
| 174 | if (error) { | 143 | if (error) { |
| 175 | pr_err("Zorro: Error registering device %s\n", z->name); | 144 | pr_err("Zorro: Error registering zorro_bus\n"); |
| 176 | continue; | 145 | kfree(bus); |
| 146 | return error; | ||
| 177 | } | 147 | } |
| 178 | error = zorro_create_sysfs_dev_files(z); | 148 | platform_set_drvdata(pdev, bus); |
| 179 | if (error) | 149 | |
| 180 | dev_err(&z->dev, "Error creating sysfs files\n"); | 150 | /* Register all devices */ |
| 181 | } | 151 | pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", |
| 182 | 152 | zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); | |
| 183 | /* Mark all available Zorro II memory */ | 153 | |
| 184 | zorro_for_each_dev(z) { | 154 | for (i = 0; i < zorro_num_autocon; i++) { |
| 185 | if (z->rom.er_Type & ERTF_MEMLIST) | 155 | z = &zorro_autocon[i]; |
| 186 | mark_region(zorro_resource_start(z), zorro_resource_end(z)+1, 1); | 156 | z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); |
| 187 | } | 157 | if (z->id == ZORRO_PROD_GVP_EPC_BASE) { |
| 188 | 158 | /* GVP quirk */ | |
| 189 | /* Unmark all used Zorro II memory */ | 159 | unsigned long magic = zorro_resource_start(z)+0x8000; |
| 190 | for (i = 0; i < m68k_num_memory; i++) | 160 | z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; |
| 191 | if (m68k_memory[i].addr < 16*1024*1024) | 161 | } |
| 192 | mark_region(m68k_memory[i].addr, | 162 | sprintf(z->name, "Zorro device %08x", z->id); |
| 193 | m68k_memory[i].addr+m68k_memory[i].size, 0); | 163 | zorro_name_device(z); |
| 194 | 164 | z->resource.name = z->name; | |
| 195 | return 0; | 165 | r = zorro_find_parent_resource(pdev, z); |
| 166 | error = request_resource(r, &z->resource); | ||
| 167 | if (error) | ||
| 168 | dev_err(&bus->dev, | ||
| 169 | "Address space collision on device %s %pR\n", | ||
| 170 | z->name, &z->resource); | ||
| 171 | dev_set_name(&z->dev, "%02x", i); | ||
| 172 | z->dev.parent = &bus->dev; | ||
| 173 | z->dev.bus = &zorro_bus_type; | ||
| 174 | error = device_register(&z->dev); | ||
| 175 | if (error) { | ||
| 176 | dev_err(&bus->dev, "Error registering device %s\n", | ||
| 177 | z->name); | ||
| 178 | continue; | ||
| 179 | } | ||
| 180 | error = zorro_create_sysfs_dev_files(z); | ||
| 181 | if (error) | ||
| 182 | dev_err(&z->dev, "Error creating sysfs files\n"); | ||
| 183 | } | ||
| 184 | |||
| 185 | /* Mark all available Zorro II memory */ | ||
| 186 | zorro_for_each_dev(z) { | ||
| 187 | if (z->rom.er_Type & ERTF_MEMLIST) | ||
| 188 | mark_region(zorro_resource_start(z), | ||
| 189 | zorro_resource_end(z)+1, 1); | ||
| 190 | } | ||
| 191 | |||
| 192 | /* Unmark all used Zorro II memory */ | ||
| 193 | for (i = 0; i < m68k_num_memory; i++) | ||
| 194 | if (m68k_memory[i].addr < 16*1024*1024) | ||
| 195 | mark_region(m68k_memory[i].addr, | ||
| 196 | m68k_memory[i].addr+m68k_memory[i].size, | ||
| 197 | 0); | ||
| 198 | |||
| 199 | return 0; | ||
| 196 | } | 200 | } |
| 197 | 201 | ||
| 198 | subsys_initcall(zorro_init); | 202 | static struct platform_driver amiga_zorro_driver = { |
| 203 | .driver = { | ||
| 204 | .name = "amiga-zorro", | ||
| 205 | .owner = THIS_MODULE, | ||
| 206 | }, | ||
| 207 | }; | ||
| 199 | 208 | ||
| 200 | EXPORT_SYMBOL(zorro_find_device); | 209 | static int __init amiga_zorro_init(void) |
| 201 | EXPORT_SYMBOL(zorro_unused_z2ram); | 210 | { |
| 211 | return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); | ||
| 212 | } | ||
| 213 | |||
| 214 | module_init(amiga_zorro_init); | ||
| 202 | 215 | ||
| 203 | MODULE_LICENSE("GPL"); | 216 | MODULE_LICENSE("GPL"); |
