diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-12 14:40:55 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-12 14:40:55 -0400 |
| commit | 07104839597803ccd9b2c4f543ee4651522b4aa1 (patch) | |
| tree | b3b569c955fb7abe10d1b89139c0f4a388933609 /drivers | |
| parent | 589acce53e235055806e81e330af1e8f115bfcc2 (diff) | |
| parent | 56c5d900dbb8e042bfad035d18433476931d8f93 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6: (180 commits)
leo: disable cursor when leaving graphics mode
cg6: disable cursor when leaving graphics mode
sparc32: sun4m interrupt mask cleanup
drivers/rtc/Kconfig: don't build rtc-cmos.o on sparc32
sparc: arch/sparc/kernel/pmc.c -- extra #include?
sparc32: Add more extensive documentation of sun4m interrupts.
sparc32: Kill irq_rcvreg from sun4m_irq.c
sparc32: Delete master_l10_limit.
sparc32: Use PROM device probing for sun4c timers.
sparc32: Use PROM device probing for sun4c interrupt register.
sparc32: Delete claim_ticker14().
sparc32: Stop calling claim_ticker14() from sun4c_irq.c
sparc32: Kill clear_profile_irq btfixup entry.
sparc32: Call sun4m_clear_profile_irq() directly from sun4m_smp.c
sparc32: Remove #if 0'd code from sun4c_irq.c
sparc32: Remove some SMP ifdefs in sun4d_irq.c
sparc32: Use PROM infrastructure for probing and mapping sun4d timers.
sparc32: Use PROM device probing for sun4m irq registers.
sparc32: Use PROM device probing for sun4m timer registers.
sparc: Fix user_regset 'n' field values.
...
Diffstat (limited to 'drivers')
72 files changed, 3677 insertions, 5893 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index f17cd4b572f8..78fbec8ceda0 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
| @@ -7,7 +7,6 @@ menuconfig ATA | |||
| 7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
| 8 | depends on BLOCK | 8 | depends on BLOCK |
| 9 | depends on !(M32R || M68K) || BROKEN | 9 | depends on !(M32R || M68K) || BROKEN |
| 10 | depends on !SUN4 || BROKEN | ||
| 11 | select SCSI | 10 | select SCSI |
| 12 | ---help--- | 11 | ---help--- |
| 13 | If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or | 12 | If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or |
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 73338d231db9..937c9c0ef4c9 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c | |||
| @@ -47,8 +47,9 @@ | |||
| 47 | #include <asm/atomic.h> | 47 | #include <asm/atomic.h> |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_SBUS | 49 | #ifdef CONFIG_SBUS |
| 50 | #include <linux/of.h> | ||
| 51 | #include <linux/of_device.h> | ||
| 50 | #include <asm/idprom.h> | 52 | #include <asm/idprom.h> |
| 51 | #include <asm/sbus.h> | ||
| 52 | #include <asm/openprom.h> | 53 | #include <asm/openprom.h> |
| 53 | #include <asm/oplib.h> | 54 | #include <asm/oplib.h> |
| 54 | #include <asm/pgtable.h> | 55 | #include <asm/pgtable.h> |
| @@ -661,249 +662,189 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page) | |||
| 661 | 662 | ||
| 662 | #ifdef CONFIG_SBUS | 663 | #ifdef CONFIG_SBUS |
| 663 | 664 | ||
| 664 | static u32 | 665 | static u32 fore200e_sba_read(volatile u32 __iomem *addr) |
| 665 | fore200e_sba_read(volatile u32 __iomem *addr) | ||
| 666 | { | 666 | { |
| 667 | return sbus_readl(addr); | 667 | return sbus_readl(addr); |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | 670 | static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | |
| 671 | static void | ||
| 672 | fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | ||
| 673 | { | 671 | { |
| 674 | sbus_writel(val, addr); | 672 | sbus_writel(val, addr); |
| 675 | } | 673 | } |
| 676 | 674 | ||
| 677 | 675 | static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) | |
| 678 | static u32 | ||
| 679 | fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) | ||
| 680 | { | 676 | { |
| 681 | u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction); | 677 | struct of_device *op = fore200e->bus_dev; |
| 678 | u32 dma_addr; | ||
| 682 | 679 | ||
| 683 | DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", | 680 | dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); |
| 684 | virt_addr, size, direction, dma_addr); | 681 | |
| 682 | DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", | ||
| 683 | virt_addr, size, direction, dma_addr); | ||
| 685 | 684 | ||
| 686 | return dma_addr; | 685 | return dma_addr; |
| 687 | } | 686 | } |
| 688 | 687 | ||
| 689 | 688 | static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | |
| 690 | static void | ||
| 691 | fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
| 692 | { | 689 | { |
| 693 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", | 690 | struct of_device *op = fore200e->bus_dev; |
| 694 | dma_addr, size, direction); | ||
| 695 | 691 | ||
| 696 | sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | 692 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", |
| 697 | } | 693 | dma_addr, size, direction); |
| 698 | 694 | ||
| 695 | dma_unmap_single(&op->dev, dma_addr, size, direction); | ||
| 696 | } | ||
| 699 | 697 | ||
| 700 | static void | 698 | static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
| 701 | fore200e_sba_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
| 702 | { | 699 | { |
| 703 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 700 | struct of_device *op = fore200e->bus_dev; |
| 701 | |||
| 702 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
| 704 | 703 | ||
| 705 | sbus_dma_sync_single_for_cpu((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | 704 | dma_sync_single_for_cpu(&op->dev, dma_addr, size, direction); |
| 706 | } | 705 | } |
| 707 | 706 | ||
| 708 | static void | 707 | static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
| 709 | fore200e_sba_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
| 710 | { | 708 | { |
| 711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 709 | struct of_device *op = fore200e->bus_dev; |
| 712 | |||
| 713 | sbus_dma_sync_single_for_device((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
| 714 | } | ||
| 715 | 710 | ||
| 711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
| 716 | 712 | ||
| 717 | /* allocate a DVMA consistent chunk of memory intended to act as a communication mechanism | 713 | dma_sync_single_for_device(&op->dev, dma_addr, size, direction); |
| 718 | (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */ | 714 | } |
| 719 | 715 | ||
| 720 | static int | 716 | /* Allocate a DVMA consistent chunk of memory intended to act as a communication mechanism |
| 721 | fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, | 717 | * (to hold descriptors, status, queues, etc.) shared by the driver and the adapter. |
| 722 | int size, int nbr, int alignment) | 718 | */ |
| 719 | static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, | ||
| 720 | int size, int nbr, int alignment) | ||
| 723 | { | 721 | { |
| 724 | chunk->alloc_size = chunk->align_size = size * nbr; | 722 | struct of_device *op = fore200e->bus_dev; |
| 725 | 723 | ||
| 726 | /* returned chunks are page-aligned */ | 724 | chunk->alloc_size = chunk->align_size = size * nbr; |
| 727 | chunk->alloc_addr = sbus_alloc_consistent((struct sbus_dev*)fore200e->bus_dev, | ||
| 728 | chunk->alloc_size, | ||
| 729 | &chunk->dma_addr); | ||
| 730 | 725 | ||
| 731 | if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) | 726 | /* returned chunks are page-aligned */ |
| 732 | return -ENOMEM; | 727 | chunk->alloc_addr = dma_alloc_coherent(&op->dev, chunk->alloc_size, |
| 728 | &chunk->dma_addr, GFP_ATOMIC); | ||
| 733 | 729 | ||
| 734 | chunk->align_addr = chunk->alloc_addr; | 730 | if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) |
| 731 | return -ENOMEM; | ||
| 732 | |||
| 733 | chunk->align_addr = chunk->alloc_addr; | ||
| 735 | 734 | ||
| 736 | return 0; | 735 | return 0; |
| 737 | } | 736 | } |
| 738 | 737 | ||
| 739 | |||
| 740 | /* free a DVMA consistent chunk of memory */ | 738 | /* free a DVMA consistent chunk of memory */ |
| 741 | 739 | static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) | |
| 742 | static void | ||
| 743 | fore200e_sba_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) | ||
| 744 | { | 740 | { |
| 745 | sbus_free_consistent((struct sbus_dev*)fore200e->bus_dev, | 741 | struct of_device *op = fore200e->bus_dev; |
| 746 | chunk->alloc_size, | ||
| 747 | chunk->alloc_addr, | ||
| 748 | chunk->dma_addr); | ||
| 749 | } | ||
| 750 | 742 | ||
| 743 | dma_free_coherent(&op->dev, chunk->alloc_size, | ||
| 744 | chunk->alloc_addr, chunk->dma_addr); | ||
| 745 | } | ||
| 751 | 746 | ||
| 752 | static void | 747 | static void fore200e_sba_irq_enable(struct fore200e *fore200e) |
| 753 | fore200e_sba_irq_enable(struct fore200e* fore200e) | ||
| 754 | { | 748 | { |
| 755 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; | 749 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; |
| 756 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr); | 750 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr); |
| 757 | } | 751 | } |
| 758 | 752 | ||
| 759 | 753 | static int fore200e_sba_irq_check(struct fore200e *fore200e) | |
| 760 | static int | ||
| 761 | fore200e_sba_irq_check(struct fore200e* fore200e) | ||
| 762 | { | 754 | { |
| 763 | return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ; | 755 | return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ; |
| 764 | } | 756 | } |
| 765 | 757 | ||
| 766 | 758 | static void fore200e_sba_irq_ack(struct fore200e *fore200e) | |
| 767 | static void | ||
| 768 | fore200e_sba_irq_ack(struct fore200e* fore200e) | ||
| 769 | { | 759 | { |
| 770 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; | 760 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; |
| 771 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr); | 761 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr); |
| 772 | } | 762 | } |
| 773 | 763 | ||
| 774 | 764 | static void fore200e_sba_reset(struct fore200e *fore200e) | |
| 775 | static void | ||
| 776 | fore200e_sba_reset(struct fore200e* fore200e) | ||
| 777 | { | 765 | { |
| 778 | fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr); | 766 | fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr); |
| 779 | fore200e_spin(10); | 767 | fore200e_spin(10); |
| 780 | fore200e->bus->write(0, fore200e->regs.sba.hcr); | 768 | fore200e->bus->write(0, fore200e->regs.sba.hcr); |
| 781 | } | 769 | } |
| 782 | 770 | ||
| 783 | 771 | static int __init fore200e_sba_map(struct fore200e *fore200e) | |
| 784 | static int __init | ||
| 785 | fore200e_sba_map(struct fore200e* fore200e) | ||
| 786 | { | 772 | { |
| 787 | struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev; | 773 | struct of_device *op = fore200e->bus_dev; |
| 788 | unsigned int bursts; | 774 | unsigned int bursts; |
| 789 | 775 | ||
| 790 | /* gain access to the SBA specific registers */ | 776 | /* gain access to the SBA specific registers */ |
| 791 | fore200e->regs.sba.hcr = sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); | 777 | fore200e->regs.sba.hcr = of_ioremap(&op->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); |
| 792 | fore200e->regs.sba.bsr = sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); | 778 | fore200e->regs.sba.bsr = of_ioremap(&op->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); |
| 793 | fore200e->regs.sba.isr = sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); | 779 | fore200e->regs.sba.isr = of_ioremap(&op->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); |
| 794 | fore200e->virt_base = sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); | 780 | fore200e->virt_base = of_ioremap(&op->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); |
| 795 | 781 | ||
| 796 | if (fore200e->virt_base == NULL) { | 782 | if (!fore200e->virt_base) { |
| 797 | printk(FORE200E "unable to map RAM of device %s\n", fore200e->name); | 783 | printk(FORE200E "unable to map RAM of device %s\n", fore200e->name); |
| 798 | return -EFAULT; | 784 | return -EFAULT; |
| 799 | } | 785 | } |
| 800 | 786 | ||
| 801 | DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); | 787 | DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); |
| 802 | 788 | ||
| 803 | fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */ | 789 | fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */ |
| 804 | 790 | ||
| 805 | /* get the supported DVMA burst sizes */ | 791 | /* get the supported DVMA burst sizes */ |
| 806 | bursts = prom_getintdefault(sbus_dev->bus->prom_node, "burst-sizes", 0x00); | 792 | bursts = of_getintprop_default(op->node->parent, "burst-sizes", 0x00); |
| 807 | 793 | ||
| 808 | if (sbus_can_dma_64bit(sbus_dev)) | 794 | if (sbus_can_dma_64bit()) |
| 809 | sbus_set_sbus64(sbus_dev, bursts); | 795 | sbus_set_sbus64(&op->dev, bursts); |
| 810 | 796 | ||
| 811 | fore200e->state = FORE200E_STATE_MAP; | 797 | fore200e->state = FORE200E_STATE_MAP; |
| 812 | return 0; | 798 | return 0; |
| 813 | } | 799 | } |
| 814 | 800 | ||
| 815 | 801 | static void fore200e_sba_unmap(struct fore200e *fore200e) | |
| 816 | static void | ||
| 817 | fore200e_sba_unmap(struct fore200e* fore200e) | ||
| 818 | { | 802 | { |
| 819 | sbus_iounmap(fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | 803 | struct of_device *op = fore200e->bus_dev; |
| 820 | sbus_iounmap(fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | ||
| 821 | sbus_iounmap(fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); | ||
| 822 | sbus_iounmap(fore200e->virt_base, SBA200E_RAM_LENGTH); | ||
| 823 | } | ||
| 824 | 804 | ||
| 805 | of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | ||
| 806 | of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | ||
| 807 | of_iounmap(&op->resource[2], fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); | ||
| 808 | of_iounmap(&op->resource[3], fore200e->virt_base, SBA200E_RAM_LENGTH); | ||
| 809 | } | ||
| 825 | 810 | ||
| 826 | static int __init | 811 | static int __init fore200e_sba_configure(struct fore200e *fore200e) |
| 827 | fore200e_sba_configure(struct fore200e* fore200e) | ||
| 828 | { | 812 | { |
| 829 | fore200e->state = FORE200E_STATE_CONFIGURE; | 813 | fore200e->state = FORE200E_STATE_CONFIGURE; |
| 830 | return 0; | 814 | return 0; |
| 831 | } | 815 | } |
| 832 | 816 | ||
| 833 | 817 | static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) | |
| 834 | static struct fore200e* __init | ||
| 835 | fore200e_sba_detect(const struct fore200e_bus* bus, int index) | ||
| 836 | { | 818 | { |
| 837 | struct fore200e* fore200e; | 819 | struct of_device *op = fore200e->bus_dev; |
| 838 | struct sbus_bus* sbus_bus; | 820 | const u8 *prop; |
| 839 | struct sbus_dev* sbus_dev = NULL; | 821 | int len; |
| 840 | |||
| 841 | unsigned int count = 0; | ||
| 842 | |||
| 843 | for_each_sbus (sbus_bus) { | ||
| 844 | for_each_sbusdev (sbus_dev, sbus_bus) { | ||
| 845 | if (strcmp(sbus_dev->prom_name, SBA200E_PROM_NAME) == 0) { | ||
| 846 | if (count >= index) | ||
| 847 | goto found; | ||
| 848 | count++; | ||
| 849 | } | ||
| 850 | } | ||
| 851 | } | ||
| 852 | return NULL; | ||
| 853 | |||
| 854 | found: | ||
| 855 | if (sbus_dev->num_registers != 4) { | ||
| 856 | printk(FORE200E "this %s device has %d instead of 4 registers\n", | ||
| 857 | bus->model_name, sbus_dev->num_registers); | ||
| 858 | return NULL; | ||
| 859 | } | ||
| 860 | |||
| 861 | fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); | ||
| 862 | if (fore200e == NULL) | ||
| 863 | return NULL; | ||
| 864 | 822 | ||
| 865 | fore200e->bus = bus; | 823 | prop = of_get_property(op->node, "madaddrlo2", &len); |
| 866 | fore200e->bus_dev = sbus_dev; | 824 | if (!prop) |
| 867 | fore200e->irq = sbus_dev->irqs[ 0 ]; | 825 | return -ENODEV; |
| 826 | memcpy(&prom->mac_addr[4], prop, 4); | ||
| 868 | 827 | ||
| 869 | fore200e->phys_base = (unsigned long)sbus_dev; | 828 | prop = of_get_property(op->node, "madaddrhi4", &len); |
| 829 | if (!prop) | ||
| 830 | return -ENODEV; | ||
| 831 | memcpy(&prom->mac_addr[2], prop, 4); | ||
| 870 | 832 | ||
| 871 | sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1); | 833 | prom->serial_number = of_getintprop_default(op->node, "serialnumber", 0); |
| 834 | prom->hw_revision = of_getintprop_default(op->node, "promversion", 0); | ||
| 872 | 835 | ||
| 873 | return fore200e; | 836 | return 0; |
| 874 | } | 837 | } |
| 875 | 838 | ||
| 876 | 839 | static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) | |
| 877 | static int __init | ||
| 878 | fore200e_sba_prom_read(struct fore200e* fore200e, struct prom_data* prom) | ||
| 879 | { | 840 | { |
| 880 | struct sbus_dev* sbus_dev = (struct sbus_dev*) fore200e->bus_dev; | 841 | struct of_device *op = fore200e->bus_dev; |
| 881 | int len; | 842 | const struct linux_prom_registers *regs; |
| 882 | |||
| 883 | len = prom_getproperty(sbus_dev->prom_node, "macaddrlo2", &prom->mac_addr[ 4 ], 4); | ||
| 884 | if (len < 0) | ||
| 885 | return -EBUSY; | ||
| 886 | |||
| 887 | len = prom_getproperty(sbus_dev->prom_node, "macaddrhi4", &prom->mac_addr[ 2 ], 4); | ||
| 888 | if (len < 0) | ||
| 889 | return -EBUSY; | ||
| 890 | |||
| 891 | prom_getproperty(sbus_dev->prom_node, "serialnumber", | ||
| 892 | (char*)&prom->serial_number, sizeof(prom->serial_number)); | ||
| 893 | |||
| 894 | prom_getproperty(sbus_dev->prom_node, "promversion", | ||
| 895 | (char*)&prom->hw_revision, sizeof(prom->hw_revision)); | ||
| 896 | |||
| 897 | return 0; | ||
| 898 | } | ||
| 899 | 843 | ||
| 844 | regs = of_get_property(op->node, "reg", NULL); | ||
| 900 | 845 | ||
| 901 | static int | 846 | return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", |
| 902 | fore200e_sba_proc_read(struct fore200e* fore200e, char *page) | 847 | (regs ? regs->which_io : 0), op->node->name); |
| 903 | { | ||
| 904 | struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev; | ||
| 905 | |||
| 906 | return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name); | ||
| 907 | } | 848 | } |
| 908 | #endif /* CONFIG_SBUS */ | 849 | #endif /* CONFIG_SBUS */ |
| 909 | 850 | ||
| @@ -2572,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) | |||
| 2572 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; | 2513 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; |
| 2573 | #ifdef CONFIG_SBUS | 2514 | #ifdef CONFIG_SBUS |
| 2574 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) | 2515 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) |
| 2575 | device = &((struct sbus_dev *) fore200e->bus_dev)->ofdev.dev; | 2516 | device = &((struct of_device *) fore200e->bus_dev)->dev; |
| 2576 | #endif | 2517 | #endif |
| 2577 | else | 2518 | else |
| 2578 | return err; | 2519 | return err; |
| @@ -2701,6 +2642,66 @@ fore200e_init(struct fore200e* fore200e) | |||
| 2701 | return 0; | 2642 | return 0; |
| 2702 | } | 2643 | } |
| 2703 | 2644 | ||
| 2645 | #ifdef CONFIG_SBUS | ||
| 2646 | static int __devinit fore200e_sba_probe(struct of_device *op, | ||
| 2647 | const struct of_device_id *match) | ||
| 2648 | { | ||
| 2649 | const struct fore200e_bus *bus = match->data; | ||
| 2650 | struct fore200e *fore200e; | ||
| 2651 | static int index = 0; | ||
| 2652 | int err; | ||
| 2653 | |||
| 2654 | fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); | ||
| 2655 | if (!fore200e) | ||
| 2656 | return -ENOMEM; | ||
| 2657 | |||
| 2658 | fore200e->bus = bus; | ||
| 2659 | fore200e->bus_dev = op; | ||
| 2660 | fore200e->irq = op->irqs[0]; | ||
| 2661 | fore200e->phys_base = op->resource[0].start; | ||
| 2662 | |||
| 2663 | sprintf(fore200e->name, "%s-%d", bus->model_name, index); | ||
| 2664 | |||
| 2665 | err = fore200e_init(fore200e); | ||
| 2666 | if (err < 0) { | ||
| 2667 | fore200e_shutdown(fore200e); | ||
| 2668 | kfree(fore200e); | ||
| 2669 | return err; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | index++; | ||
| 2673 | dev_set_drvdata(&op->dev, fore200e); | ||
| 2674 | |||
| 2675 | return 0; | ||
| 2676 | } | ||
| 2677 | |||
| 2678 | static int __devexit fore200e_sba_remove(struct of_device *op) | ||
| 2679 | { | ||
| 2680 | struct fore200e *fore200e = dev_get_drvdata(&op->dev); | ||
| 2681 | |||
| 2682 | fore200e_shutdown(fore200e); | ||
| 2683 | kfree(fore200e); | ||
| 2684 | |||
| 2685 | return 0; | ||
| 2686 | } | ||
| 2687 | |||
| 2688 | static const struct of_device_id fore200e_sba_match[] = { | ||
| 2689 | { | ||
| 2690 | .name = SBA200E_PROM_NAME, | ||
| 2691 | .data = (void *) &fore200e_bus[1], | ||
| 2692 | }, | ||
| 2693 | {}, | ||
| 2694 | }; | ||
| 2695 | MODULE_DEVICE_TABLE(of, fore200e_sba_match); | ||
| 2696 | |||
| 2697 | static struct of_platform_driver fore200e_sba_driver = { | ||
| 2698 | .name = "fore_200e", | ||
| 2699 | .match_table = fore200e_sba_match, | ||
| 2700 | .probe = fore200e_sba_probe, | ||
| 2701 | .remove = __devexit_p(fore200e_sba_remove), | ||
| 2702 | }; | ||
| 2703 | #endif | ||
| 2704 | |||
| 2704 | #ifdef CONFIG_PCI | 2705 | #ifdef CONFIG_PCI |
| 2705 | static int __devinit | 2706 | static int __devinit |
| 2706 | fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | 2707 | fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) |
| @@ -2784,67 +2785,40 @@ static struct pci_driver fore200e_pca_driver = { | |||
| 2784 | }; | 2785 | }; |
| 2785 | #endif | 2786 | #endif |
| 2786 | 2787 | ||
| 2787 | 2788 | static int __init fore200e_module_init(void) | |
| 2788 | static int __init | ||
| 2789 | fore200e_module_init(void) | ||
| 2790 | { | 2789 | { |
| 2791 | const struct fore200e_bus* bus; | 2790 | int err; |
| 2792 | struct fore200e* fore200e; | ||
| 2793 | int index; | ||
| 2794 | |||
| 2795 | printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); | ||
| 2796 | 2791 | ||
| 2797 | /* for each configured bus interface */ | 2792 | printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); |
| 2798 | for (bus = fore200e_bus; bus->model_name; bus++) { | ||
| 2799 | 2793 | ||
| 2800 | /* detect all boards present on that bus */ | 2794 | #ifdef CONFIG_SBUS |
| 2801 | for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) { | 2795 | err = of_register_driver(&fore200e_sba_driver, &of_bus_type); |
| 2802 | 2796 | if (err) | |
| 2803 | printk(FORE200E "device %s found at 0x%lx, IRQ %s\n", | 2797 | return err; |
| 2804 | fore200e->bus->model_name, | 2798 | #endif |
| 2805 | fore200e->phys_base, fore200e_irq_itoa(fore200e->irq)); | ||
| 2806 | |||
| 2807 | sprintf(fore200e->name, "%s-%d", bus->model_name, index); | ||
| 2808 | |||
| 2809 | if (fore200e_init(fore200e) < 0) { | ||
| 2810 | |||
| 2811 | fore200e_shutdown(fore200e); | ||
| 2812 | break; | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | list_add(&fore200e->entry, &fore200e_boards); | ||
| 2816 | } | ||
| 2817 | } | ||
| 2818 | 2799 | ||
| 2819 | #ifdef CONFIG_PCI | 2800 | #ifdef CONFIG_PCI |
| 2820 | if (!pci_register_driver(&fore200e_pca_driver)) | 2801 | err = pci_register_driver(&fore200e_pca_driver); |
| 2821 | return 0; | ||
| 2822 | #endif | 2802 | #endif |
| 2823 | 2803 | ||
| 2824 | if (!list_empty(&fore200e_boards)) | 2804 | #ifdef CONFIG_SBUS |
| 2825 | return 0; | 2805 | if (err) |
| 2806 | of_unregister_driver(&fore200e_sba_driver); | ||
| 2807 | #endif | ||
| 2826 | 2808 | ||
| 2827 | return -ENODEV; | 2809 | return err; |
| 2828 | } | 2810 | } |
| 2829 | 2811 | ||
| 2830 | 2812 | static void __exit fore200e_module_cleanup(void) | |
| 2831 | static void __exit | ||
| 2832 | fore200e_module_cleanup(void) | ||
| 2833 | { | 2813 | { |
| 2834 | struct fore200e *fore200e, *next; | ||
| 2835 | |||
| 2836 | #ifdef CONFIG_PCI | 2814 | #ifdef CONFIG_PCI |
| 2837 | pci_unregister_driver(&fore200e_pca_driver); | 2815 | pci_unregister_driver(&fore200e_pca_driver); |
| 2816 | #endif | ||
| 2817 | #ifdef CONFIG_SBUS | ||
| 2818 | of_unregister_driver(&fore200e_sba_driver); | ||
| 2838 | #endif | 2819 | #endif |
| 2839 | |||
| 2840 | list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) { | ||
| 2841 | fore200e_shutdown(fore200e); | ||
| 2842 | kfree(fore200e); | ||
| 2843 | } | ||
| 2844 | DPRINTK(1, "module being removed\n"); | ||
| 2845 | } | 2820 | } |
| 2846 | 2821 | ||
| 2847 | |||
| 2848 | static int | 2822 | static int |
| 2849 | fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) | 2823 | fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) |
| 2850 | { | 2824 | { |
| @@ -3163,7 +3137,6 @@ static const struct fore200e_bus fore200e_bus[] = { | |||
| 3163 | fore200e_pca_dma_sync_for_device, | 3137 | fore200e_pca_dma_sync_for_device, |
| 3164 | fore200e_pca_dma_chunk_alloc, | 3138 | fore200e_pca_dma_chunk_alloc, |
| 3165 | fore200e_pca_dma_chunk_free, | 3139 | fore200e_pca_dma_chunk_free, |
| 3166 | NULL, | ||
| 3167 | fore200e_pca_configure, | 3140 | fore200e_pca_configure, |
| 3168 | fore200e_pca_map, | 3141 | fore200e_pca_map, |
| 3169 | fore200e_pca_reset, | 3142 | fore200e_pca_reset, |
| @@ -3185,7 +3158,6 @@ static const struct fore200e_bus fore200e_bus[] = { | |||
| 3185 | fore200e_sba_dma_sync_for_device, | 3158 | fore200e_sba_dma_sync_for_device, |
| 3186 | fore200e_sba_dma_chunk_alloc, | 3159 | fore200e_sba_dma_chunk_alloc, |
| 3187 | fore200e_sba_dma_chunk_free, | 3160 | fore200e_sba_dma_chunk_free, |
| 3188 | fore200e_sba_detect, | ||
| 3189 | fore200e_sba_configure, | 3161 | fore200e_sba_configure, |
| 3190 | fore200e_sba_map, | 3162 | fore200e_sba_map, |
| 3191 | fore200e_sba_reset, | 3163 | fore200e_sba_reset, |
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index 5c6e7adcb19c..7f97c09aaea5 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h | |||
| @@ -778,9 +778,9 @@ typedef struct fore200e_pca_regs { | |||
| 778 | /* SBA-200E registers */ | 778 | /* SBA-200E registers */ |
| 779 | 779 | ||
| 780 | typedef struct fore200e_sba_regs { | 780 | typedef struct fore200e_sba_regs { |
| 781 | volatile u32 __iomem *hcr; /* address of host control register */ | 781 | u32 __iomem *hcr; /* address of host control register */ |
| 782 | volatile u32 __iomem *bsr; /* address of burst transfer size register */ | 782 | u32 __iomem *bsr; /* address of burst transfer size register */ |
| 783 | volatile u32 __iomem *isr; /* address of interrupt level selection register */ | 783 | u32 __iomem *isr; /* address of interrupt level selection register */ |
| 784 | } fore200e_sba_regs_t; | 784 | } fore200e_sba_regs_t; |
| 785 | 785 | ||
| 786 | 786 | ||
| @@ -810,7 +810,6 @@ typedef struct fore200e_bus { | |||
| 810 | void (*dma_sync_for_device)(struct fore200e*, u32, int, int); | 810 | void (*dma_sync_for_device)(struct fore200e*, u32, int, int); |
| 811 | int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); | 811 | int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); |
| 812 | void (*dma_chunk_free)(struct fore200e*, struct chunk*); | 812 | void (*dma_chunk_free)(struct fore200e*, struct chunk*); |
| 813 | struct fore200e* (*detect)(const struct fore200e_bus*, int); | ||
| 814 | int (*configure)(struct fore200e*); | 813 | int (*configure)(struct fore200e*); |
| 815 | int (*map)(struct fore200e*); | 814 | int (*map)(struct fore200e*); |
| 816 | void (*reset)(struct fore200e*); | 815 | void (*reset)(struct fore200e*); |
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index a8de037ecd4a..953c0b83d758 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* sunvdc.c: Sun LDOM Virtual Disk Client. | 1 | /* sunvdc.c: Sun LDOM Virtual Disk Client. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| @@ -834,7 +834,7 @@ static int vdc_port_remove(struct vio_dev *vdev) | |||
| 834 | return 0; | 834 | return 0; |
| 835 | } | 835 | } |
| 836 | 836 | ||
| 837 | static struct vio_device_id vdc_port_match[] = { | 837 | static const struct vio_device_id vdc_port_match[] = { |
| 838 | { | 838 | { |
| 839 | .type = "vdc-port", | 839 | .type = "vdc-port", |
| 840 | }, | 840 | }, |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 5220f541df25..8859aeac2d25 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
| @@ -736,7 +736,7 @@ static int __devexit n2rng_remove(struct of_device *op) | |||
| 736 | return 0; | 736 | return 0; |
| 737 | } | 737 | } |
| 738 | 738 | ||
| 739 | static struct of_device_id n2rng_match[] = { | 739 | static const struct of_device_id n2rng_match[] = { |
| 740 | { | 740 | { |
| 741 | .name = "random-number-generator", | 741 | .name = "random-number-generator", |
| 742 | .compatible = "SUNW,n2-rng", | 742 | .compatible = "SUNW,n2-rng", |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index f53d4d00faf0..b47710c17885 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -88,12 +88,12 @@ | |||
| 88 | #endif | 88 | #endif |
| 89 | 89 | ||
| 90 | #ifdef CONFIG_SPARC32 | 90 | #ifdef CONFIG_SPARC32 |
| 91 | #include <linux/pci.h> | 91 | #include <linux/of.h> |
| 92 | #include <linux/jiffies.h> | 92 | #include <linux/of_device.h> |
| 93 | #include <asm/ebus.h> | 93 | #include <asm/io.h> |
| 94 | 94 | ||
| 95 | static unsigned long rtc_port; | 95 | static unsigned long rtc_port; |
| 96 | static int rtc_irq = PCI_IRQ_NONE; | 96 | static int rtc_irq; |
| 97 | #endif | 97 | #endif |
| 98 | 98 | ||
| 99 | #ifdef CONFIG_HPET_RTC_IRQ | 99 | #ifdef CONFIG_HPET_RTC_IRQ |
| @@ -973,8 +973,8 @@ static int __init rtc_init(void) | |||
| 973 | char *guess = NULL; | 973 | char *guess = NULL; |
| 974 | #endif | 974 | #endif |
| 975 | #ifdef CONFIG_SPARC32 | 975 | #ifdef CONFIG_SPARC32 |
| 976 | struct linux_ebus *ebus; | 976 | struct device_node *ebus_dp; |
| 977 | struct linux_ebus_device *edev; | 977 | struct of_device *op; |
| 978 | #else | 978 | #else |
| 979 | void *r; | 979 | void *r; |
| 980 | #ifdef RTC_IRQ | 980 | #ifdef RTC_IRQ |
| @@ -983,12 +983,16 @@ static int __init rtc_init(void) | |||
| 983 | #endif | 983 | #endif |
| 984 | 984 | ||
| 985 | #ifdef CONFIG_SPARC32 | 985 | #ifdef CONFIG_SPARC32 |
| 986 | for_each_ebus(ebus) { | 986 | for_each_node_by_name(ebus_dp, "ebus") { |
| 987 | for_each_ebusdev(edev, ebus) { | 987 | struct device_node *dp; |
| 988 | if (strcmp(edev->prom_node->name, "rtc") == 0) { | 988 | for (dp = ebus_dp; dp; dp = dp->sibling) { |
| 989 | rtc_port = edev->resource[0].start; | 989 | if (!strcmp(dp->name, "rtc")) { |
| 990 | rtc_irq = edev->irqs[0]; | 990 | op = of_find_device_by_node(dp); |
| 991 | goto found; | 991 | if (op) { |
| 992 | rtc_port = op->resource[0].start; | ||
| 993 | rtc_irq = op->irqs[0]; | ||
| 994 | goto found; | ||
| 995 | } | ||
| 992 | } | 996 | } |
| 993 | } | 997 | } |
| 994 | } | 998 | } |
| @@ -997,7 +1001,7 @@ static int __init rtc_init(void) | |||
| 997 | return -EIO; | 1001 | return -EIO; |
| 998 | 1002 | ||
| 999 | found: | 1003 | found: |
| 1000 | if (rtc_irq == PCI_IRQ_NONE) { | 1004 | if (!rtc_irq) { |
| 1001 | rtc_has_irq = 0; | 1005 | rtc_has_irq = 0; |
| 1002 | goto no_irq; | 1006 | goto no_irq; |
| 1003 | } | 1007 | } |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 3309e862f317..ebacc0af40fe 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
| @@ -800,6 +800,13 @@ config SENSORS_W83627EHF | |||
| 800 | This driver can also be built as a module. If so, the module | 800 | This driver can also be built as a module. If so, the module |
| 801 | will be called w83627ehf. | 801 | will be called w83627ehf. |
| 802 | 802 | ||
| 803 | config SENSORS_ULTRA45 | ||
| 804 | tristate "Sun Ultra45 PIC16F747" | ||
| 805 | depends on SPARC64 | ||
| 806 | help | ||
| 807 | This driver provides support for the Ultra45 workstation environmental | ||
| 808 | sensors. | ||
| 809 | |||
| 803 | config SENSORS_HDAPS | 810 | config SENSORS_HDAPS |
| 804 | tristate "IBM Hard Drive Active Protection System (hdaps)" | 811 | tristate "IBM Hard Drive Active Protection System (hdaps)" |
| 805 | depends on INPUT && X86 | 812 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6babc801b348..042d5a78622e 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
| @@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o | |||
| 41 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o | 41 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o |
| 42 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 42 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
| 43 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o | 43 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o |
| 44 | obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o | ||
| 44 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o | 45 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o |
| 45 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o | 46 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o |
| 46 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | 47 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o |
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c new file mode 100644 index 000000000000..68e90abeba96 --- /dev/null +++ b/drivers/hwmon/ultra45_env.c | |||
| @@ -0,0 +1,320 @@ | |||
| 1 | /* ultra45_env.c: Driver for Ultra45 PIC16F747 environmental monitor. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/types.h> | ||
| 8 | #include <linux/slab.h> | ||
| 9 | #include <linux/of_device.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/hwmon.h> | ||
| 12 | #include <linux/hwmon-sysfs.h> | ||
| 13 | |||
| 14 | #define DRV_MODULE_VERSION "0.1" | ||
| 15 | |||
| 16 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
| 17 | MODULE_DESCRIPTION("Ultra45 environmental monitor driver"); | ||
| 18 | MODULE_LICENSE("GPL"); | ||
| 19 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
| 20 | |||
| 21 | /* PIC device registers */ | ||
| 22 | #define REG_CMD 0x00UL | ||
| 23 | #define REG_CMD_RESET 0x80 | ||
| 24 | #define REG_CMD_ESTAR 0x01 | ||
| 25 | #define REG_STAT 0x01UL | ||
| 26 | #define REG_STAT_FWVER 0xf0 | ||
| 27 | #define REG_STAT_TGOOD 0x08 | ||
| 28 | #define REG_STAT_STALE 0x04 | ||
| 29 | #define REG_STAT_BUSY 0x02 | ||
| 30 | #define REG_STAT_FAULT 0x01 | ||
| 31 | #define REG_DATA 0x40UL | ||
| 32 | #define REG_ADDR 0x41UL | ||
| 33 | #define REG_SIZE 0x42UL | ||
| 34 | |||
| 35 | /* Registers accessed indirectly via REG_DATA/REG_ADDR */ | ||
| 36 | #define IREG_FAN0 0x00 | ||
| 37 | #define IREG_FAN1 0x01 | ||
| 38 | #define IREG_FAN2 0x02 | ||
| 39 | #define IREG_FAN3 0x03 | ||
| 40 | #define IREG_FAN4 0x04 | ||
| 41 | #define IREG_FAN5 0x05 | ||
| 42 | #define IREG_LCL_TEMP 0x06 | ||
| 43 | #define IREG_RMT1_TEMP 0x07 | ||
| 44 | #define IREG_RMT2_TEMP 0x08 | ||
| 45 | #define IREG_RMT3_TEMP 0x09 | ||
| 46 | #define IREG_LM95221_TEMP 0x0a | ||
| 47 | #define IREG_FIRE_TEMP 0x0b | ||
| 48 | #define IREG_LSI1064_TEMP 0x0c | ||
| 49 | #define IREG_FRONT_TEMP 0x0d | ||
| 50 | #define IREG_FAN_STAT 0x0e | ||
| 51 | #define IREG_VCORE0 0x0f | ||
| 52 | #define IREG_VCORE1 0x10 | ||
| 53 | #define IREG_VMEM0 0x11 | ||
| 54 | #define IREG_VMEM1 0x12 | ||
| 55 | #define IREG_PSU_TEMP 0x13 | ||
| 56 | |||
| 57 | struct env { | ||
| 58 | void __iomem *regs; | ||
| 59 | spinlock_t lock; | ||
| 60 | |||
| 61 | struct device *hwmon_dev; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static u8 env_read(struct env *p, u8 ireg) | ||
| 65 | { | ||
| 66 | u8 ret; | ||
| 67 | |||
| 68 | spin_lock(&p->lock); | ||
| 69 | writeb(ireg, p->regs + REG_ADDR); | ||
| 70 | ret = readb(p->regs + REG_DATA); | ||
| 71 | spin_unlock(&p->lock); | ||
| 72 | |||
| 73 | return ret; | ||
| 74 | } | ||
| 75 | |||
| 76 | static void env_write(struct env *p, u8 ireg, u8 val) | ||
| 77 | { | ||
| 78 | spin_lock(&p->lock); | ||
| 79 | writeb(ireg, p->regs + REG_ADDR); | ||
| 80 | writeb(val, p->regs + REG_DATA); | ||
| 81 | spin_unlock(&p->lock); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* There seems to be a adr7462 providing these values, thus a lot | ||
| 85 | * of these calculations are borrowed from the adt7470 driver. | ||
| 86 | */ | ||
| 87 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | ||
| 88 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | ||
| 89 | #define FAN_PERIOD_INVALID (0xff << 8) | ||
| 90 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | ||
| 91 | |||
| 92 | static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 93 | { | ||
| 94 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
| 95 | struct env *p = dev_get_drvdata(dev); | ||
| 96 | int rpm, period; | ||
| 97 | u8 val; | ||
| 98 | |||
| 99 | val = env_read(p, IREG_FAN0 + fan_nr); | ||
| 100 | period = (int) val << 8; | ||
| 101 | if (FAN_DATA_VALID(period)) | ||
| 102 | rpm = FAN_PERIOD_TO_RPM(period); | ||
| 103 | else | ||
| 104 | rpm = 0; | ||
| 105 | |||
| 106 | return sprintf(buf, "%d\n", rpm); | ||
| 107 | } | ||
| 108 | |||
| 109 | static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr, | ||
| 110 | const char *buf, size_t count) | ||
| 111 | { | ||
| 112 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
| 113 | int rpm = simple_strtol(buf, NULL, 10); | ||
| 114 | struct env *p = dev_get_drvdata(dev); | ||
| 115 | int period; | ||
| 116 | u8 val; | ||
| 117 | |||
| 118 | if (!rpm) | ||
| 119 | return -EINVAL; | ||
| 120 | |||
| 121 | period = FAN_RPM_TO_PERIOD(rpm); | ||
| 122 | val = period >> 8; | ||
| 123 | env_write(p, IREG_FAN0 + fan_nr, val); | ||
| 124 | |||
| 125 | return count; | ||
| 126 | } | ||
| 127 | |||
| 128 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 129 | { | ||
| 130 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
| 131 | struct env *p = dev_get_drvdata(dev); | ||
| 132 | u8 val = env_read(p, IREG_FAN_STAT); | ||
| 133 | return sprintf(buf, "%d\n", (val & (1 << fan_nr)) ? 1 : 0); | ||
| 134 | } | ||
| 135 | |||
| 136 | #define fan(index) \ | ||
| 137 | static SENSOR_DEVICE_ATTR(fan##index##_speed, S_IRUGO | S_IWUSR, \ | ||
| 138 | show_fan_speed, set_fan_speed, index); \ | ||
| 139 | static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, \ | ||
| 140 | show_fan_fault, NULL, index) | ||
| 141 | |||
| 142 | fan(0); | ||
| 143 | fan(1); | ||
| 144 | fan(2); | ||
| 145 | fan(3); | ||
| 146 | fan(4); | ||
| 147 | |||
| 148 | static SENSOR_DEVICE_ATTR(psu_fan_fault, S_IRUGO, show_fan_fault, NULL, 6); | ||
| 149 | |||
| 150 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 151 | { | ||
| 152 | int temp_nr = to_sensor_dev_attr(attr)->index; | ||
| 153 | struct env *p = dev_get_drvdata(dev); | ||
| 154 | s8 val; | ||
| 155 | |||
| 156 | val = env_read(p, IREG_LCL_TEMP + temp_nr); | ||
| 157 | return sprintf(buf, "%d\n", ((int) val) - 64); | ||
| 158 | } | ||
| 159 | |||
| 160 | static SENSOR_DEVICE_ATTR(adt7462_local_temp, S_IRUGO, show_temp, NULL, 0); | ||
| 161 | static SENSOR_DEVICE_ATTR(cpu0_temp, S_IRUGO, show_temp, NULL, 1); | ||
| 162 | static SENSOR_DEVICE_ATTR(cpu1_temp, S_IRUGO, show_temp, NULL, 2); | ||
| 163 | static SENSOR_DEVICE_ATTR(motherboard_temp, S_IRUGO, show_temp, NULL, 3); | ||
| 164 | static SENSOR_DEVICE_ATTR(lm95221_local_temp, S_IRUGO, show_temp, NULL, 4); | ||
| 165 | static SENSOR_DEVICE_ATTR(fire_temp, S_IRUGO, show_temp, NULL, 5); | ||
| 166 | static SENSOR_DEVICE_ATTR(lsi1064_local_temp, S_IRUGO, show_temp, NULL, 6); | ||
| 167 | static SENSOR_DEVICE_ATTR(front_panel_temp, S_IRUGO, show_temp, NULL, 7); | ||
| 168 | static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_temp, NULL, 13); | ||
| 169 | |||
| 170 | static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 171 | { | ||
| 172 | int index = to_sensor_dev_attr(attr)->index; | ||
| 173 | struct env *p = dev_get_drvdata(dev); | ||
| 174 | u8 val; | ||
| 175 | |||
| 176 | val = readb(p->regs + REG_STAT); | ||
| 177 | return sprintf(buf, "%d\n", (val & (1 << index)) ? 1 : 0); | ||
| 178 | } | ||
| 179 | |||
| 180 | static SENSOR_DEVICE_ATTR(fan_failure, S_IRUGO, show_stat_bit, NULL, 0); | ||
| 181 | static SENSOR_DEVICE_ATTR(env_bus_busy, S_IRUGO, show_stat_bit, NULL, 1); | ||
| 182 | static SENSOR_DEVICE_ATTR(env_data_stale, S_IRUGO, show_stat_bit, NULL, 2); | ||
| 183 | static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL, 3); | ||
| 184 | |||
| 185 | static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 186 | { | ||
| 187 | struct env *p = dev_get_drvdata(dev); | ||
| 188 | u8 val; | ||
| 189 | |||
| 190 | val = readb(p->regs + REG_STAT); | ||
| 191 | return sprintf(buf, "%d\n", val >> 4); | ||
| 192 | } | ||
| 193 | |||
| 194 | static SENSOR_DEVICE_ATTR(firmware_version, S_IRUGO, show_fwver, NULL, 0); | ||
| 195 | |||
| 196 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 197 | { | ||
| 198 | return sprintf(buf, "ultra45\n"); | ||
| 199 | } | ||
| 200 | |||
| 201 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); | ||
| 202 | |||
| 203 | static struct attribute *env_attributes[] = { | ||
| 204 | &sensor_dev_attr_fan0_speed.dev_attr.attr, | ||
| 205 | &sensor_dev_attr_fan0_fault.dev_attr.attr, | ||
| 206 | &sensor_dev_attr_fan1_speed.dev_attr.attr, | ||
| 207 | &sensor_dev_attr_fan1_fault.dev_attr.attr, | ||
| 208 | &sensor_dev_attr_fan2_speed.dev_attr.attr, | ||
| 209 | &sensor_dev_attr_fan2_fault.dev_attr.attr, | ||
| 210 | &sensor_dev_attr_fan3_speed.dev_attr.attr, | ||
| 211 | &sensor_dev_attr_fan3_fault.dev_attr.attr, | ||
| 212 | &sensor_dev_attr_fan4_speed.dev_attr.attr, | ||
| 213 | &sensor_dev_attr_fan4_fault.dev_attr.attr, | ||
| 214 | &sensor_dev_attr_psu_fan_fault.dev_attr.attr, | ||
| 215 | &sensor_dev_attr_adt7462_local_temp.dev_attr.attr, | ||
| 216 | &sensor_dev_attr_cpu0_temp.dev_attr.attr, | ||
| 217 | &sensor_dev_attr_cpu1_temp.dev_attr.attr, | ||
| 218 | &sensor_dev_attr_motherboard_temp.dev_attr.attr, | ||
| 219 | &sensor_dev_attr_lm95221_local_temp.dev_attr.attr, | ||
| 220 | &sensor_dev_attr_fire_temp.dev_attr.attr, | ||
| 221 | &sensor_dev_attr_lsi1064_local_temp.dev_attr.attr, | ||
| 222 | &sensor_dev_attr_front_panel_temp.dev_attr.attr, | ||
| 223 | &sensor_dev_attr_psu_temp.dev_attr.attr, | ||
| 224 | &sensor_dev_attr_fan_failure.dev_attr.attr, | ||
| 225 | &sensor_dev_attr_env_bus_busy.dev_attr.attr, | ||
| 226 | &sensor_dev_attr_env_data_stale.dev_attr.attr, | ||
| 227 | &sensor_dev_attr_tpm_self_test_passed.dev_attr.attr, | ||
| 228 | &sensor_dev_attr_firmware_version.dev_attr.attr, | ||
| 229 | &sensor_dev_attr_name.dev_attr.attr, | ||
| 230 | NULL, | ||
| 231 | }; | ||
| 232 | |||
| 233 | static const struct attribute_group env_group = { | ||
| 234 | .attrs = env_attributes, | ||
| 235 | }; | ||
| 236 | |||
| 237 | static int __devinit env_probe(struct of_device *op, | ||
| 238 | const struct of_device_id *match) | ||
| 239 | { | ||
| 240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 241 | int err = -ENOMEM; | ||
| 242 | |||
| 243 | if (!p) | ||
| 244 | goto out; | ||
| 245 | |||
| 246 | spin_lock_init(&p->lock); | ||
| 247 | |||
| 248 | p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747"); | ||
| 249 | if (!p->regs) | ||
| 250 | goto out_free; | ||
| 251 | |||
| 252 | err = sysfs_create_group(&op->dev.kobj, &env_group); | ||
| 253 | if (err) | ||
| 254 | goto out_iounmap; | ||
| 255 | |||
| 256 | p->hwmon_dev = hwmon_device_register(&op->dev); | ||
| 257 | if (IS_ERR(p->hwmon_dev)) { | ||
| 258 | err = PTR_ERR(p->hwmon_dev); | ||
| 259 | goto out_sysfs_remove_group; | ||
| 260 | } | ||
| 261 | |||
| 262 | dev_set_drvdata(&op->dev, p); | ||
| 263 | err = 0; | ||
| 264 | |||
| 265 | out: | ||
| 266 | return err; | ||
| 267 | |||
| 268 | out_sysfs_remove_group: | ||
| 269 | sysfs_remove_group(&op->dev.kobj, &env_group); | ||
| 270 | |||
| 271 | out_iounmap: | ||
| 272 | of_iounmap(&op->resource[0], p->regs, REG_SIZE); | ||
| 273 | |||
| 274 | out_free: | ||
| 275 | kfree(p); | ||
| 276 | goto out; | ||
| 277 | } | ||
| 278 | |||
| 279 | static int __devexit env_remove(struct of_device *op) | ||
| 280 | { | ||
| 281 | struct env *p = dev_get_drvdata(&op->dev); | ||
| 282 | |||
| 283 | if (p) { | ||
| 284 | sysfs_remove_group(&op->dev.kobj, &env_group); | ||
| 285 | hwmon_device_unregister(p->hwmon_dev); | ||
| 286 | of_iounmap(&op->resource[0], p->regs, REG_SIZE); | ||
| 287 | kfree(p); | ||
| 288 | } | ||
| 289 | |||
| 290 | return 0; | ||
| 291 | } | ||
| 292 | |||
| 293 | static const struct of_device_id env_match[] = { | ||
| 294 | { | ||
| 295 | .name = "env-monitor", | ||
| 296 | .compatible = "SUNW,ebus-pic16f747-env", | ||
| 297 | }, | ||
| 298 | {}, | ||
| 299 | }; | ||
| 300 | MODULE_DEVICE_TABLE(of, env_match); | ||
| 301 | |||
| 302 | static struct of_platform_driver env_driver = { | ||
| 303 | .name = "ultra45_env", | ||
| 304 | .match_table = env_match, | ||
| 305 | .probe = env_probe, | ||
| 306 | .remove = __devexit_p(env_remove), | ||
| 307 | }; | ||
| 308 | |||
| 309 | static int __init env_init(void) | ||
| 310 | { | ||
| 311 | return of_register_driver(&env_driver, &of_bus_type); | ||
| 312 | } | ||
| 313 | |||
| 314 | static void __exit env_exit(void) | ||
| 315 | { | ||
| 316 | of_unregister_driver(&env_driver); | ||
| 317 | } | ||
| 318 | |||
| 319 | module_init(env_init); | ||
| 320 | module_exit(env_exit); | ||
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index d8765cc93d27..c4f42311fdec 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
| @@ -249,7 +249,7 @@ static int bbc_remove(struct of_device *op) | |||
| 249 | return 0; | 249 | return 0; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | static struct of_device_id bbc_beep_match[] = { | 252 | static const struct of_device_id bbc_beep_match[] = { |
| 253 | { | 253 | { |
| 254 | .name = "beep", | 254 | .name = "beep", |
| 255 | .compatible = "SUNW,bbc-beep", | 255 | .compatible = "SUNW,bbc-beep", |
| @@ -328,7 +328,7 @@ static int grover_remove(struct of_device *op) | |||
| 328 | return 0; | 328 | return 0; |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | static struct of_device_id grover_beep_match[] = { | 331 | static const struct of_device_id grover_beep_match[] = { |
| 332 | { | 332 | { |
| 333 | .name = "beep", | 333 | .name = "beep", |
| 334 | .compatible = "SUNW,smbus-beep", | 334 | .compatible = "SUNW,smbus-beep", |
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index 692a79ec2a22..5071af2c0604 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
| @@ -87,7 +87,7 @@ static int __devexit sparc_i8042_remove(struct of_device *op) | |||
| 87 | return 0; | 87 | return 0; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static struct of_device_id sparc_i8042_match[] = { | 90 | static const struct of_device_id sparc_i8042_match[] = { |
| 91 | { | 91 | { |
| 92 | .name = "8042", | 92 | .name = "8042", |
| 93 | }, | 93 | }, |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 5b14262af017..e3e40427e00e 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -82,6 +82,14 @@ config LEDS_COBALT_RAQ | |||
| 82 | help | 82 | help |
| 83 | This option enables support for the Cobalt Raq series LEDs. | 83 | This option enables support for the Cobalt Raq series LEDs. |
| 84 | 84 | ||
| 85 | config LEDS_SUNFIRE | ||
| 86 | tristate "LED support for SunFire servers." | ||
| 87 | depends on LEDS_CLASS && SPARC64 | ||
| 88 | select LEDS_TRIGGERS | ||
| 89 | help | ||
| 90 | This option enables support for the Left, Middle, and Right | ||
| 91 | LEDs on the I/O and CPU boards of SunFire UltraSPARC servers. | ||
| 92 | |||
| 85 | config LEDS_HP6XX | 93 | config LEDS_HP6XX |
| 86 | tristate "LED Support for the HP Jornada 6xx" | 94 | tristate "LED Support for the HP Jornada 6xx" |
| 87 | depends on LEDS_CLASS && SH_HP6XX | 95 | depends on LEDS_CLASS && SH_HP6XX |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 3a8e6a04363c..eb186c351a1c 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o | |||
| 14 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o | 14 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o |
| 15 | obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o | 15 | obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o |
| 16 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | 16 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o |
| 17 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o | ||
| 17 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o | 18 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o |
| 18 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | 19 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o |
| 19 | obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o | 20 | obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o |
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c new file mode 100644 index 000000000000..6b008f0c3f62 --- /dev/null +++ b/drivers/leds/leds-sunfire.c | |||
| @@ -0,0 +1,273 @@ | |||
| 1 | /* leds-sunfire.c: SUNW,Ultra-Enterprise LED driver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/leds.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | |||
| 13 | #include <asm/fhc.h> | ||
| 14 | #include <asm/upa.h> | ||
| 15 | |||
| 16 | #define DRIVER_NAME "leds-sunfire" | ||
| 17 | #define PFX DRIVER_NAME ": " | ||
| 18 | |||
| 19 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
| 20 | MODULE_DESCRIPTION("Sun Fire LED driver"); | ||
| 21 | MODULE_LICENSE("GPL"); | ||
| 22 | |||
| 23 | struct sunfire_led { | ||
| 24 | struct led_classdev led_cdev; | ||
| 25 | void __iomem *reg; | ||
| 26 | }; | ||
| 27 | #define to_sunfire_led(d) container_of(d, struct sunfire_led, led_cdev) | ||
| 28 | |||
| 29 | static void __clockboard_set(struct led_classdev *led_cdev, | ||
| 30 | enum led_brightness led_val, u8 bit) | ||
| 31 | { | ||
| 32 | struct sunfire_led *p = to_sunfire_led(led_cdev); | ||
| 33 | u8 reg = upa_readb(p->reg); | ||
| 34 | |||
| 35 | switch (bit) { | ||
| 36 | case CLOCK_CTRL_LLED: | ||
| 37 | if (led_val) | ||
| 38 | reg &= ~bit; | ||
| 39 | else | ||
| 40 | reg |= bit; | ||
| 41 | break; | ||
| 42 | |||
| 43 | default: | ||
| 44 | if (led_val) | ||
| 45 | reg |= bit; | ||
| 46 | else | ||
| 47 | reg &= ~bit; | ||
| 48 | break; | ||
| 49 | } | ||
| 50 | upa_writeb(reg, p->reg); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void clockboard_left_set(struct led_classdev *led_cdev, | ||
| 54 | enum led_brightness led_val) | ||
| 55 | { | ||
| 56 | __clockboard_set(led_cdev, led_val, CLOCK_CTRL_LLED); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void clockboard_middle_set(struct led_classdev *led_cdev, | ||
| 60 | enum led_brightness led_val) | ||
| 61 | { | ||
| 62 | __clockboard_set(led_cdev, led_val, CLOCK_CTRL_MLED); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void clockboard_right_set(struct led_classdev *led_cdev, | ||
| 66 | enum led_brightness led_val) | ||
| 67 | { | ||
| 68 | __clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED); | ||
| 69 | } | ||
| 70 | |||
| 71 | static void __fhc_set(struct led_classdev *led_cdev, | ||
| 72 | enum led_brightness led_val, u32 bit) | ||
| 73 | { | ||
| 74 | struct sunfire_led *p = to_sunfire_led(led_cdev); | ||
| 75 | u32 reg = upa_readl(p->reg); | ||
| 76 | |||
| 77 | switch (bit) { | ||
| 78 | case FHC_CONTROL_LLED: | ||
| 79 | if (led_val) | ||
| 80 | reg &= ~bit; | ||
| 81 | else | ||
| 82 | reg |= bit; | ||
| 83 | break; | ||
| 84 | |||
| 85 | default: | ||
| 86 | if (led_val) | ||
| 87 | reg |= bit; | ||
| 88 | else | ||
| 89 | reg &= ~bit; | ||
| 90 | break; | ||
| 91 | } | ||
| 92 | upa_writel(reg, p->reg); | ||
| 93 | } | ||
| 94 | |||
| 95 | static void fhc_left_set(struct led_classdev *led_cdev, | ||
| 96 | enum led_brightness led_val) | ||
| 97 | { | ||
| 98 | __fhc_set(led_cdev, led_val, FHC_CONTROL_LLED); | ||
| 99 | } | ||
| 100 | |||
| 101 | static void fhc_middle_set(struct led_classdev *led_cdev, | ||
| 102 | enum led_brightness led_val) | ||
| 103 | { | ||
| 104 | __fhc_set(led_cdev, led_val, FHC_CONTROL_MLED); | ||
| 105 | } | ||
| 106 | |||
| 107 | static void fhc_right_set(struct led_classdev *led_cdev, | ||
| 108 | enum led_brightness led_val) | ||
| 109 | { | ||
| 110 | __fhc_set(led_cdev, led_val, FHC_CONTROL_RLED); | ||
| 111 | } | ||
| 112 | |||
| 113 | typedef void (*set_handler)(struct led_classdev *, enum led_brightness); | ||
| 114 | struct led_type { | ||
| 115 | const char *name; | ||
| 116 | set_handler handler; | ||
| 117 | const char *default_trigger; | ||
| 118 | }; | ||
| 119 | |||
| 120 | #define NUM_LEDS_PER_BOARD 3 | ||
| 121 | struct sunfire_drvdata { | ||
| 122 | struct sunfire_led leds[NUM_LEDS_PER_BOARD]; | ||
| 123 | }; | ||
| 124 | |||
| 125 | static int __devinit sunfire_led_generic_probe(struct platform_device *pdev, | ||
| 126 | struct led_type *types) | ||
| 127 | { | ||
| 128 | struct sunfire_drvdata *p; | ||
| 129 | int i, err = -EINVAL; | ||
| 130 | |||
| 131 | if (pdev->num_resources != 1) { | ||
| 132 | printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n", | ||
| 133 | pdev->num_resources); | ||
| 134 | goto out; | ||
| 135 | } | ||
| 136 | |||
| 137 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 138 | if (!p) { | ||
| 139 | printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n"); | ||
| 140 | goto out; | ||
| 141 | } | ||
| 142 | |||
| 143 | for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { | ||
| 144 | struct led_classdev *lp = &p->leds[i].led_cdev; | ||
| 145 | |||
| 146 | p->leds[i].reg = (void __iomem *) pdev->resource[0].start; | ||
| 147 | lp->name = types[i].name; | ||
| 148 | lp->brightness = LED_FULL; | ||
| 149 | lp->brightness_set = types[i].handler; | ||
| 150 | lp->default_trigger = types[i].default_trigger; | ||
| 151 | |||
| 152 | err = led_classdev_register(&pdev->dev, lp); | ||
| 153 | if (err) { | ||
| 154 | printk(KERN_ERR PFX "Could not register %s LED\n", | ||
| 155 | lp->name); | ||
| 156 | goto out_unregister_led_cdevs; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | dev_set_drvdata(&pdev->dev, p); | ||
| 161 | |||
| 162 | err = 0; | ||
| 163 | out: | ||
| 164 | return err; | ||
| 165 | |||
| 166 | out_unregister_led_cdevs: | ||
| 167 | for (i--; i >= 0; i--) | ||
| 168 | led_classdev_unregister(&p->leds[i].led_cdev); | ||
| 169 | goto out; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int __devexit sunfire_led_generic_remove(struct platform_device *pdev) | ||
| 173 | { | ||
| 174 | struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev); | ||
| 175 | int i; | ||
| 176 | |||
| 177 | for (i = 0; i < NUM_LEDS_PER_BOARD; i++) | ||
| 178 | led_classdev_unregister(&p->leds[i].led_cdev); | ||
| 179 | |||
| 180 | kfree(p); | ||
| 181 | |||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = { | ||
| 186 | { | ||
| 187 | .name = "clockboard-left", | ||
| 188 | .handler = clockboard_left_set, | ||
| 189 | }, | ||
| 190 | { | ||
| 191 | .name = "clockboard-middle", | ||
| 192 | .handler = clockboard_middle_set, | ||
| 193 | }, | ||
| 194 | { | ||
| 195 | .name = "clockboard-right", | ||
| 196 | .handler = clockboard_right_set, | ||
| 197 | .default_trigger= "heartbeat", | ||
| 198 | }, | ||
| 199 | }; | ||
| 200 | |||
| 201 | static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev) | ||
| 202 | { | ||
| 203 | return sunfire_led_generic_probe(pdev, clockboard_led_types); | ||
| 204 | } | ||
| 205 | |||
| 206 | static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = { | ||
| 207 | { | ||
| 208 | .name = "fhc-left", | ||
| 209 | .handler = fhc_left_set, | ||
| 210 | }, | ||
| 211 | { | ||
| 212 | .name = "fhc-middle", | ||
| 213 | .handler = fhc_middle_set, | ||
| 214 | }, | ||
| 215 | { | ||
| 216 | .name = "fhc-right", | ||
| 217 | .handler = fhc_right_set, | ||
| 218 | .default_trigger= "heartbeat", | ||
| 219 | }, | ||
| 220 | }; | ||
| 221 | |||
| 222 | static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev) | ||
| 223 | { | ||
| 224 | return sunfire_led_generic_probe(pdev, fhc_led_types); | ||
| 225 | } | ||
| 226 | |||
| 227 | MODULE_ALIAS("platform:sunfire-clockboard-leds"); | ||
| 228 | MODULE_ALIAS("platform:sunfire-fhc-leds"); | ||
| 229 | |||
| 230 | static struct platform_driver sunfire_clockboard_led_driver = { | ||
| 231 | .probe = sunfire_clockboard_led_probe, | ||
| 232 | .remove = __devexit_p(sunfire_led_generic_remove), | ||
| 233 | .driver = { | ||
| 234 | .name = "sunfire-clockboard-leds", | ||
| 235 | .owner = THIS_MODULE, | ||
| 236 | }, | ||
| 237 | }; | ||
| 238 | |||
| 239 | static struct platform_driver sunfire_fhc_led_driver = { | ||
| 240 | .probe = sunfire_fhc_led_probe, | ||
| 241 | .remove = __devexit_p(sunfire_led_generic_remove), | ||
| 242 | .driver = { | ||
| 243 | .name = "sunfire-fhc-leds", | ||
| 244 | .owner = THIS_MODULE, | ||
| 245 | }, | ||
| 246 | }; | ||
| 247 | |||
| 248 | static int __init sunfire_leds_init(void) | ||
| 249 | { | ||
| 250 | int err = platform_driver_register(&sunfire_clockboard_led_driver); | ||
| 251 | |||
| 252 | if (err) { | ||
| 253 | printk(KERN_ERR PFX "Could not register clock board LED driver\n"); | ||
| 254 | return err; | ||
| 255 | } | ||
| 256 | |||
| 257 | err = platform_driver_register(&sunfire_fhc_led_driver); | ||
| 258 | if (err) { | ||
| 259 | printk(KERN_ERR PFX "Could not register FHC LED driver\n"); | ||
| 260 | platform_driver_unregister(&sunfire_clockboard_led_driver); | ||
| 261 | } | ||
| 262 | |||
| 263 | return err; | ||
| 264 | } | ||
| 265 | |||
| 266 | static void __exit sunfire_leds_exit(void) | ||
| 267 | { | ||
| 268 | platform_driver_unregister(&sunfire_clockboard_led_driver); | ||
| 269 | platform_driver_unregister(&sunfire_fhc_led_driver); | ||
| 270 | } | ||
| 271 | |||
| 272 | module_init(sunfire_leds_init); | ||
| 273 | module_exit(sunfire_leds_exit); | ||
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 0d7c88396c88..fd7a1017399a 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
| @@ -1,13 +1,10 @@ | |||
| 1 | /* | 1 | /* sun_uflash.c - Driver for user-programmable flash on |
| 2 | * | 2 | * Sun Microsystems SME boardsets. |
| 3 | * sun_uflash - Driver implementation for user-programmable flash | ||
| 4 | * present on many Sun Microsystems SME boardsets. | ||
| 5 | * | 3 | * |
| 6 | * This driver does NOT provide access to the OBP-flash for | 4 | * This driver does NOT provide access to the OBP-flash for |
| 7 | * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead. | 5 | * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead. |
| 8 | * | 6 | * |
| 9 | * Copyright (c) 2001 Eric Brower (ebrower@usa.net) | 7 | * Copyright (c) 2001 Eric Brower (ebrower@usa.net) |
| 10 | * | ||
| 11 | */ | 8 | */ |
| 12 | 9 | ||
| 13 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| @@ -16,8 +13,8 @@ | |||
| 16 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 17 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 18 | #include <linux/ioport.h> | 15 | #include <linux/ioport.h> |
| 19 | #include <asm/ebus.h> | 16 | #include <linux/of.h> |
| 20 | #include <asm/oplib.h> | 17 | #include <linux/of_device.h> |
| 21 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
| 22 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
| 23 | #include <asm/io.h> | 20 | #include <asm/io.h> |
| @@ -26,67 +23,65 @@ | |||
| 26 | #include <linux/mtd/map.h> | 23 | #include <linux/mtd/map.h> |
| 27 | 24 | ||
| 28 | #define UFLASH_OBPNAME "flashprom" | 25 | #define UFLASH_OBPNAME "flashprom" |
| 29 | #define UFLASH_DEVNAME "userflash" | 26 | #define DRIVER_NAME "sun_uflash" |
| 27 | #define PFX DRIVER_NAME ": " | ||
| 30 | 28 | ||
| 31 | #define UFLASH_WINDOW_SIZE 0x200000 | 29 | #define UFLASH_WINDOW_SIZE 0x200000 |
| 32 | #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ | 30 | #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ |
| 33 | 31 | ||
| 34 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); | 32 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); |
| 35 | MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); | 33 | MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); |
| 36 | MODULE_SUPPORTED_DEVICE("userflash"); | 34 | MODULE_SUPPORTED_DEVICE(DRIVER_NAME); |
| 37 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
| 38 | MODULE_VERSION("2.0"); | 36 | MODULE_VERSION("2.1"); |
| 39 | 37 | ||
| 40 | static LIST_HEAD(device_list); | ||
| 41 | struct uflash_dev { | 38 | struct uflash_dev { |
| 42 | const char *name; /* device name */ | 39 | const char *name; /* device name */ |
| 43 | struct map_info map; /* mtd map info */ | 40 | struct map_info map; /* mtd map info */ |
| 44 | struct mtd_info *mtd; /* mtd info */ | 41 | struct mtd_info *mtd; /* mtd info */ |
| 45 | }; | 42 | }; |
| 46 | 43 | ||
| 47 | |||
| 48 | struct map_info uflash_map_templ = { | 44 | struct map_info uflash_map_templ = { |
| 49 | .name = "SUNW,???-????", | 45 | .name = "SUNW,???-????", |
| 50 | .size = UFLASH_WINDOW_SIZE, | 46 | .size = UFLASH_WINDOW_SIZE, |
| 51 | .bankwidth = UFLASH_BUSWIDTH, | 47 | .bankwidth = UFLASH_BUSWIDTH, |
| 52 | }; | 48 | }; |
| 53 | 49 | ||
| 54 | int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) | 50 | int uflash_devinit(struct of_device *op, struct device_node *dp) |
| 55 | { | 51 | { |
| 56 | struct uflash_dev *up; | 52 | struct uflash_dev *up; |
| 57 | struct resource *res; | ||
| 58 | 53 | ||
| 59 | res = &edev->resource[0]; | 54 | if (op->resource[1].flags) { |
| 60 | |||
| 61 | if (edev->num_addrs != 1) { | ||
| 62 | /* Non-CFI userflash device-- once I find one we | 55 | /* Non-CFI userflash device-- once I find one we |
| 63 | * can work on supporting it. | 56 | * can work on supporting it. |
| 64 | */ | 57 | */ |
| 65 | printk("%s: unsupported device at 0x%llx (%d regs): " \ | 58 | printk(KERN_ERR PFX "Unsupported device at %s, 0x%llx\n", |
| 66 | "email ebrower@usa.net\n", | 59 | dp->full_name, (unsigned long long)op->resource[0].start); |
| 67 | dp->full_name, (unsigned long long)res->start, | ||
| 68 | edev->num_addrs); | ||
| 69 | 60 | ||
| 70 | return -ENODEV; | 61 | return -ENODEV; |
| 71 | } | 62 | } |
| 72 | 63 | ||
| 73 | up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); | 64 | up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); |
| 74 | if (!up) | 65 | if (!up) { |
| 66 | printk(KERN_ERR PFX "Cannot allocate struct uflash_dev\n"); | ||
| 75 | return -ENOMEM; | 67 | return -ENOMEM; |
| 68 | } | ||
| 76 | 69 | ||
| 77 | /* copy defaults and tweak parameters */ | 70 | /* copy defaults and tweak parameters */ |
| 78 | memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); | 71 | memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); |
| 79 | up->map.size = (res->end - res->start) + 1UL; | 72 | |
| 73 | up->map.size = resource_size(&op->resource[0]); | ||
| 80 | 74 | ||
| 81 | up->name = of_get_property(dp, "model", NULL); | 75 | up->name = of_get_property(dp, "model", NULL); |
| 82 | if (up->name && 0 < strlen(up->name)) | 76 | if (up->name && 0 < strlen(up->name)) |
| 83 | up->map.name = (char *)up->name; | 77 | up->map.name = (char *)up->name; |
| 84 | 78 | ||
| 85 | up->map.phys = res->start; | 79 | up->map.phys = op->resource[0].start; |
| 86 | 80 | ||
| 87 | up->map.virt = ioremap_nocache(res->start, up->map.size); | 81 | up->map.virt = of_ioremap(&op->resource[0], 0, up->map.size, |
| 82 | DRIVER_NAME); | ||
| 88 | if (!up->map.virt) { | 83 | if (!up->map.virt) { |
| 89 | printk("%s: Failed to map device.\n", dp->full_name); | 84 | printk(KERN_ERR PFX "Failed to map device.\n"); |
| 90 | kfree(up); | 85 | kfree(up); |
| 91 | 86 | ||
| 92 | return -EINVAL; | 87 | return -EINVAL; |
| @@ -97,7 +92,7 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) | |||
| 97 | /* MTD registration */ | 92 | /* MTD registration */ |
| 98 | up->mtd = do_map_probe("cfi_probe", &up->map); | 93 | up->mtd = do_map_probe("cfi_probe", &up->map); |
| 99 | if (!up->mtd) { | 94 | if (!up->mtd) { |
| 100 | iounmap(up->map.virt); | 95 | of_iounmap(&op->resource[0], up->map.virt, up->map.size); |
| 101 | kfree(up); | 96 | kfree(up); |
| 102 | 97 | ||
| 103 | return -ENXIO; | 98 | return -ENXIO; |
| @@ -107,32 +102,34 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) | |||
| 107 | 102 | ||
| 108 | add_mtd_device(up->mtd); | 103 | add_mtd_device(up->mtd); |
| 109 | 104 | ||
| 110 | dev_set_drvdata(&edev->ofdev.dev, up); | 105 | dev_set_drvdata(&op->dev, up); |
| 111 | 106 | ||
| 112 | return 0; | 107 | return 0; |
| 113 | } | 108 | } |
| 114 | 109 | ||
| 115 | static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match) | 110 | static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match) |
| 116 | { | 111 | { |
| 117 | struct linux_ebus_device *edev = to_ebus_device(&dev->dev); | 112 | struct device_node *dp = op->node; |
| 118 | struct device_node *dp = dev->node; | ||
| 119 | 113 | ||
| 120 | if (of_find_property(dp, "user", NULL)) | 114 | /* Flashprom must have the "user" property in order to |
| 115 | * be used by this driver. | ||
| 116 | */ | ||
| 117 | if (!of_find_property(dp, "user", NULL)) | ||
| 121 | return -ENODEV; | 118 | return -ENODEV; |
| 122 | 119 | ||
| 123 | return uflash_devinit(edev, dp); | 120 | return uflash_devinit(op, dp); |
| 124 | } | 121 | } |
| 125 | 122 | ||
| 126 | static int __devexit uflash_remove(struct of_device *dev) | 123 | static int __devexit uflash_remove(struct of_device *op) |
| 127 | { | 124 | { |
| 128 | struct uflash_dev *up = dev_get_drvdata(&dev->dev); | 125 | struct uflash_dev *up = dev_get_drvdata(&op->dev); |
| 129 | 126 | ||
| 130 | if (up->mtd) { | 127 | if (up->mtd) { |
| 131 | del_mtd_device(up->mtd); | 128 | del_mtd_device(up->mtd); |
| 132 | map_destroy(up->mtd); | 129 | map_destroy(up->mtd); |
| 133 | } | 130 | } |
| 134 | if (up->map.virt) { | 131 | if (up->map.virt) { |
| 135 | iounmap(up->map.virt); | 132 | of_iounmap(&op->resource[0], up->map.virt, up->map.size); |
| 136 | up->map.virt = NULL; | 133 | up->map.virt = NULL; |
| 137 | } | 134 | } |
| 138 | 135 | ||
| @@ -141,7 +138,7 @@ static int __devexit uflash_remove(struct of_device *dev) | |||
| 141 | return 0; | 138 | return 0; |
| 142 | } | 139 | } |
| 143 | 140 | ||
| 144 | static struct of_device_id uflash_match[] = { | 141 | static const struct of_device_id uflash_match[] = { |
| 145 | { | 142 | { |
| 146 | .name = UFLASH_OBPNAME, | 143 | .name = UFLASH_OBPNAME, |
| 147 | }, | 144 | }, |
| @@ -151,7 +148,7 @@ static struct of_device_id uflash_match[] = { | |||
| 151 | MODULE_DEVICE_TABLE(of, uflash_match); | 148 | MODULE_DEVICE_TABLE(of, uflash_match); |
| 152 | 149 | ||
| 153 | static struct of_platform_driver uflash_driver = { | 150 | static struct of_platform_driver uflash_driver = { |
| 154 | .name = UFLASH_DEVNAME, | 151 | .name = DRIVER_NAME, |
| 155 | .match_table = uflash_match, | 152 | .match_table = uflash_match, |
| 156 | .probe = uflash_probe, | 153 | .probe = uflash_probe, |
| 157 | .remove = __devexit_p(uflash_remove), | 154 | .remove = __devexit_p(uflash_remove), |
| @@ -159,7 +156,7 @@ static struct of_platform_driver uflash_driver = { | |||
| 159 | 156 | ||
| 160 | static int __init uflash_init(void) | 157 | static int __init uflash_init(void) |
| 161 | { | 158 | { |
| 162 | return of_register_driver(&uflash_driver, &ebus_bus_type); | 159 | return of_register_driver(&uflash_driver, &of_bus_type); |
| 163 | } | 160 | } |
| 164 | 161 | ||
| 165 | static void __exit uflash_exit(void) | 162 | static void __exit uflash_exit(void) |
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 06e682334c7e..3ad7589d6a1c 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* myri_sbus.c: MyriCOM MyriNET SBUS card driver. | 1 | /* myri_sbus.c: MyriCOM MyriNET SBUS card driver. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | static char version[] = | 6 | static char version[] = |
| @@ -22,6 +22,9 @@ static char version[] = | |||
| 22 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
| 23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
| 24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
| 25 | #include <linux/dma-mapping.h> | ||
| 26 | #include <linux/of.h> | ||
| 27 | #include <linux/of_device.h> | ||
| 25 | 28 | ||
| 26 | #include <net/dst.h> | 29 | #include <net/dst.h> |
| 27 | #include <net/arp.h> | 30 | #include <net/arp.h> |
| @@ -33,7 +36,6 @@ static char version[] = | |||
| 33 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
| 34 | #include <asm/byteorder.h> | 37 | #include <asm/byteorder.h> |
| 35 | #include <asm/idprom.h> | 38 | #include <asm/idprom.h> |
| 36 | #include <asm/sbus.h> | ||
| 37 | #include <asm/openprom.h> | 39 | #include <asm/openprom.h> |
| 38 | #include <asm/oplib.h> | 40 | #include <asm/oplib.h> |
| 39 | #include <asm/auxio.h> | 41 | #include <asm/auxio.h> |
| @@ -243,7 +245,8 @@ static void myri_clean_rings(struct myri_eth *mp) | |||
| 243 | u32 dma_addr; | 245 | u32 dma_addr; |
| 244 | 246 | ||
| 245 | dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); | 247 | dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); |
| 246 | sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE); | 248 | dma_unmap_single(&mp->myri_op->dev, dma_addr, |
| 249 | RX_ALLOC_SIZE, DMA_FROM_DEVICE); | ||
| 247 | dev_kfree_skb(mp->rx_skbs[i]); | 250 | dev_kfree_skb(mp->rx_skbs[i]); |
| 248 | mp->rx_skbs[i] = NULL; | 251 | mp->rx_skbs[i] = NULL; |
| 249 | } | 252 | } |
| @@ -259,7 +262,9 @@ static void myri_clean_rings(struct myri_eth *mp) | |||
| 259 | u32 dma_addr; | 262 | u32 dma_addr; |
| 260 | 263 | ||
| 261 | dma_addr = sbus_readl(&txd->myri_gathers[0].addr); | 264 | dma_addr = sbus_readl(&txd->myri_gathers[0].addr); |
| 262 | sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3, SBUS_DMA_TODEVICE); | 265 | dma_unmap_single(&mp->myri_op->dev, dma_addr, |
| 266 | (skb->len + 3) & ~3, | ||
| 267 | DMA_TO_DEVICE); | ||
| 263 | dev_kfree_skb(mp->tx_skbs[i]); | 268 | dev_kfree_skb(mp->tx_skbs[i]); |
| 264 | mp->tx_skbs[i] = NULL; | 269 | mp->tx_skbs[i] = NULL; |
| 265 | } | 270 | } |
| @@ -288,7 +293,9 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq) | |||
| 288 | skb->dev = dev; | 293 | skb->dev = dev; |
| 289 | skb_put(skb, RX_ALLOC_SIZE); | 294 | skb_put(skb, RX_ALLOC_SIZE); |
| 290 | 295 | ||
| 291 | dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE); | 296 | dma_addr = dma_map_single(&mp->myri_op->dev, |
| 297 | skb->data, RX_ALLOC_SIZE, | ||
| 298 | DMA_FROM_DEVICE); | ||
| 292 | sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr); | 299 | sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr); |
| 293 | sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len); | 300 | sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len); |
| 294 | sbus_writel(i, &rxd[i].ctx); | 301 | sbus_writel(i, &rxd[i].ctx); |
| @@ -344,7 +351,8 @@ static void myri_tx(struct myri_eth *mp, struct net_device *dev) | |||
| 344 | 351 | ||
| 345 | DTX(("SKB[%d] ", entry)); | 352 | DTX(("SKB[%d] ", entry)); |
| 346 | dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr); | 353 | dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr); |
| 347 | sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len, SBUS_DMA_TODEVICE); | 354 | dma_unmap_single(&mp->myri_op->dev, dma_addr, |
| 355 | skb->len, DMA_TO_DEVICE); | ||
| 348 | dev_kfree_skb(skb); | 356 | dev_kfree_skb(skb); |
| 349 | mp->tx_skbs[entry] = NULL; | 357 | mp->tx_skbs[entry] = NULL; |
| 350 | dev->stats.tx_packets++; | 358 | dev->stats.tx_packets++; |
| @@ -423,9 +431,9 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
| 423 | 431 | ||
| 424 | /* Check for errors. */ | 432 | /* Check for errors. */ |
| 425 | DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum)); | 433 | DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum)); |
| 426 | sbus_dma_sync_single_for_cpu(mp->myri_sdev, | 434 | dma_sync_single_for_cpu(&mp->myri_op->dev, |
| 427 | sbus_readl(&rxd->myri_scatters[0].addr), | 435 | sbus_readl(&rxd->myri_scatters[0].addr), |
| 428 | RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE); | 436 | RX_ALLOC_SIZE, DMA_FROM_DEVICE); |
| 429 | if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) { | 437 | if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) { |
| 430 | DRX(("ERROR[")); | 438 | DRX(("ERROR[")); |
| 431 | dev->stats.rx_errors++; | 439 | dev->stats.rx_errors++; |
| @@ -442,10 +450,10 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
| 442 | drops++; | 450 | drops++; |
| 443 | DRX(("DROP ")); | 451 | DRX(("DROP ")); |
| 444 | dev->stats.rx_dropped++; | 452 | dev->stats.rx_dropped++; |
| 445 | sbus_dma_sync_single_for_device(mp->myri_sdev, | 453 | dma_sync_single_for_device(&mp->myri_op->dev, |
| 446 | sbus_readl(&rxd->myri_scatters[0].addr), | 454 | sbus_readl(&rxd->myri_scatters[0].addr), |
| 447 | RX_ALLOC_SIZE, | 455 | RX_ALLOC_SIZE, |
| 448 | SBUS_DMA_FROMDEVICE); | 456 | DMA_FROM_DEVICE); |
| 449 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); | 457 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); |
| 450 | sbus_writel(index, &rxd->ctx); | 458 | sbus_writel(index, &rxd->ctx); |
| 451 | sbus_writel(1, &rxd->num_sg); | 459 | sbus_writel(1, &rxd->num_sg); |
| @@ -464,17 +472,17 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
| 464 | DRX(("skb_alloc(FAILED) ")); | 472 | DRX(("skb_alloc(FAILED) ")); |
| 465 | goto drop_it; | 473 | goto drop_it; |
| 466 | } | 474 | } |
| 467 | sbus_unmap_single(mp->myri_sdev, | 475 | dma_unmap_single(&mp->myri_op->dev, |
| 468 | sbus_readl(&rxd->myri_scatters[0].addr), | 476 | sbus_readl(&rxd->myri_scatters[0].addr), |
| 469 | RX_ALLOC_SIZE, | 477 | RX_ALLOC_SIZE, |
| 470 | SBUS_DMA_FROMDEVICE); | 478 | DMA_FROM_DEVICE); |
| 471 | mp->rx_skbs[index] = new_skb; | 479 | mp->rx_skbs[index] = new_skb; |
| 472 | new_skb->dev = dev; | 480 | new_skb->dev = dev; |
| 473 | skb_put(new_skb, RX_ALLOC_SIZE); | 481 | skb_put(new_skb, RX_ALLOC_SIZE); |
| 474 | dma_addr = sbus_map_single(mp->myri_sdev, | 482 | dma_addr = dma_map_single(&mp->myri_op->dev, |
| 475 | new_skb->data, | 483 | new_skb->data, |
| 476 | RX_ALLOC_SIZE, | 484 | RX_ALLOC_SIZE, |
| 477 | SBUS_DMA_FROMDEVICE); | 485 | DMA_FROM_DEVICE); |
| 478 | sbus_writel(dma_addr, &rxd->myri_scatters[0].addr); | 486 | sbus_writel(dma_addr, &rxd->myri_scatters[0].addr); |
| 479 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); | 487 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); |
| 480 | sbus_writel(index, &rxd->ctx); | 488 | sbus_writel(index, &rxd->ctx); |
| @@ -500,10 +508,10 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
| 500 | 508 | ||
| 501 | /* Reuse original ring buffer. */ | 509 | /* Reuse original ring buffer. */ |
| 502 | DRX(("reuse ")); | 510 | DRX(("reuse ")); |
| 503 | sbus_dma_sync_single_for_device(mp->myri_sdev, | 511 | dma_sync_single_for_device(&mp->myri_op->dev, |
| 504 | sbus_readl(&rxd->myri_scatters[0].addr), | 512 | sbus_readl(&rxd->myri_scatters[0].addr), |
| 505 | RX_ALLOC_SIZE, | 513 | RX_ALLOC_SIZE, |
| 506 | SBUS_DMA_FROMDEVICE); | 514 | DMA_FROM_DEVICE); |
| 507 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); | 515 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); |
| 508 | sbus_writel(index, &rxd->ctx); | 516 | sbus_writel(index, &rxd->ctx); |
| 509 | sbus_writel(1, &rxd->num_sg); | 517 | sbus_writel(1, &rxd->num_sg); |
| @@ -652,7 +660,8 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 652 | sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]); | 660 | sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]); |
| 653 | } | 661 | } |
| 654 | 662 | ||
| 655 | dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len, SBUS_DMA_TODEVICE); | 663 | dma_addr = dma_map_single(&mp->myri_op->dev, skb->data, |
| 664 | len, DMA_TO_DEVICE); | ||
| 656 | sbus_writel(dma_addr, &txd->myri_gathers[0].addr); | 665 | sbus_writel(dma_addr, &txd->myri_gathers[0].addr); |
| 657 | sbus_writel(len, &txd->myri_gathers[0].len); | 666 | sbus_writel(len, &txd->myri_gathers[0].len); |
| 658 | sbus_writel(1, &txd->num_sg); | 667 | sbus_writel(1, &txd->num_sg); |
| @@ -891,30 +900,30 @@ static const struct header_ops myri_header_ops = { | |||
| 891 | .cache_update = myri_header_cache_update, | 900 | .cache_update = myri_header_cache_update, |
| 892 | }; | 901 | }; |
| 893 | 902 | ||
| 894 | static int __devinit myri_ether_init(struct sbus_dev *sdev) | 903 | static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) |
| 895 | { | 904 | { |
| 896 | static int num; | 905 | struct device_node *dp = op->node; |
| 897 | static unsigned version_printed; | 906 | static unsigned version_printed; |
| 898 | struct net_device *dev; | 907 | struct net_device *dev; |
| 899 | struct myri_eth *mp; | ||
| 900 | unsigned char prop_buf[32]; | ||
| 901 | int i; | ||
| 902 | DECLARE_MAC_BUF(mac); | 908 | DECLARE_MAC_BUF(mac); |
| 909 | struct myri_eth *mp; | ||
| 910 | const void *prop; | ||
| 911 | static int num; | ||
| 912 | int i, len; | ||
| 903 | 913 | ||
| 904 | DET(("myri_ether_init(%p,%d):\n", sdev, num)); | 914 | DET(("myri_ether_init(%p,%d):\n", op, num)); |
| 905 | dev = alloc_etherdev(sizeof(struct myri_eth)); | 915 | dev = alloc_etherdev(sizeof(struct myri_eth)); |
| 906 | |||
| 907 | if (!dev) | 916 | if (!dev) |
| 908 | return -ENOMEM; | 917 | return -ENOMEM; |
| 909 | 918 | ||
| 910 | if (version_printed++ == 0) | 919 | if (version_printed++ == 0) |
| 911 | printk(version); | 920 | printk(version); |
| 912 | 921 | ||
| 913 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 922 | SET_NETDEV_DEV(dev, &op->dev); |
| 914 | 923 | ||
| 915 | mp = (struct myri_eth *) dev->priv; | 924 | mp = netdev_priv(dev); |
| 916 | spin_lock_init(&mp->irq_lock); | 925 | spin_lock_init(&mp->irq_lock); |
| 917 | mp->myri_sdev = sdev; | 926 | mp->myri_op = op; |
| 918 | 927 | ||
| 919 | /* Clean out skb arrays. */ | 928 | /* Clean out skb arrays. */ |
| 920 | for (i = 0; i < (RX_RING_SIZE + 1); i++) | 929 | for (i = 0; i < (RX_RING_SIZE + 1); i++) |
| @@ -924,55 +933,44 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
| 924 | mp->tx_skbs[i] = NULL; | 933 | mp->tx_skbs[i] = NULL; |
| 925 | 934 | ||
| 926 | /* First check for EEPROM information. */ | 935 | /* First check for EEPROM information. */ |
| 927 | i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info", | 936 | prop = of_get_property(dp, "myrinet-eeprom-info", &len); |
| 928 | (char *)&mp->eeprom, sizeof(struct myri_eeprom)); | 937 | |
| 929 | DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i)); | 938 | if (prop) |
| 930 | if (i == 0 || i == -1) { | 939 | memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom)); |
| 940 | if (!prop) { | ||
| 931 | /* No eeprom property, must cook up the values ourselves. */ | 941 | /* No eeprom property, must cook up the values ourselves. */ |
| 932 | DET(("No EEPROM: ")); | 942 | DET(("No EEPROM: ")); |
| 933 | mp->eeprom.bus_type = BUS_TYPE_SBUS; | 943 | mp->eeprom.bus_type = BUS_TYPE_SBUS; |
| 934 | mp->eeprom.cpuvers = prom_getintdefault(sdev->prom_node,"cpu_version",0); | 944 | mp->eeprom.cpuvers = |
| 935 | mp->eeprom.cval = prom_getintdefault(sdev->prom_node,"clock_value",0); | 945 | of_getintprop_default(dp, "cpu_version", 0); |
| 936 | mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0); | 946 | mp->eeprom.cval = |
| 937 | DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers, | 947 | of_getintprop_default(dp, "clock_value", 0); |
| 938 | mp->eeprom.cval, mp->eeprom.ramsz)); | 948 | mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0); |
| 939 | if (mp->eeprom.cpuvers == 0) { | 949 | if (!mp->eeprom.cpuvers) |
| 940 | DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3)); | ||
| 941 | mp->eeprom.cpuvers = CPUVERS_2_3; | 950 | mp->eeprom.cpuvers = CPUVERS_2_3; |
| 942 | } | 951 | if (mp->eeprom.cpuvers < CPUVERS_3_0) |
| 943 | if (mp->eeprom.cpuvers < CPUVERS_3_0) { | ||
| 944 | DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n")); | ||
| 945 | mp->eeprom.cval = 0; | 952 | mp->eeprom.cval = 0; |
| 946 | } | 953 | if (!mp->eeprom.ramsz) |
| 947 | if (mp->eeprom.ramsz == 0) { | ||
| 948 | DET(("EEPROM: ramsz == 0, setting to 128k\n")); | ||
| 949 | mp->eeprom.ramsz = (128 * 1024); | 954 | mp->eeprom.ramsz = (128 * 1024); |
| 950 | } | 955 | |
| 951 | i = prom_getproperty(sdev->prom_node, "myrinet-board-id", | 956 | prop = of_get_property(dp, "myrinet-board-id", &len); |
| 952 | &prop_buf[0], 10); | 957 | if (prop) |
| 953 | DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i)); | 958 | memcpy(&mp->eeprom.id[0], prop, 6); |
| 954 | if ((i != 0) && (i != -1)) | ||
| 955 | memcpy(&mp->eeprom.id[0], &prop_buf[0], 6); | ||
| 956 | else | 959 | else |
| 957 | set_boardid_from_idprom(mp, num); | 960 | set_boardid_from_idprom(mp, num); |
| 958 | i = prom_getproperty(sdev->prom_node, "fpga_version", | 961 | |
| 959 | &mp->eeprom.fvers[0], 32); | 962 | prop = of_get_property(dp, "fpga_version", &len); |
| 960 | DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i)); | 963 | if (prop) |
| 961 | if (i == 0 || i == -1) | 964 | memcpy(&mp->eeprom.fvers[0], prop, 32); |
| 965 | else | ||
| 962 | memset(&mp->eeprom.fvers[0], 0, 32); | 966 | memset(&mp->eeprom.fvers[0], 0, 32); |
| 963 | 967 | ||
| 964 | if (mp->eeprom.cpuvers == CPUVERS_4_1) { | 968 | if (mp->eeprom.cpuvers == CPUVERS_4_1) { |
| 965 | DET(("EEPROM: cpuvers CPUVERS_4_1, ")); | 969 | if (mp->eeprom.ramsz == (128 * 1024)) |
| 966 | if (mp->eeprom.ramsz == (128 * 1024)) { | ||
| 967 | DET(("ramsize 128k, setting to 256k, ")); | ||
| 968 | mp->eeprom.ramsz = (256 * 1024); | 970 | mp->eeprom.ramsz = (256 * 1024); |
| 969 | } | 971 | if ((mp->eeprom.cval == 0x40414041) || |
| 970 | if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){ | 972 | (mp->eeprom.cval == 0x90449044)) |
| 971 | DET(("changing cval from %08x to %08x ", | ||
| 972 | mp->eeprom.cval, 0x50e450e4)); | ||
| 973 | mp->eeprom.cval = 0x50e450e4; | 973 | mp->eeprom.cval = 0x50e450e4; |
| 974 | } | ||
| 975 | DET(("\n")); | ||
| 976 | } | 974 | } |
| 977 | } | 975 | } |
| 978 | #ifdef DEBUG_DETECT | 976 | #ifdef DEBUG_DETECT |
| @@ -991,8 +989,8 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
| 991 | * XXX only a valid version for PCI cards? Ask feldy... | 989 | * XXX only a valid version for PCI cards? Ask feldy... |
| 992 | */ | 990 | */ |
| 993 | DET(("Mapping regs for cpuvers < CPUVERS_4_0\n")); | 991 | DET(("Mapping regs for cpuvers < CPUVERS_4_0\n")); |
| 994 | mp->regs = sbus_ioremap(&sdev->resource[0], 0, | 992 | mp->regs = of_ioremap(&op->resource[0], 0, |
| 995 | mp->reg_size, "MyriCOM Regs"); | 993 | mp->reg_size, "MyriCOM Regs"); |
| 996 | if (!mp->regs) { | 994 | if (!mp->regs) { |
| 997 | printk("MyriCOM: Cannot map MyriCOM registers.\n"); | 995 | printk("MyriCOM: Cannot map MyriCOM registers.\n"); |
| 998 | goto err; | 996 | goto err; |
| @@ -1001,13 +999,12 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
| 1001 | mp->lregs = mp->lanai + (0x10000 * 2); | 999 | mp->lregs = mp->lanai + (0x10000 * 2); |
| 1002 | } else { | 1000 | } else { |
| 1003 | DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n")); | 1001 | DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n")); |
| 1004 | mp->cregs = sbus_ioremap(&sdev->resource[0], 0, | 1002 | mp->cregs = of_ioremap(&op->resource[0], 0, |
| 1005 | PAGE_SIZE, "MyriCOM Control Regs"); | 1003 | PAGE_SIZE, "MyriCOM Control Regs"); |
| 1006 | mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024), | 1004 | mp->lregs = of_ioremap(&op->resource[0], (256 * 1024), |
| 1007 | PAGE_SIZE, "MyriCOM LANAI Regs"); | 1005 | PAGE_SIZE, "MyriCOM LANAI Regs"); |
| 1008 | mp->lanai = | 1006 | mp->lanai = of_ioremap(&op->resource[0], (512 * 1024), |
| 1009 | sbus_ioremap(&sdev->resource[0], (512 * 1024), | 1007 | mp->eeprom.ramsz, "MyriCOM SRAM"); |
| 1010 | mp->eeprom.ramsz, "MyriCOM SRAM"); | ||
| 1011 | } | 1008 | } |
| 1012 | DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n", | 1009 | DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n", |
| 1013 | mp->cregs, mp->lregs, mp->lanai)); | 1010 | mp->cregs, mp->lregs, mp->lanai)); |
| @@ -1039,16 +1036,15 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
| 1039 | myri_reset_on(mp->cregs); | 1036 | myri_reset_on(mp->cregs); |
| 1040 | 1037 | ||
| 1041 | /* Get the supported DVMA burst sizes from our SBUS. */ | 1038 | /* Get the supported DVMA burst sizes from our SBUS. */ |
| 1042 | mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node, | 1039 | mp->myri_bursts = of_getintprop_default(dp->parent, |
| 1043 | "burst-sizes", 0x00); | 1040 | "burst-sizes", 0x00); |
| 1044 | 1041 | if (!sbus_can_burst64()) | |
| 1045 | if (!sbus_can_burst64(sdev)) | ||
| 1046 | mp->myri_bursts &= ~(DMA_BURST64); | 1042 | mp->myri_bursts &= ~(DMA_BURST64); |
| 1047 | 1043 | ||
| 1048 | DET(("MYRI bursts %02x\n", mp->myri_bursts)); | 1044 | DET(("MYRI bursts %02x\n", mp->myri_bursts)); |
| 1049 | 1045 | ||
| 1050 | /* Encode SBUS interrupt level in second control register. */ | 1046 | /* Encode SBUS interrupt level in second control register. */ |
| 1051 | i = prom_getint(sdev->prom_node, "interrupts"); | 1047 | i = of_getintprop_default(dp, "interrupts", 0); |
| 1052 | if (i == 0) | 1048 | if (i == 0) |
| 1053 | i = 4; | 1049 | i = 4; |
| 1054 | DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n", | 1050 | DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n", |
| @@ -1063,7 +1059,7 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
| 1063 | dev->tx_timeout = &myri_tx_timeout; | 1059 | dev->tx_timeout = &myri_tx_timeout; |
| 1064 | dev->watchdog_timeo = 5*HZ; | 1060 | dev->watchdog_timeo = 5*HZ; |
| 1065 | dev->set_multicast_list = &myri_set_multicast; | 1061 | dev->set_multicast_list = &myri_set_multicast; |
| 1066 | dev->irq = sdev->irqs[0]; | 1062 | dev->irq = op->irqs[0]; |
| 1067 | 1063 | ||
| 1068 | /* Register interrupt handler now. */ | 1064 | /* Register interrupt handler now. */ |
| 1069 | DET(("Requesting MYRIcom IRQ line.\n")); | 1065 | DET(("Requesting MYRIcom IRQ line.\n")); |
| @@ -1088,7 +1084,7 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
| 1088 | goto err_free_irq; | 1084 | goto err_free_irq; |
| 1089 | } | 1085 | } |
| 1090 | 1086 | ||
| 1091 | dev_set_drvdata(&sdev->ofdev.dev, mp); | 1087 | dev_set_drvdata(&op->dev, mp); |
| 1092 | 1088 | ||
| 1093 | num++; | 1089 | num++; |
| 1094 | 1090 | ||
| @@ -1105,17 +1101,9 @@ err: | |||
| 1105 | return -ENODEV; | 1101 | return -ENODEV; |
| 1106 | } | 1102 | } |
| 1107 | 1103 | ||
| 1108 | 1104 | static int __devexit myri_sbus_remove(struct of_device *op) | |
| 1109 | static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
| 1110 | { | ||
| 1111 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
| 1112 | |||
| 1113 | return myri_ether_init(sdev); | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | static int __devexit myri_sbus_remove(struct of_device *dev) | ||
| 1117 | { | 1105 | { |
| 1118 | struct myri_eth *mp = dev_get_drvdata(&dev->dev); | 1106 | struct myri_eth *mp = dev_get_drvdata(&op->dev); |
| 1119 | struct net_device *net_dev = mp->dev; | 1107 | struct net_device *net_dev = mp->dev; |
| 1120 | 1108 | ||
| 1121 | unregister_netdev(net_dev); | 1109 | unregister_netdev(net_dev); |
| @@ -1123,21 +1111,21 @@ static int __devexit myri_sbus_remove(struct of_device *dev) | |||
| 1123 | free_irq(net_dev->irq, net_dev); | 1111 | free_irq(net_dev->irq, net_dev); |
| 1124 | 1112 | ||
| 1125 | if (mp->eeprom.cpuvers < CPUVERS_4_0) { | 1113 | if (mp->eeprom.cpuvers < CPUVERS_4_0) { |
| 1126 | sbus_iounmap(mp->regs, mp->reg_size); | 1114 | of_iounmap(&op->resource[0], mp->regs, mp->reg_size); |
| 1127 | } else { | 1115 | } else { |
| 1128 | sbus_iounmap(mp->cregs, PAGE_SIZE); | 1116 | of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE); |
| 1129 | sbus_iounmap(mp->lregs, (256 * 1024)); | 1117 | of_iounmap(&op->resource[0], mp->lregs, (256 * 1024)); |
| 1130 | sbus_iounmap(mp->lanai, (512 * 1024)); | 1118 | of_iounmap(&op->resource[0], mp->lanai, (512 * 1024)); |
| 1131 | } | 1119 | } |
| 1132 | 1120 | ||
| 1133 | free_netdev(net_dev); | 1121 | free_netdev(net_dev); |
| 1134 | 1122 | ||
| 1135 | dev_set_drvdata(&dev->dev, NULL); | 1123 | dev_set_drvdata(&op->dev, NULL); |
| 1136 | 1124 | ||
| 1137 | return 0; | 1125 | return 0; |
| 1138 | } | 1126 | } |
| 1139 | 1127 | ||
| 1140 | static struct of_device_id myri_sbus_match[] = { | 1128 | static const struct of_device_id myri_sbus_match[] = { |
| 1141 | { | 1129 | { |
| 1142 | .name = "MYRICOM,mlanai", | 1130 | .name = "MYRICOM,mlanai", |
| 1143 | }, | 1131 | }, |
| @@ -1158,7 +1146,7 @@ static struct of_platform_driver myri_sbus_driver = { | |||
| 1158 | 1146 | ||
| 1159 | static int __init myri_sbus_init(void) | 1147 | static int __init myri_sbus_init(void) |
| 1160 | { | 1148 | { |
| 1161 | return of_register_driver(&myri_sbus_driver, &sbus_bus_type); | 1149 | return of_register_driver(&myri_sbus_driver, &of_bus_type); |
| 1162 | } | 1150 | } |
| 1163 | 1151 | ||
| 1164 | static void __exit myri_sbus_exit(void) | 1152 | static void __exit myri_sbus_exit(void) |
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index 5d93fcc95d55..ff363e95d9cf 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h | |||
| @@ -288,7 +288,7 @@ struct myri_eth { | |||
| 288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ | 288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ |
| 289 | unsigned int reg_size; /* Size of register space. */ | 289 | unsigned int reg_size; /* Size of register space. */ |
| 290 | unsigned int shmem_base; /* Offset to shared ram. */ | 290 | unsigned int shmem_base; /* Offset to shared ram. */ |
| 291 | struct sbus_dev *myri_sdev; /* Our SBUS device struct. */ | 291 | struct of_device *myri_op; /* Our OF device struct. */ |
| 292 | }; | 292 | }; |
| 293 | 293 | ||
| 294 | /* We use this to acquire receive skb's that we can DMA directly into. */ | 294 | /* We use this to acquire receive skb's that we can DMA directly into. */ |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index e3be81eba8a4..ebc812702903 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
| @@ -9130,7 +9130,7 @@ static int __devexit niu_of_remove(struct of_device *op) | |||
| 9130 | return 0; | 9130 | return 0; |
| 9131 | } | 9131 | } |
| 9132 | 9132 | ||
| 9133 | static struct of_device_id niu_match[] = { | 9133 | static const struct of_device_id niu_match[] = { |
| 9134 | { | 9134 | { |
| 9135 | .name = "network", | 9135 | .name = "network", |
| 9136 | .compatible = "SUNW,niusl", | 9136 | .compatible = "SUNW,niusl", |
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 31e7384e312a..018d0fca9422 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | /* $Id: sunbmac.c,v 1.30 2002/01/15 06:48:55 davem Exp $ | 1 | /* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. |
| 2 | * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. | ||
| 3 | * | 2 | * |
| 4 | * Copyright (C) 1997, 1998, 1999, 2003 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1997, 1998, 1999, 2003, 2008 David S. Miller (davem@davemloft.net) |
| 5 | */ | 4 | */ |
| 6 | 5 | ||
| 7 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| @@ -23,6 +22,9 @@ | |||
| 23 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
| 24 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
| 25 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
| 25 | #include <linux/dma-mapping.h> | ||
| 26 | #include <linux/of.h> | ||
| 27 | #include <linux/of_device.h> | ||
| 26 | 28 | ||
| 27 | #include <asm/auxio.h> | 29 | #include <asm/auxio.h> |
| 28 | #include <asm/byteorder.h> | 30 | #include <asm/byteorder.h> |
| @@ -32,15 +34,14 @@ | |||
| 32 | #include <asm/openprom.h> | 34 | #include <asm/openprom.h> |
| 33 | #include <asm/oplib.h> | 35 | #include <asm/oplib.h> |
| 34 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
| 35 | #include <asm/sbus.h> | ||
| 36 | #include <asm/system.h> | 37 | #include <asm/system.h> |
| 37 | 38 | ||
| 38 | #include "sunbmac.h" | 39 | #include "sunbmac.h" |
| 39 | 40 | ||
| 40 | #define DRV_NAME "sunbmac" | 41 | #define DRV_NAME "sunbmac" |
| 41 | #define DRV_VERSION "2.0" | 42 | #define DRV_VERSION "2.1" |
| 42 | #define DRV_RELDATE "11/24/03" | 43 | #define DRV_RELDATE "August 26, 2008" |
| 43 | #define DRV_AUTHOR "David S. Miller (davem@redhat.com)" | 44 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
| 44 | 45 | ||
| 45 | static char version[] = | 46 | static char version[] = |
| 46 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; | 47 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; |
| @@ -96,8 +97,8 @@ static int qec_global_reset(void __iomem *gregs) | |||
| 96 | 97 | ||
| 97 | static void qec_init(struct bigmac *bp) | 98 | static void qec_init(struct bigmac *bp) |
| 98 | { | 99 | { |
| 100 | struct of_device *qec_op = bp->qec_op; | ||
| 99 | void __iomem *gregs = bp->gregs; | 101 | void __iomem *gregs = bp->gregs; |
| 100 | struct sbus_dev *qec_sdev = bp->qec_sdev; | ||
| 101 | u8 bsizes = bp->bigmac_bursts; | 102 | u8 bsizes = bp->bigmac_bursts; |
| 102 | u32 regval; | 103 | u32 regval; |
| 103 | 104 | ||
| @@ -112,13 +113,13 @@ static void qec_init(struct bigmac *bp) | |||
| 112 | sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE); | 113 | sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE); |
| 113 | 114 | ||
| 114 | /* All of memsize is given to bigmac. */ | 115 | /* All of memsize is given to bigmac. */ |
| 115 | sbus_writel(qec_sdev->reg_addrs[1].reg_size, | 116 | sbus_writel(resource_size(&qec_op->resource[1]), |
| 116 | gregs + GLOB_MSIZE); | 117 | gregs + GLOB_MSIZE); |
| 117 | 118 | ||
| 118 | /* Half to the transmitter, half to the receiver. */ | 119 | /* Half to the transmitter, half to the receiver. */ |
| 119 | sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1, | 120 | sbus_writel(resource_size(&qec_op->resource[1]) >> 1, |
| 120 | gregs + GLOB_TSIZE); | 121 | gregs + GLOB_TSIZE); |
| 121 | sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1, | 122 | sbus_writel(resource_size(&qec_op->resource[1]) >> 1, |
| 122 | gregs + GLOB_RSIZE); | 123 | gregs + GLOB_RSIZE); |
| 123 | } | 124 | } |
| 124 | 125 | ||
| @@ -239,9 +240,10 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq) | |||
| 239 | skb_reserve(skb, 34); | 240 | skb_reserve(skb, 34); |
| 240 | 241 | ||
| 241 | bb->be_rxd[i].rx_addr = | 242 | bb->be_rxd[i].rx_addr = |
| 242 | sbus_map_single(bp->bigmac_sdev, skb->data, | 243 | dma_map_single(&bp->bigmac_op->dev, |
| 243 | RX_BUF_ALLOC_SIZE - 34, | 244 | skb->data, |
| 244 | SBUS_DMA_FROMDEVICE); | 245 | RX_BUF_ALLOC_SIZE - 34, |
| 246 | DMA_FROM_DEVICE); | ||
| 245 | bb->be_rxd[i].rx_flags = | 247 | bb->be_rxd[i].rx_flags = |
| 246 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); | 248 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); |
| 247 | } | 249 | } |
| @@ -776,9 +778,9 @@ static void bigmac_tx(struct bigmac *bp) | |||
| 776 | skb = bp->tx_skbs[elem]; | 778 | skb = bp->tx_skbs[elem]; |
| 777 | bp->enet_stats.tx_packets++; | 779 | bp->enet_stats.tx_packets++; |
| 778 | bp->enet_stats.tx_bytes += skb->len; | 780 | bp->enet_stats.tx_bytes += skb->len; |
| 779 | sbus_unmap_single(bp->bigmac_sdev, | 781 | dma_unmap_single(&bp->bigmac_op->dev, |
| 780 | this->tx_addr, skb->len, | 782 | this->tx_addr, skb->len, |
| 781 | SBUS_DMA_TODEVICE); | 783 | DMA_TO_DEVICE); |
| 782 | 784 | ||
| 783 | DTX(("skb(%p) ", skb)); | 785 | DTX(("skb(%p) ", skb)); |
| 784 | bp->tx_skbs[elem] = NULL; | 786 | bp->tx_skbs[elem] = NULL; |
| @@ -831,18 +833,19 @@ static void bigmac_rx(struct bigmac *bp) | |||
| 831 | drops++; | 833 | drops++; |
| 832 | goto drop_it; | 834 | goto drop_it; |
| 833 | } | 835 | } |
| 834 | sbus_unmap_single(bp->bigmac_sdev, | 836 | dma_unmap_single(&bp->bigmac_op->dev, |
| 835 | this->rx_addr, | 837 | this->rx_addr, |
| 836 | RX_BUF_ALLOC_SIZE - 34, | 838 | RX_BUF_ALLOC_SIZE - 34, |
| 837 | SBUS_DMA_FROMDEVICE); | 839 | DMA_FROM_DEVICE); |
| 838 | bp->rx_skbs[elem] = new_skb; | 840 | bp->rx_skbs[elem] = new_skb; |
| 839 | new_skb->dev = bp->dev; | 841 | new_skb->dev = bp->dev; |
| 840 | skb_put(new_skb, ETH_FRAME_LEN); | 842 | skb_put(new_skb, ETH_FRAME_LEN); |
| 841 | skb_reserve(new_skb, 34); | 843 | skb_reserve(new_skb, 34); |
| 842 | this->rx_addr = sbus_map_single(bp->bigmac_sdev, | 844 | this->rx_addr = |
| 843 | new_skb->data, | 845 | dma_map_single(&bp->bigmac_op->dev, |
| 844 | RX_BUF_ALLOC_SIZE - 34, | 846 | new_skb->data, |
| 845 | SBUS_DMA_FROMDEVICE); | 847 | RX_BUF_ALLOC_SIZE - 34, |
| 848 | DMA_FROM_DEVICE); | ||
| 846 | this->rx_flags = | 849 | this->rx_flags = |
| 847 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); | 850 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); |
| 848 | 851 | ||
| @@ -857,13 +860,13 @@ static void bigmac_rx(struct bigmac *bp) | |||
| 857 | } | 860 | } |
| 858 | skb_reserve(copy_skb, 2); | 861 | skb_reserve(copy_skb, 2); |
| 859 | skb_put(copy_skb, len); | 862 | skb_put(copy_skb, len); |
| 860 | sbus_dma_sync_single_for_cpu(bp->bigmac_sdev, | 863 | dma_sync_single_for_cpu(&bp->bigmac_op->dev, |
| 861 | this->rx_addr, len, | 864 | this->rx_addr, len, |
| 862 | SBUS_DMA_FROMDEVICE); | 865 | DMA_FROM_DEVICE); |
| 863 | skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len); | 866 | skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len); |
| 864 | sbus_dma_sync_single_for_device(bp->bigmac_sdev, | 867 | dma_sync_single_for_device(&bp->bigmac_op->dev, |
| 865 | this->rx_addr, len, | 868 | this->rx_addr, len, |
| 866 | SBUS_DMA_FROMDEVICE); | 869 | DMA_FROM_DEVICE); |
| 867 | 870 | ||
| 868 | /* Reuse original ring buffer. */ | 871 | /* Reuse original ring buffer. */ |
| 869 | this->rx_flags = | 872 | this->rx_flags = |
| @@ -959,7 +962,8 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 959 | u32 mapping; | 962 | u32 mapping; |
| 960 | 963 | ||
| 961 | len = skb->len; | 964 | len = skb->len; |
| 962 | mapping = sbus_map_single(bp->bigmac_sdev, skb->data, len, SBUS_DMA_TODEVICE); | 965 | mapping = dma_map_single(&bp->bigmac_op->dev, skb->data, |
| 966 | len, DMA_TO_DEVICE); | ||
| 963 | 967 | ||
| 964 | /* Avoid a race... */ | 968 | /* Avoid a race... */ |
| 965 | spin_lock_irq(&bp->lock); | 969 | spin_lock_irq(&bp->lock); |
| @@ -1051,12 +1055,8 @@ static void bigmac_set_multicast(struct net_device *dev) | |||
| 1051 | /* Ethtool support... */ | 1055 | /* Ethtool support... */ |
| 1052 | static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 1056 | static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
| 1053 | { | 1057 | { |
| 1054 | struct bigmac *bp = dev->priv; | ||
| 1055 | |||
| 1056 | strcpy(info->driver, "sunbmac"); | 1058 | strcpy(info->driver, "sunbmac"); |
| 1057 | strcpy(info->version, "2.0"); | 1059 | strcpy(info->version, "2.0"); |
| 1058 | sprintf(info->bus_info, "SBUS:%d", | ||
| 1059 | bp->qec_sdev->slot); | ||
| 1060 | } | 1060 | } |
| 1061 | 1061 | ||
| 1062 | static u32 bigmac_get_link(struct net_device *dev) | 1062 | static u32 bigmac_get_link(struct net_device *dev) |
| @@ -1075,14 +1075,15 @@ static const struct ethtool_ops bigmac_ethtool_ops = { | |||
| 1075 | .get_link = bigmac_get_link, | 1075 | .get_link = bigmac_get_link, |
| 1076 | }; | 1076 | }; |
| 1077 | 1077 | ||
| 1078 | static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | 1078 | static int __devinit bigmac_ether_init(struct of_device *op, |
| 1079 | struct of_device *qec_op) | ||
| 1079 | { | 1080 | { |
| 1080 | struct net_device *dev; | ||
| 1081 | static int version_printed; | 1081 | static int version_printed; |
| 1082 | struct bigmac *bp; | 1082 | struct net_device *dev; |
| 1083 | u8 bsizes, bsizes_more; | 1083 | u8 bsizes, bsizes_more; |
| 1084 | int i; | ||
| 1085 | DECLARE_MAC_BUF(mac); | 1084 | DECLARE_MAC_BUF(mac); |
| 1085 | struct bigmac *bp; | ||
| 1086 | int i; | ||
| 1086 | 1087 | ||
| 1087 | /* Get a new device struct for this interface. */ | 1088 | /* Get a new device struct for this interface. */ |
| 1088 | dev = alloc_etherdev(sizeof(struct bigmac)); | 1089 | dev = alloc_etherdev(sizeof(struct bigmac)); |
| @@ -1092,32 +1093,21 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1092 | if (version_printed++ == 0) | 1093 | if (version_printed++ == 0) |
| 1093 | printk(KERN_INFO "%s", version); | 1094 | printk(KERN_INFO "%s", version); |
| 1094 | 1095 | ||
| 1095 | dev->base_addr = (long) qec_sdev; | ||
| 1096 | for (i = 0; i < 6; i++) | 1096 | for (i = 0; i < 6; i++) |
| 1097 | dev->dev_addr[i] = idprom->id_ethaddr[i]; | 1097 | dev->dev_addr[i] = idprom->id_ethaddr[i]; |
| 1098 | 1098 | ||
| 1099 | /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ | 1099 | /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ |
| 1100 | bp = dev->priv; | 1100 | bp = netdev_priv(dev); |
| 1101 | bp->qec_sdev = qec_sdev; | 1101 | bp->qec_op = qec_op; |
| 1102 | bp->bigmac_sdev = qec_sdev->child; | 1102 | bp->bigmac_op = op; |
| 1103 | 1103 | ||
| 1104 | SET_NETDEV_DEV(dev, &bp->bigmac_sdev->ofdev.dev); | 1104 | SET_NETDEV_DEV(dev, &op->dev); |
| 1105 | 1105 | ||
| 1106 | spin_lock_init(&bp->lock); | 1106 | spin_lock_init(&bp->lock); |
| 1107 | 1107 | ||
| 1108 | /* Verify the registers we expect, are actually there. */ | ||
| 1109 | if ((bp->bigmac_sdev->num_registers != 3) || | ||
| 1110 | (bp->qec_sdev->num_registers != 2)) { | ||
| 1111 | printk(KERN_ERR "BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n", | ||
| 1112 | bp->qec_sdev->num_registers, | ||
| 1113 | bp->bigmac_sdev->num_registers); | ||
| 1114 | printk(KERN_ERR "BIGMAC: Would you like that for here or to go?\n"); | ||
| 1115 | goto fail_and_cleanup; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /* Map in QEC global control registers. */ | 1108 | /* Map in QEC global control registers. */ |
| 1119 | bp->gregs = sbus_ioremap(&bp->qec_sdev->resource[0], 0, | 1109 | bp->gregs = of_ioremap(&qec_op->resource[0], 0, |
| 1120 | GLOB_REG_SIZE, "BigMAC QEC GLobal Regs"); | 1110 | GLOB_REG_SIZE, "BigMAC QEC GLobal Regs"); |
| 1121 | if (!bp->gregs) { | 1111 | if (!bp->gregs) { |
| 1122 | printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n"); | 1112 | printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n"); |
| 1123 | goto fail_and_cleanup; | 1113 | goto fail_and_cleanup; |
| @@ -1134,13 +1124,8 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1134 | goto fail_and_cleanup; | 1124 | goto fail_and_cleanup; |
| 1135 | 1125 | ||
| 1136 | /* Get supported SBUS burst sizes. */ | 1126 | /* Get supported SBUS burst sizes. */ |
| 1137 | bsizes = prom_getintdefault(bp->qec_sdev->prom_node, | 1127 | bsizes = of_getintprop_default(qec_op->node, "burst-sizes", 0xff); |
| 1138 | "burst-sizes", | 1128 | bsizes_more = of_getintprop_default(qec_op->node, "burst-sizes", 0xff); |
| 1139 | 0xff); | ||
| 1140 | |||
| 1141 | bsizes_more = prom_getintdefault(bp->qec_sdev->bus->prom_node, | ||
| 1142 | "burst-sizes", | ||
| 1143 | 0xff); | ||
| 1144 | 1129 | ||
| 1145 | bsizes &= 0xff; | 1130 | bsizes &= 0xff; |
| 1146 | if (bsizes_more != 0xff) | 1131 | if (bsizes_more != 0xff) |
| @@ -1154,16 +1139,16 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1154 | qec_init(bp); | 1139 | qec_init(bp); |
| 1155 | 1140 | ||
| 1156 | /* Map in the BigMAC channel registers. */ | 1141 | /* Map in the BigMAC channel registers. */ |
| 1157 | bp->creg = sbus_ioremap(&bp->bigmac_sdev->resource[0], 0, | 1142 | bp->creg = of_ioremap(&op->resource[0], 0, |
| 1158 | CREG_REG_SIZE, "BigMAC QEC Channel Regs"); | 1143 | CREG_REG_SIZE, "BigMAC QEC Channel Regs"); |
| 1159 | if (!bp->creg) { | 1144 | if (!bp->creg) { |
| 1160 | printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n"); | 1145 | printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n"); |
| 1161 | goto fail_and_cleanup; | 1146 | goto fail_and_cleanup; |
| 1162 | } | 1147 | } |
| 1163 | 1148 | ||
| 1164 | /* Map in the BigMAC control registers. */ | 1149 | /* Map in the BigMAC control registers. */ |
| 1165 | bp->bregs = sbus_ioremap(&bp->bigmac_sdev->resource[1], 0, | 1150 | bp->bregs = of_ioremap(&op->resource[1], 0, |
| 1166 | BMAC_REG_SIZE, "BigMAC Primary Regs"); | 1151 | BMAC_REG_SIZE, "BigMAC Primary Regs"); |
| 1167 | if (!bp->bregs) { | 1152 | if (!bp->bregs) { |
| 1168 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n"); | 1153 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n"); |
| 1169 | goto fail_and_cleanup; | 1154 | goto fail_and_cleanup; |
| @@ -1172,8 +1157,8 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1172 | /* Map in the BigMAC transceiver registers, this is how you poke at | 1157 | /* Map in the BigMAC transceiver registers, this is how you poke at |
| 1173 | * the BigMAC's PHY. | 1158 | * the BigMAC's PHY. |
| 1174 | */ | 1159 | */ |
| 1175 | bp->tregs = sbus_ioremap(&bp->bigmac_sdev->resource[2], 0, | 1160 | bp->tregs = of_ioremap(&op->resource[2], 0, |
| 1176 | TCVR_REG_SIZE, "BigMAC Transceiver Regs"); | 1161 | TCVR_REG_SIZE, "BigMAC Transceiver Regs"); |
| 1177 | if (!bp->tregs) { | 1162 | if (!bp->tregs) { |
| 1178 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n"); | 1163 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n"); |
| 1179 | goto fail_and_cleanup; | 1164 | goto fail_and_cleanup; |
| @@ -1183,17 +1168,17 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1183 | bigmac_stop(bp); | 1168 | bigmac_stop(bp); |
| 1184 | 1169 | ||
| 1185 | /* Allocate transmit/receive descriptor DVMA block. */ | 1170 | /* Allocate transmit/receive descriptor DVMA block. */ |
| 1186 | bp->bmac_block = sbus_alloc_consistent(bp->bigmac_sdev, | 1171 | bp->bmac_block = dma_alloc_coherent(&bp->bigmac_op->dev, |
| 1187 | PAGE_SIZE, | 1172 | PAGE_SIZE, |
| 1188 | &bp->bblock_dvma); | 1173 | &bp->bblock_dvma, GFP_ATOMIC); |
| 1189 | if (bp->bmac_block == NULL || bp->bblock_dvma == 0) { | 1174 | if (bp->bmac_block == NULL || bp->bblock_dvma == 0) { |
| 1190 | printk(KERN_ERR "BIGMAC: Cannot allocate consistent DMA.\n"); | 1175 | printk(KERN_ERR "BIGMAC: Cannot allocate consistent DMA.\n"); |
| 1191 | goto fail_and_cleanup; | 1176 | goto fail_and_cleanup; |
| 1192 | } | 1177 | } |
| 1193 | 1178 | ||
| 1194 | /* Get the board revision of this BigMAC. */ | 1179 | /* Get the board revision of this BigMAC. */ |
| 1195 | bp->board_rev = prom_getintdefault(bp->bigmac_sdev->prom_node, | 1180 | bp->board_rev = of_getintprop_default(bp->bigmac_op->node, |
| 1196 | "board-version", 1); | 1181 | "board-version", 1); |
| 1197 | 1182 | ||
| 1198 | /* Init auto-negotiation timer state. */ | 1183 | /* Init auto-negotiation timer state. */ |
| 1199 | init_timer(&bp->bigmac_timer); | 1184 | init_timer(&bp->bigmac_timer); |
| @@ -1217,7 +1202,7 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1217 | dev->watchdog_timeo = 5*HZ; | 1202 | dev->watchdog_timeo = 5*HZ; |
| 1218 | 1203 | ||
| 1219 | /* Finish net device registration. */ | 1204 | /* Finish net device registration. */ |
| 1220 | dev->irq = bp->bigmac_sdev->irqs[0]; | 1205 | dev->irq = bp->bigmac_op->irqs[0]; |
| 1221 | dev->dma = 0; | 1206 | dev->dma = 0; |
| 1222 | 1207 | ||
| 1223 | if (register_netdev(dev)) { | 1208 | if (register_netdev(dev)) { |
| @@ -1225,7 +1210,7 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
| 1225 | goto fail_and_cleanup; | 1210 | goto fail_and_cleanup; |
| 1226 | } | 1211 | } |
| 1227 | 1212 | ||
| 1228 | dev_set_drvdata(&bp->bigmac_sdev->ofdev.dev, bp); | 1213 | dev_set_drvdata(&bp->bigmac_op->dev, bp); |
| 1229 | 1214 | ||
| 1230 | printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n", | 1215 | printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n", |
| 1231 | dev->name, print_mac(mac, dev->dev_addr)); | 1216 | dev->name, print_mac(mac, dev->dev_addr)); |
| @@ -1236,66 +1221,67 @@ fail_and_cleanup: | |||
| 1236 | /* Something went wrong, undo whatever we did so far. */ | 1221 | /* Something went wrong, undo whatever we did so far. */ |
| 1237 | /* Free register mappings if any. */ | 1222 | /* Free register mappings if any. */ |
| 1238 | if (bp->gregs) | 1223 | if (bp->gregs) |
| 1239 | sbus_iounmap(bp->gregs, GLOB_REG_SIZE); | 1224 | of_iounmap(&qec_op->resource[0], bp->gregs, GLOB_REG_SIZE); |
| 1240 | if (bp->creg) | 1225 | if (bp->creg) |
| 1241 | sbus_iounmap(bp->creg, CREG_REG_SIZE); | 1226 | of_iounmap(&op->resource[0], bp->creg, CREG_REG_SIZE); |
| 1242 | if (bp->bregs) | 1227 | if (bp->bregs) |
| 1243 | sbus_iounmap(bp->bregs, BMAC_REG_SIZE); | 1228 | of_iounmap(&op->resource[1], bp->bregs, BMAC_REG_SIZE); |
| 1244 | if (bp->tregs) | 1229 | if (bp->tregs) |
| 1245 | sbus_iounmap(bp->tregs, TCVR_REG_SIZE); | 1230 | of_iounmap(&op->resource[2], bp->tregs, TCVR_REG_SIZE); |
| 1246 | 1231 | ||
| 1247 | if (bp->bmac_block) | 1232 | if (bp->bmac_block) |
| 1248 | sbus_free_consistent(bp->bigmac_sdev, | 1233 | dma_free_coherent(&bp->bigmac_op->dev, |
| 1249 | PAGE_SIZE, | 1234 | PAGE_SIZE, |
| 1250 | bp->bmac_block, | 1235 | bp->bmac_block, |
| 1251 | bp->bblock_dvma); | 1236 | bp->bblock_dvma); |
| 1252 | 1237 | ||
| 1253 | /* This also frees the co-located 'dev->priv' */ | 1238 | /* This also frees the co-located 'dev->priv' */ |
| 1254 | free_netdev(dev); | 1239 | free_netdev(dev); |
| 1255 | return -ENODEV; | 1240 | return -ENODEV; |
| 1256 | } | 1241 | } |
| 1257 | 1242 | ||
| 1258 | /* QEC can be the parent of either QuadEthernet or | 1243 | /* QEC can be the parent of either QuadEthernet or a BigMAC. We want |
| 1259 | * a BigMAC. We want the latter. | 1244 | * the latter. |
| 1260 | */ | 1245 | */ |
| 1261 | static int __devinit bigmac_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 1246 | static int __devinit bigmac_sbus_probe(struct of_device *op, |
| 1247 | const struct of_device_id *match) | ||
| 1262 | { | 1248 | { |
| 1263 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 1249 | struct device *parent = op->dev.parent; |
| 1264 | struct device_node *dp = dev->node; | 1250 | struct of_device *qec_op; |
| 1265 | 1251 | ||
| 1266 | if (!strcmp(dp->name, "be")) | 1252 | qec_op = to_of_device(parent); |
| 1267 | sdev = sdev->parent; | ||
| 1268 | 1253 | ||
| 1269 | return bigmac_ether_init(sdev); | 1254 | return bigmac_ether_init(op, qec_op); |
| 1270 | } | 1255 | } |
| 1271 | 1256 | ||
| 1272 | static int __devexit bigmac_sbus_remove(struct of_device *dev) | 1257 | static int __devexit bigmac_sbus_remove(struct of_device *op) |
| 1273 | { | 1258 | { |
| 1274 | struct bigmac *bp = dev_get_drvdata(&dev->dev); | 1259 | struct bigmac *bp = dev_get_drvdata(&op->dev); |
| 1260 | struct device *parent = op->dev.parent; | ||
| 1275 | struct net_device *net_dev = bp->dev; | 1261 | struct net_device *net_dev = bp->dev; |
| 1262 | struct of_device *qec_op; | ||
| 1263 | |||
| 1264 | qec_op = to_of_device(parent); | ||
| 1276 | 1265 | ||
| 1277 | unregister_netdev(net_dev); | 1266 | unregister_netdev(net_dev); |
| 1278 | 1267 | ||
| 1279 | sbus_iounmap(bp->gregs, GLOB_REG_SIZE); | 1268 | of_iounmap(&qec_op->resource[0], bp->gregs, GLOB_REG_SIZE); |
| 1280 | sbus_iounmap(bp->creg, CREG_REG_SIZE); | 1269 | of_iounmap(&op->resource[0], bp->creg, CREG_REG_SIZE); |
| 1281 | sbus_iounmap(bp->bregs, BMAC_REG_SIZE); | 1270 | of_iounmap(&op->resource[1], bp->bregs, BMAC_REG_SIZE); |
| 1282 | sbus_iounmap(bp->tregs, TCVR_REG_SIZE); | 1271 | of_iounmap(&op->resource[2], bp->tregs, TCVR_REG_SIZE); |
| 1283 | sbus_free_consistent(bp->bigmac_sdev, | 1272 | dma_free_coherent(&op->dev, |
| 1284 | PAGE_SIZE, | 1273 | PAGE_SIZE, |
| 1285 | bp->bmac_block, | 1274 | bp->bmac_block, |
| 1286 | bp->bblock_dvma); | 1275 | bp->bblock_dvma); |
| 1287 | 1276 | ||
| 1288 | free_netdev(net_dev); | 1277 | free_netdev(net_dev); |
| 1289 | 1278 | ||
| 1290 | dev_set_drvdata(&dev->dev, NULL); | 1279 | dev_set_drvdata(&op->dev, NULL); |
| 1291 | 1280 | ||
| 1292 | return 0; | 1281 | return 0; |
| 1293 | } | 1282 | } |
| 1294 | 1283 | ||
| 1295 | static struct of_device_id bigmac_sbus_match[] = { | 1284 | static const struct of_device_id bigmac_sbus_match[] = { |
| 1296 | { | ||
| 1297 | .name = "qec", | ||
| 1298 | }, | ||
| 1299 | { | 1285 | { |
| 1300 | .name = "be", | 1286 | .name = "be", |
| 1301 | }, | 1287 | }, |
| @@ -1313,7 +1299,7 @@ static struct of_platform_driver bigmac_sbus_driver = { | |||
| 1313 | 1299 | ||
| 1314 | static int __init bigmac_init(void) | 1300 | static int __init bigmac_init(void) |
| 1315 | { | 1301 | { |
| 1316 | return of_register_driver(&bigmac_sbus_driver, &sbus_bus_type); | 1302 | return of_register_driver(&bigmac_sbus_driver, &of_bus_type); |
| 1317 | } | 1303 | } |
| 1318 | 1304 | ||
| 1319 | static void __exit bigmac_exit(void) | 1305 | static void __exit bigmac_exit(void) |
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index b563d3c2993e..8840bc0b840b 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h | |||
| @@ -329,8 +329,8 @@ struct bigmac { | |||
| 329 | unsigned int timer_ticks; | 329 | unsigned int timer_ticks; |
| 330 | 330 | ||
| 331 | struct net_device_stats enet_stats; | 331 | struct net_device_stats enet_stats; |
| 332 | struct sbus_dev *qec_sdev; | 332 | struct of_device *qec_op; |
| 333 | struct sbus_dev *bigmac_sdev; | 333 | struct of_device *bigmac_op; |
| 334 | struct net_device *dev; | 334 | struct net_device *dev; |
| 335 | }; | 335 | }; |
| 336 | 336 | ||
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index b79d5f018f79..f1ebeb5f65b2 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. | 3 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 1996, 1998, 1999, 2002, 2003, | 5 | * Copyright (C) 1996, 1998, 1999, 2002, 2003, |
| 6 | 2006 David S. Miller (davem@davemloft.net) | 6 | * 2006, 2008 David S. Miller (davem@davemloft.net) |
| 7 | * | 7 | * |
| 8 | * Changes : | 8 | * Changes : |
| 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> | 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> |
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
| 35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
| 36 | #include <linux/bitops.h> | 36 | #include <linux/bitops.h> |
| 37 | #include <linux/dma-mapping.h> | ||
| 37 | 38 | ||
| 38 | #include <asm/system.h> | 39 | #include <asm/system.h> |
| 39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| @@ -41,8 +42,9 @@ | |||
| 41 | #include <asm/byteorder.h> | 42 | #include <asm/byteorder.h> |
| 42 | 43 | ||
| 43 | #ifdef CONFIG_SPARC | 44 | #ifdef CONFIG_SPARC |
| 45 | #include <linux/of.h> | ||
| 46 | #include <linux/of_device.h> | ||
| 44 | #include <asm/idprom.h> | 47 | #include <asm/idprom.h> |
| 45 | #include <asm/sbus.h> | ||
| 46 | #include <asm/openprom.h> | 48 | #include <asm/openprom.h> |
| 47 | #include <asm/oplib.h> | 49 | #include <asm/oplib.h> |
| 48 | #include <asm/prom.h> | 50 | #include <asm/prom.h> |
| @@ -60,8 +62,8 @@ | |||
| 60 | #include "sunhme.h" | 62 | #include "sunhme.h" |
| 61 | 63 | ||
| 62 | #define DRV_NAME "sunhme" | 64 | #define DRV_NAME "sunhme" |
| 63 | #define DRV_VERSION "3.00" | 65 | #define DRV_VERSION "3.10" |
| 64 | #define DRV_RELDATE "June 23, 2006" | 66 | #define DRV_RELDATE "August 26, 2008" |
| 65 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" | 67 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
| 66 | 68 | ||
| 67 | static char version[] = | 69 | static char version[] = |
| @@ -251,13 +253,13 @@ static u32 pci_hme_read_desc32(hme32 *p) | |||
| 251 | #define hme_read_desc32(__hp, __p) \ | 253 | #define hme_read_desc32(__hp, __p) \ |
| 252 | ((__hp)->read_desc32(__p)) | 254 | ((__hp)->read_desc32(__p)) |
| 253 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ | 255 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ |
| 254 | ((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size), (__dir))) | 256 | ((__hp)->dma_map((__hp)->dma_dev, (__ptr), (__size), (__dir))) |
| 255 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ | 257 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ |
| 256 | ((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size), (__dir))) | 258 | ((__hp)->dma_unmap((__hp)->dma_dev, (__addr), (__size), (__dir))) |
| 257 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ | 259 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ |
| 258 | ((__hp)->dma_sync_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir))) | 260 | ((__hp)->dma_sync_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir))) |
| 259 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ | 261 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ |
| 260 | ((__hp)->dma_sync_for_device((__hp)->happy_dev, (__addr), (__size), (__dir))) | 262 | ((__hp)->dma_sync_for_device((__hp)->dma_dev, (__addr), (__size), (__dir))) |
| 261 | #else | 263 | #else |
| 262 | #ifdef CONFIG_SBUS | 264 | #ifdef CONFIG_SBUS |
| 263 | /* SBUS only compilation */ | 265 | /* SBUS only compilation */ |
| @@ -277,13 +279,13 @@ do { (__txd)->tx_addr = (__force hme32)(u32)(__addr); \ | |||
| 277 | } while(0) | 279 | } while(0) |
| 278 | #define hme_read_desc32(__hp, __p) ((__force u32)(hme32)*(__p)) | 280 | #define hme_read_desc32(__hp, __p) ((__force u32)(hme32)*(__p)) |
| 279 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ | 281 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ |
| 280 | sbus_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir)) | 282 | dma_map_single((__hp)->dma_dev, (__ptr), (__size), (__dir)) |
| 281 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ | 283 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ |
| 282 | sbus_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir)) | 284 | dma_unmap_single((__hp)->dma_dev, (__addr), (__size), (__dir)) |
| 283 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ | 285 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ |
| 284 | sbus_dma_sync_single_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir)) | 286 | dma_dma_sync_single_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir)) |
| 285 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ | 287 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ |
| 286 | sbus_dma_sync_single_for_device((__hp)->happy_dev, (__addr), (__size), (__dir)) | 288 | dma_dma_sync_single_for_device((__hp)->dma_dev, (__addr), (__size), (__dir)) |
| 287 | #else | 289 | #else |
| 288 | /* PCI only compilation */ | 290 | /* PCI only compilation */ |
| 289 | #define hme_write32(__hp, __reg, __val) \ | 291 | #define hme_write32(__hp, __reg, __val) \ |
| @@ -305,36 +307,17 @@ static inline u32 hme_read_desc32(struct happy_meal *hp, hme32 *p) | |||
| 305 | return le32_to_cpup((__le32 *)p); | 307 | return le32_to_cpup((__le32 *)p); |
| 306 | } | 308 | } |
| 307 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ | 309 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ |
| 308 | pci_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir)) | 310 | pci_map_single((__hp)->dma_dev, (__ptr), (__size), (__dir)) |
| 309 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ | 311 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ |
| 310 | pci_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir)) | 312 | pci_unmap_single((__hp)->dma_dev, (__addr), (__size), (__dir)) |
| 311 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ | 313 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ |
| 312 | pci_dma_sync_single_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir)) | 314 | pci_dma_sync_single_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir)) |
| 313 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ | 315 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ |
| 314 | pci_dma_sync_single_for_device((__hp)->happy_dev, (__addr), (__size), (__dir)) | 316 | pci_dma_sync_single_for_device((__hp)->dma_dev, (__addr), (__size), (__dir)) |
| 315 | #endif | 317 | #endif |
| 316 | #endif | 318 | #endif |
| 317 | 319 | ||
| 318 | 320 | ||
| 319 | #ifdef SBUS_DMA_BIDIRECTIONAL | ||
| 320 | # define DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL | ||
| 321 | #else | ||
| 322 | # define DMA_BIDIRECTIONAL 0 | ||
| 323 | #endif | ||
| 324 | |||
| 325 | #ifdef SBUS_DMA_FROMDEVICE | ||
| 326 | # define DMA_FROMDEVICE SBUS_DMA_FROMDEVICE | ||
| 327 | #else | ||
| 328 | # define DMA_TODEVICE 1 | ||
| 329 | #endif | ||
| 330 | |||
| 331 | #ifdef SBUS_DMA_TODEVICE | ||
| 332 | # define DMA_TODEVICE SBUS_DMA_TODEVICE | ||
| 333 | #else | ||
| 334 | # define DMA_FROMDEVICE 2 | ||
| 335 | #endif | ||
| 336 | |||
| 337 | |||
| 338 | /* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ | 321 | /* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ |
| 339 | static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit) | 322 | static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit) |
| 340 | { | 323 | { |
| @@ -1224,7 +1207,8 @@ static void happy_meal_clean_rings(struct happy_meal *hp) | |||
| 1224 | 1207 | ||
| 1225 | rxd = &hp->happy_block->happy_meal_rxd[i]; | 1208 | rxd = &hp->happy_block->happy_meal_rxd[i]; |
| 1226 | dma_addr = hme_read_desc32(hp, &rxd->rx_addr); | 1209 | dma_addr = hme_read_desc32(hp, &rxd->rx_addr); |
| 1227 | hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE); | 1210 | dma_unmap_single(hp->dma_dev, dma_addr, |
| 1211 | RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE); | ||
| 1228 | dev_kfree_skb_any(skb); | 1212 | dev_kfree_skb_any(skb); |
| 1229 | hp->rx_skbs[i] = NULL; | 1213 | hp->rx_skbs[i] = NULL; |
| 1230 | } | 1214 | } |
| @@ -1242,10 +1226,10 @@ static void happy_meal_clean_rings(struct happy_meal *hp) | |||
| 1242 | for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) { | 1226 | for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) { |
| 1243 | txd = &hp->happy_block->happy_meal_txd[i]; | 1227 | txd = &hp->happy_block->happy_meal_txd[i]; |
| 1244 | dma_addr = hme_read_desc32(hp, &txd->tx_addr); | 1228 | dma_addr = hme_read_desc32(hp, &txd->tx_addr); |
| 1245 | hme_dma_unmap(hp, dma_addr, | 1229 | dma_unmap_single(hp->dma_dev, dma_addr, |
| 1246 | (hme_read_desc32(hp, &txd->tx_flags) | 1230 | (hme_read_desc32(hp, &txd->tx_flags) |
| 1247 | & TXFLAG_SIZE), | 1231 | & TXFLAG_SIZE), |
| 1248 | DMA_TODEVICE); | 1232 | DMA_TO_DEVICE); |
| 1249 | 1233 | ||
| 1250 | if (frag != skb_shinfo(skb)->nr_frags) | 1234 | if (frag != skb_shinfo(skb)->nr_frags) |
| 1251 | i++; | 1235 | i++; |
| @@ -1287,7 +1271,8 @@ static void happy_meal_init_rings(struct happy_meal *hp) | |||
| 1287 | skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); | 1271 | skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); |
| 1288 | hme_write_rxd(hp, &hb->happy_meal_rxd[i], | 1272 | hme_write_rxd(hp, &hb->happy_meal_rxd[i], |
| 1289 | (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), | 1273 | (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), |
| 1290 | hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); | 1274 | dma_map_single(hp->dma_dev, skb->data, RX_BUF_ALLOC_SIZE, |
| 1275 | DMA_FROM_DEVICE)); | ||
| 1291 | skb_reserve(skb, RX_OFFSET); | 1276 | skb_reserve(skb, RX_OFFSET); |
| 1292 | } | 1277 | } |
| 1293 | 1278 | ||
| @@ -1593,7 +1578,7 @@ static int happy_meal_init(struct happy_meal *hp) | |||
| 1593 | if ((hp->happy_bursts & DMA_BURST64) && | 1578 | if ((hp->happy_bursts & DMA_BURST64) && |
| 1594 | ((hp->happy_flags & HFLAG_PCI) != 0 | 1579 | ((hp->happy_flags & HFLAG_PCI) != 0 |
| 1595 | #ifdef CONFIG_SBUS | 1580 | #ifdef CONFIG_SBUS |
| 1596 | || sbus_can_burst64(hp->happy_dev) | 1581 | || sbus_can_burst64() |
| 1597 | #endif | 1582 | #endif |
| 1598 | || 0)) { | 1583 | || 0)) { |
| 1599 | u32 gcfg = GREG_CFG_BURST64; | 1584 | u32 gcfg = GREG_CFG_BURST64; |
| @@ -1603,11 +1588,13 @@ static int happy_meal_init(struct happy_meal *hp) | |||
| 1603 | * do not. -DaveM | 1588 | * do not. -DaveM |
| 1604 | */ | 1589 | */ |
| 1605 | #ifdef CONFIG_SBUS | 1590 | #ifdef CONFIG_SBUS |
| 1606 | if ((hp->happy_flags & HFLAG_PCI) == 0 && | 1591 | if ((hp->happy_flags & HFLAG_PCI) == 0) { |
| 1607 | sbus_can_dma_64bit(hp->happy_dev)) { | 1592 | struct of_device *op = hp->happy_dev; |
| 1608 | sbus_set_sbus64(hp->happy_dev, | 1593 | if (sbus_can_dma_64bit()) { |
| 1609 | hp->happy_bursts); | 1594 | sbus_set_sbus64(&op->dev, |
| 1610 | gcfg |= GREG_CFG_64BIT; | 1595 | hp->happy_bursts); |
| 1596 | gcfg |= GREG_CFG_64BIT; | ||
| 1597 | } | ||
| 1611 | } | 1598 | } |
| 1612 | #endif | 1599 | #endif |
| 1613 | 1600 | ||
| @@ -1966,7 +1953,7 @@ static void happy_meal_tx(struct happy_meal *hp) | |||
| 1966 | dma_len = hme_read_desc32(hp, &this->tx_flags); | 1953 | dma_len = hme_read_desc32(hp, &this->tx_flags); |
| 1967 | 1954 | ||
| 1968 | dma_len &= TXFLAG_SIZE; | 1955 | dma_len &= TXFLAG_SIZE; |
| 1969 | hme_dma_unmap(hp, dma_addr, dma_len, DMA_TODEVICE); | 1956 | dma_unmap_single(hp->dma_dev, dma_addr, dma_len, DMA_TO_DEVICE); |
| 1970 | 1957 | ||
| 1971 | elem = NEXT_TX(elem); | 1958 | elem = NEXT_TX(elem); |
| 1972 | this = &txbase[elem]; | 1959 | this = &txbase[elem]; |
| @@ -2044,13 +2031,14 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) | |||
| 2044 | drops++; | 2031 | drops++; |
| 2045 | goto drop_it; | 2032 | goto drop_it; |
| 2046 | } | 2033 | } |
| 2047 | hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE); | 2034 | dma_unmap_single(hp->dma_dev, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE); |
| 2048 | hp->rx_skbs[elem] = new_skb; | 2035 | hp->rx_skbs[elem] = new_skb; |
| 2049 | new_skb->dev = dev; | 2036 | new_skb->dev = dev; |
| 2050 | skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); | 2037 | skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); |
| 2051 | hme_write_rxd(hp, this, | 2038 | hme_write_rxd(hp, this, |
| 2052 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), | 2039 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), |
| 2053 | hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); | 2040 | dma_map_single(hp->dma_dev, new_skb->data, RX_BUF_ALLOC_SIZE, |
| 2041 | DMA_FROM_DEVICE)); | ||
| 2054 | skb_reserve(new_skb, RX_OFFSET); | 2042 | skb_reserve(new_skb, RX_OFFSET); |
| 2055 | 2043 | ||
| 2056 | /* Trim the original skb for the netif. */ | 2044 | /* Trim the original skb for the netif. */ |
| @@ -2065,10 +2053,9 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) | |||
| 2065 | 2053 | ||
| 2066 | skb_reserve(copy_skb, 2); | 2054 | skb_reserve(copy_skb, 2); |
| 2067 | skb_put(copy_skb, len); | 2055 | skb_put(copy_skb, len); |
| 2068 | hme_dma_sync_for_cpu(hp, dma_addr, len, DMA_FROMDEVICE); | 2056 | dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE); |
| 2069 | skb_copy_from_linear_data(skb, copy_skb->data, len); | 2057 | skb_copy_from_linear_data(skb, copy_skb->data, len); |
| 2070 | hme_dma_sync_for_device(hp, dma_addr, len, DMA_FROMDEVICE); | 2058 | dma_sync_single_for_device(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE); |
| 2071 | |||
| 2072 | /* Reuse original ring buffer. */ | 2059 | /* Reuse original ring buffer. */ |
| 2073 | hme_write_rxd(hp, this, | 2060 | hme_write_rxd(hp, this, |
| 2074 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), | 2061 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), |
| @@ -2300,7 +2287,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 2300 | u32 mapping, len; | 2287 | u32 mapping, len; |
| 2301 | 2288 | ||
| 2302 | len = skb->len; | 2289 | len = skb->len; |
| 2303 | mapping = hme_dma_map(hp, skb->data, len, DMA_TODEVICE); | 2290 | mapping = dma_map_single(hp->dma_dev, skb->data, len, DMA_TO_DEVICE); |
| 2304 | tx_flags |= (TXFLAG_SOP | TXFLAG_EOP); | 2291 | tx_flags |= (TXFLAG_SOP | TXFLAG_EOP); |
| 2305 | hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry], | 2292 | hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry], |
| 2306 | (tx_flags | (len & TXFLAG_SIZE)), | 2293 | (tx_flags | (len & TXFLAG_SIZE)), |
| @@ -2314,7 +2301,8 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 2314 | * Otherwise we could race with the device. | 2301 | * Otherwise we could race with the device. |
| 2315 | */ | 2302 | */ |
| 2316 | first_len = skb_headlen(skb); | 2303 | first_len = skb_headlen(skb); |
| 2317 | first_mapping = hme_dma_map(hp, skb->data, first_len, DMA_TODEVICE); | 2304 | first_mapping = dma_map_single(hp->dma_dev, skb->data, first_len, |
| 2305 | DMA_TO_DEVICE); | ||
| 2318 | entry = NEXT_TX(entry); | 2306 | entry = NEXT_TX(entry); |
| 2319 | 2307 | ||
| 2320 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { | 2308 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { |
| @@ -2322,10 +2310,9 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 2322 | u32 len, mapping, this_txflags; | 2310 | u32 len, mapping, this_txflags; |
| 2323 | 2311 | ||
| 2324 | len = this_frag->size; | 2312 | len = this_frag->size; |
| 2325 | mapping = hme_dma_map(hp, | 2313 | mapping = dma_map_page(hp->dma_dev, this_frag->page, |
| 2326 | ((void *) page_address(this_frag->page) + | 2314 | this_frag->page_offset, len, |
| 2327 | this_frag->page_offset), | 2315 | DMA_TO_DEVICE); |
| 2328 | len, DMA_TODEVICE); | ||
| 2329 | this_txflags = tx_flags; | 2316 | this_txflags = tx_flags; |
| 2330 | if (frag == skb_shinfo(skb)->nr_frags - 1) | 2317 | if (frag == skb_shinfo(skb)->nr_frags - 1) |
| 2331 | this_txflags |= TXFLAG_EOP; | 2318 | this_txflags |= TXFLAG_EOP; |
| @@ -2493,9 +2480,12 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info | |||
| 2493 | } | 2480 | } |
| 2494 | #ifdef CONFIG_SBUS | 2481 | #ifdef CONFIG_SBUS |
| 2495 | else { | 2482 | else { |
| 2496 | struct sbus_dev *sdev = hp->happy_dev; | 2483 | const struct linux_prom_registers *regs; |
| 2497 | sprintf(info->bus_info, "SBUS:%d", | 2484 | struct of_device *op = hp->happy_dev; |
| 2498 | sdev->slot); | 2485 | regs = of_get_property(op->node, "regs", NULL); |
| 2486 | if (regs) | ||
| 2487 | sprintf(info->bus_info, "SBUS:%d", | ||
| 2488 | regs->which_io); | ||
| 2499 | } | 2489 | } |
| 2500 | #endif | 2490 | #endif |
| 2501 | } | 2491 | } |
| @@ -2521,63 +2511,21 @@ static const struct ethtool_ops hme_ethtool_ops = { | |||
| 2521 | static int hme_version_printed; | 2511 | static int hme_version_printed; |
| 2522 | 2512 | ||
| 2523 | #ifdef CONFIG_SBUS | 2513 | #ifdef CONFIG_SBUS |
| 2524 | void __devinit quattro_get_ranges(struct quattro *qp) | ||
| 2525 | { | ||
| 2526 | struct sbus_dev *sdev = qp->quattro_dev; | ||
| 2527 | int err; | ||
| 2528 | |||
| 2529 | err = prom_getproperty(sdev->prom_node, | ||
| 2530 | "ranges", | ||
| 2531 | (char *)&qp->ranges[0], | ||
| 2532 | sizeof(qp->ranges)); | ||
| 2533 | if (err == 0 || err == -1) { | ||
| 2534 | qp->nranges = 0; | ||
| 2535 | return; | ||
| 2536 | } | ||
| 2537 | qp->nranges = (err / sizeof(struct linux_prom_ranges)); | ||
| 2538 | } | ||
| 2539 | |||
| 2540 | static void __devinit quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp) | ||
| 2541 | { | ||
| 2542 | struct sbus_dev *sdev = hp->happy_dev; | ||
| 2543 | int rng; | ||
| 2544 | |||
| 2545 | for (rng = 0; rng < qp->nranges; rng++) { | ||
| 2546 | struct linux_prom_ranges *rngp = &qp->ranges[rng]; | ||
| 2547 | int reg; | ||
| 2548 | |||
| 2549 | for (reg = 0; reg < 5; reg++) { | ||
| 2550 | if (sdev->reg_addrs[reg].which_io == | ||
| 2551 | rngp->ot_child_space) | ||
| 2552 | break; | ||
| 2553 | } | ||
| 2554 | if (reg == 5) | ||
| 2555 | continue; | ||
| 2556 | |||
| 2557 | sdev->reg_addrs[reg].which_io = rngp->ot_parent_space; | ||
| 2558 | sdev->reg_addrs[reg].phys_addr += rngp->ot_parent_base; | ||
| 2559 | } | ||
| 2560 | } | ||
| 2561 | |||
| 2562 | /* Given a happy meal sbus device, find it's quattro parent. | 2514 | /* Given a happy meal sbus device, find it's quattro parent. |
| 2563 | * If none exist, allocate and return a new one. | 2515 | * If none exist, allocate and return a new one. |
| 2564 | * | 2516 | * |
| 2565 | * Return NULL on failure. | 2517 | * Return NULL on failure. |
| 2566 | */ | 2518 | */ |
| 2567 | static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev) | 2519 | static struct quattro * __devinit quattro_sbus_find(struct of_device *child) |
| 2568 | { | 2520 | { |
| 2569 | struct sbus_dev *sdev; | 2521 | struct device *parent = child->dev.parent; |
| 2522 | struct of_device *op; | ||
| 2570 | struct quattro *qp; | 2523 | struct quattro *qp; |
| 2571 | int i; | ||
| 2572 | 2524 | ||
| 2573 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2525 | op = to_of_device(parent); |
| 2574 | for (i = 0, sdev = qp->quattro_dev; | 2526 | qp = dev_get_drvdata(&op->dev); |
| 2575 | (sdev != NULL) && (i < 4); | 2527 | if (qp) |
| 2576 | sdev = sdev->next, i++) { | 2528 | return qp; |
| 2577 | if (sdev == goal_sdev) | ||
| 2578 | return qp; | ||
| 2579 | } | ||
| 2580 | } | ||
| 2581 | 2529 | ||
| 2582 | qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); | 2530 | qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); |
| 2583 | if (qp != NULL) { | 2531 | if (qp != NULL) { |
| @@ -2586,10 +2534,11 @@ static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev) | |||
| 2586 | for (i = 0; i < 4; i++) | 2534 | for (i = 0; i < 4; i++) |
| 2587 | qp->happy_meals[i] = NULL; | 2535 | qp->happy_meals[i] = NULL; |
| 2588 | 2536 | ||
| 2589 | qp->quattro_dev = goal_sdev; | 2537 | qp->quattro_dev = child; |
| 2590 | qp->next = qfe_sbus_list; | 2538 | qp->next = qfe_sbus_list; |
| 2591 | qfe_sbus_list = qp; | 2539 | qfe_sbus_list = qp; |
| 2592 | quattro_get_ranges(qp); | 2540 | |
| 2541 | dev_set_drvdata(&op->dev, qp); | ||
| 2593 | } | 2542 | } |
| 2594 | return qp; | 2543 | return qp; |
| 2595 | } | 2544 | } |
| @@ -2602,10 +2551,10 @@ static void __init quattro_sbus_register_irqs(void) | |||
| 2602 | struct quattro *qp; | 2551 | struct quattro *qp; |
| 2603 | 2552 | ||
| 2604 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2553 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
| 2605 | struct sbus_dev *sdev = qp->quattro_dev; | 2554 | struct of_device *op = qp->quattro_dev; |
| 2606 | int err; | 2555 | int err; |
| 2607 | 2556 | ||
| 2608 | err = request_irq(sdev->irqs[0], | 2557 | err = request_irq(op->irqs[0], |
| 2609 | quattro_sbus_interrupt, | 2558 | quattro_sbus_interrupt, |
| 2610 | IRQF_SHARED, "Quattro", | 2559 | IRQF_SHARED, "Quattro", |
| 2611 | qp); | 2560 | qp); |
| @@ -2621,9 +2570,9 @@ static void quattro_sbus_free_irqs(void) | |||
| 2621 | struct quattro *qp; | 2570 | struct quattro *qp; |
| 2622 | 2571 | ||
| 2623 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2572 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
| 2624 | struct sbus_dev *sdev = qp->quattro_dev; | 2573 | struct of_device *op = qp->quattro_dev; |
| 2625 | 2574 | ||
| 2626 | free_irq(sdev->irqs[0], qp); | 2575 | free_irq(op->irqs[0], qp); |
| 2627 | } | 2576 | } |
| 2628 | } | 2577 | } |
| 2629 | #endif /* CONFIG_SBUS */ | 2578 | #endif /* CONFIG_SBUS */ |
| @@ -2660,9 +2609,9 @@ static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev) | |||
| 2660 | #endif /* CONFIG_PCI */ | 2609 | #endif /* CONFIG_PCI */ |
| 2661 | 2610 | ||
| 2662 | #ifdef CONFIG_SBUS | 2611 | #ifdef CONFIG_SBUS |
| 2663 | static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) | 2612 | static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) |
| 2664 | { | 2613 | { |
| 2665 | struct device_node *dp = sdev->ofdev.node; | 2614 | struct device_node *dp = op->node, *sbus_dp; |
| 2666 | struct quattro *qp = NULL; | 2615 | struct quattro *qp = NULL; |
| 2667 | struct happy_meal *hp; | 2616 | struct happy_meal *hp; |
| 2668 | struct net_device *dev; | 2617 | struct net_device *dev; |
| @@ -2671,7 +2620,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2671 | DECLARE_MAC_BUF(mac); | 2620 | DECLARE_MAC_BUF(mac); |
| 2672 | 2621 | ||
| 2673 | if (is_qfe) { | 2622 | if (is_qfe) { |
| 2674 | qp = quattro_sbus_find(sdev); | 2623 | qp = quattro_sbus_find(op); |
| 2675 | if (qp == NULL) | 2624 | if (qp == NULL) |
| 2676 | goto err_out; | 2625 | goto err_out; |
| 2677 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) | 2626 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) |
| @@ -2685,7 +2634,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2685 | dev = alloc_etherdev(sizeof(struct happy_meal)); | 2634 | dev = alloc_etherdev(sizeof(struct happy_meal)); |
| 2686 | if (!dev) | 2635 | if (!dev) |
| 2687 | goto err_out; | 2636 | goto err_out; |
| 2688 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 2637 | SET_NETDEV_DEV(dev, &op->dev); |
| 2689 | 2638 | ||
| 2690 | if (hme_version_printed++ == 0) | 2639 | if (hme_version_printed++ == 0) |
| 2691 | printk(KERN_INFO "%s", version); | 2640 | printk(KERN_INFO "%s", version); |
| @@ -2713,56 +2662,50 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2713 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | 2662 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); |
| 2714 | } | 2663 | } |
| 2715 | 2664 | ||
| 2716 | hp = dev->priv; | 2665 | hp = netdev_priv(dev); |
| 2717 | 2666 | ||
| 2718 | hp->happy_dev = sdev; | 2667 | hp->happy_dev = op; |
| 2668 | hp->dma_dev = &op->dev; | ||
| 2719 | 2669 | ||
| 2720 | spin_lock_init(&hp->happy_lock); | 2670 | spin_lock_init(&hp->happy_lock); |
| 2721 | 2671 | ||
| 2722 | err = -ENODEV; | 2672 | err = -ENODEV; |
| 2723 | if (sdev->num_registers != 5) { | ||
| 2724 | printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", | ||
| 2725 | sdev->num_registers); | ||
| 2726 | goto err_out_free_netdev; | ||
| 2727 | } | ||
| 2728 | |||
| 2729 | if (qp != NULL) { | 2673 | if (qp != NULL) { |
| 2730 | hp->qfe_parent = qp; | 2674 | hp->qfe_parent = qp; |
| 2731 | hp->qfe_ent = qfe_slot; | 2675 | hp->qfe_ent = qfe_slot; |
| 2732 | qp->happy_meals[qfe_slot] = dev; | 2676 | qp->happy_meals[qfe_slot] = dev; |
| 2733 | quattro_apply_ranges(qp, hp); | ||
| 2734 | } | 2677 | } |
| 2735 | 2678 | ||
| 2736 | hp->gregs = sbus_ioremap(&sdev->resource[0], 0, | 2679 | hp->gregs = of_ioremap(&op->resource[0], 0, |
| 2737 | GREG_REG_SIZE, "HME Global Regs"); | 2680 | GREG_REG_SIZE, "HME Global Regs"); |
| 2738 | if (!hp->gregs) { | 2681 | if (!hp->gregs) { |
| 2739 | printk(KERN_ERR "happymeal: Cannot map global registers.\n"); | 2682 | printk(KERN_ERR "happymeal: Cannot map global registers.\n"); |
| 2740 | goto err_out_free_netdev; | 2683 | goto err_out_free_netdev; |
| 2741 | } | 2684 | } |
| 2742 | 2685 | ||
| 2743 | hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, | 2686 | hp->etxregs = of_ioremap(&op->resource[1], 0, |
| 2744 | ETX_REG_SIZE, "HME TX Regs"); | 2687 | ETX_REG_SIZE, "HME TX Regs"); |
| 2745 | if (!hp->etxregs) { | 2688 | if (!hp->etxregs) { |
| 2746 | printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); | 2689 | printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); |
| 2747 | goto err_out_iounmap; | 2690 | goto err_out_iounmap; |
| 2748 | } | 2691 | } |
| 2749 | 2692 | ||
| 2750 | hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, | 2693 | hp->erxregs = of_ioremap(&op->resource[2], 0, |
| 2751 | ERX_REG_SIZE, "HME RX Regs"); | 2694 | ERX_REG_SIZE, "HME RX Regs"); |
| 2752 | if (!hp->erxregs) { | 2695 | if (!hp->erxregs) { |
| 2753 | printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); | 2696 | printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); |
| 2754 | goto err_out_iounmap; | 2697 | goto err_out_iounmap; |
| 2755 | } | 2698 | } |
| 2756 | 2699 | ||
| 2757 | hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, | 2700 | hp->bigmacregs = of_ioremap(&op->resource[3], 0, |
| 2758 | BMAC_REG_SIZE, "HME BIGMAC Regs"); | 2701 | BMAC_REG_SIZE, "HME BIGMAC Regs"); |
| 2759 | if (!hp->bigmacregs) { | 2702 | if (!hp->bigmacregs) { |
| 2760 | printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); | 2703 | printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); |
| 2761 | goto err_out_iounmap; | 2704 | goto err_out_iounmap; |
| 2762 | } | 2705 | } |
| 2763 | 2706 | ||
| 2764 | hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, | 2707 | hp->tcvregs = of_ioremap(&op->resource[4], 0, |
| 2765 | TCVR_REG_SIZE, "HME Tranceiver Regs"); | 2708 | TCVR_REG_SIZE, "HME Tranceiver Regs"); |
| 2766 | if (!hp->tcvregs) { | 2709 | if (!hp->tcvregs) { |
| 2767 | printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); | 2710 | printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); |
| 2768 | goto err_out_iounmap; | 2711 | goto err_out_iounmap; |
| @@ -2781,13 +2724,18 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2781 | if (qp != NULL) | 2724 | if (qp != NULL) |
| 2782 | hp->happy_flags |= HFLAG_QUATTRO; | 2725 | hp->happy_flags |= HFLAG_QUATTRO; |
| 2783 | 2726 | ||
| 2727 | sbus_dp = to_of_device(op->dev.parent)->node; | ||
| 2728 | if (is_qfe) | ||
| 2729 | sbus_dp = to_of_device(op->dev.parent->parent)->node; | ||
| 2730 | |||
| 2784 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ | 2731 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ |
| 2785 | hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, | 2732 | hp->happy_bursts = of_getintprop_default(sbus_dp, |
| 2786 | "burst-sizes", 0x00); | 2733 | "burst-sizes", 0x00); |
| 2787 | 2734 | ||
| 2788 | hp->happy_block = sbus_alloc_consistent(hp->happy_dev, | 2735 | hp->happy_block = dma_alloc_coherent(hp->dma_dev, |
| 2789 | PAGE_SIZE, | 2736 | PAGE_SIZE, |
| 2790 | &hp->hblock_dvma); | 2737 | &hp->hblock_dvma, |
| 2738 | GFP_ATOMIC); | ||
| 2791 | err = -ENOMEM; | 2739 | err = -ENOMEM; |
| 2792 | if (!hp->happy_block) { | 2740 | if (!hp->happy_block) { |
| 2793 | printk(KERN_ERR "happymeal: Cannot allocate descriptors.\n"); | 2741 | printk(KERN_ERR "happymeal: Cannot allocate descriptors.\n"); |
| @@ -2816,19 +2764,13 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2816 | /* Happy Meal can do it all... */ | 2764 | /* Happy Meal can do it all... */ |
| 2817 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | 2765 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; |
| 2818 | 2766 | ||
| 2819 | dev->irq = sdev->irqs[0]; | 2767 | dev->irq = op->irqs[0]; |
| 2820 | 2768 | ||
| 2821 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) | 2769 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) |
| 2822 | /* Hook up PCI register/dma accessors. */ | 2770 | /* Hook up SBUS register/descriptor accessors. */ |
| 2823 | hp->read_desc32 = sbus_hme_read_desc32; | 2771 | hp->read_desc32 = sbus_hme_read_desc32; |
| 2824 | hp->write_txd = sbus_hme_write_txd; | 2772 | hp->write_txd = sbus_hme_write_txd; |
| 2825 | hp->write_rxd = sbus_hme_write_rxd; | 2773 | hp->write_rxd = sbus_hme_write_rxd; |
| 2826 | hp->dma_map = (u32 (*)(void *, void *, long, int))sbus_map_single; | ||
| 2827 | hp->dma_unmap = (void (*)(void *, u32, long, int))sbus_unmap_single; | ||
| 2828 | hp->dma_sync_for_cpu = (void (*)(void *, u32, long, int)) | ||
| 2829 | sbus_dma_sync_single_for_cpu; | ||
| 2830 | hp->dma_sync_for_device = (void (*)(void *, u32, long, int)) | ||
| 2831 | sbus_dma_sync_single_for_device; | ||
| 2832 | hp->read32 = sbus_hme_read32; | 2774 | hp->read32 = sbus_hme_read32; |
| 2833 | hp->write32 = sbus_hme_write32; | 2775 | hp->write32 = sbus_hme_write32; |
| 2834 | #endif | 2776 | #endif |
| @@ -2843,10 +2785,10 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2843 | if (register_netdev(hp->dev)) { | 2785 | if (register_netdev(hp->dev)) { |
| 2844 | printk(KERN_ERR "happymeal: Cannot register net device, " | 2786 | printk(KERN_ERR "happymeal: Cannot register net device, " |
| 2845 | "aborting.\n"); | 2787 | "aborting.\n"); |
| 2846 | goto err_out_free_consistent; | 2788 | goto err_out_free_coherent; |
| 2847 | } | 2789 | } |
| 2848 | 2790 | ||
| 2849 | dev_set_drvdata(&sdev->ofdev.dev, hp); | 2791 | dev_set_drvdata(&op->dev, hp); |
| 2850 | 2792 | ||
| 2851 | if (qfe_slot != -1) | 2793 | if (qfe_slot != -1) |
| 2852 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", | 2794 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", |
| @@ -2859,23 +2801,23 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
| 2859 | 2801 | ||
| 2860 | return 0; | 2802 | return 0; |
| 2861 | 2803 | ||
| 2862 | err_out_free_consistent: | 2804 | err_out_free_coherent: |
| 2863 | sbus_free_consistent(hp->happy_dev, | 2805 | dma_free_coherent(hp->dma_dev, |
| 2864 | PAGE_SIZE, | 2806 | PAGE_SIZE, |
| 2865 | hp->happy_block, | 2807 | hp->happy_block, |
| 2866 | hp->hblock_dvma); | 2808 | hp->hblock_dvma); |
| 2867 | 2809 | ||
| 2868 | err_out_iounmap: | 2810 | err_out_iounmap: |
| 2869 | if (hp->gregs) | 2811 | if (hp->gregs) |
| 2870 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | 2812 | of_iounmap(&op->resource[0], hp->gregs, GREG_REG_SIZE); |
| 2871 | if (hp->etxregs) | 2813 | if (hp->etxregs) |
| 2872 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | 2814 | of_iounmap(&op->resource[1], hp->etxregs, ETX_REG_SIZE); |
| 2873 | if (hp->erxregs) | 2815 | if (hp->erxregs) |
| 2874 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | 2816 | of_iounmap(&op->resource[2], hp->erxregs, ERX_REG_SIZE); |
| 2875 | if (hp->bigmacregs) | 2817 | if (hp->bigmacregs) |
| 2876 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | 2818 | of_iounmap(&op->resource[3], hp->bigmacregs, BMAC_REG_SIZE); |
| 2877 | if (hp->tcvregs) | 2819 | if (hp->tcvregs) |
| 2878 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | 2820 | of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE); |
| 2879 | 2821 | ||
| 2880 | err_out_free_netdev: | 2822 | err_out_free_netdev: |
| 2881 | free_netdev(dev); | 2823 | free_netdev(dev); |
| @@ -3035,6 +2977,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
| 3035 | memset(hp, 0, sizeof(*hp)); | 2977 | memset(hp, 0, sizeof(*hp)); |
| 3036 | 2978 | ||
| 3037 | hp->happy_dev = pdev; | 2979 | hp->happy_dev = pdev; |
| 2980 | hp->dma_dev = &pdev->dev; | ||
| 3038 | 2981 | ||
| 3039 | spin_lock_init(&hp->happy_lock); | 2982 | spin_lock_init(&hp->happy_lock); |
| 3040 | 2983 | ||
| @@ -3121,7 +3064,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
| 3121 | #endif | 3064 | #endif |
| 3122 | 3065 | ||
| 3123 | hp->happy_block = (struct hmeal_init_block *) | 3066 | hp->happy_block = (struct hmeal_init_block *) |
| 3124 | pci_alloc_consistent(pdev, PAGE_SIZE, &hp->hblock_dvma); | 3067 | dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &hp->hblock_dvma, GFP_KERNEL); |
| 3125 | 3068 | ||
| 3126 | err = -ENODEV; | 3069 | err = -ENODEV; |
| 3127 | if (!hp->happy_block) { | 3070 | if (!hp->happy_block) { |
| @@ -3151,16 +3094,10 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
| 3151 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | 3094 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; |
| 3152 | 3095 | ||
| 3153 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) | 3096 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) |
| 3154 | /* Hook up PCI register/dma accessors. */ | 3097 | /* Hook up PCI register/descriptor accessors. */ |
| 3155 | hp->read_desc32 = pci_hme_read_desc32; | 3098 | hp->read_desc32 = pci_hme_read_desc32; |
| 3156 | hp->write_txd = pci_hme_write_txd; | 3099 | hp->write_txd = pci_hme_write_txd; |
| 3157 | hp->write_rxd = pci_hme_write_rxd; | 3100 | hp->write_rxd = pci_hme_write_rxd; |
| 3158 | hp->dma_map = (u32 (*)(void *, void *, long, int))pci_map_single; | ||
| 3159 | hp->dma_unmap = (void (*)(void *, u32, long, int))pci_unmap_single; | ||
| 3160 | hp->dma_sync_for_cpu = (void (*)(void *, u32, long, int)) | ||
| 3161 | pci_dma_sync_single_for_cpu; | ||
| 3162 | hp->dma_sync_for_device = (void (*)(void *, u32, long, int)) | ||
| 3163 | pci_dma_sync_single_for_device; | ||
| 3164 | hp->read32 = pci_hme_read32; | 3101 | hp->read32 = pci_hme_read32; |
| 3165 | hp->write32 = pci_hme_write32; | 3102 | hp->write32 = pci_hme_write32; |
| 3166 | #endif | 3103 | #endif |
| @@ -3231,10 +3168,8 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) | |||
| 3231 | 3168 | ||
| 3232 | unregister_netdev(net_dev); | 3169 | unregister_netdev(net_dev); |
| 3233 | 3170 | ||
| 3234 | pci_free_consistent(hp->happy_dev, | 3171 | dma_free_coherent(hp->dma_dev, PAGE_SIZE, |
| 3235 | PAGE_SIZE, | 3172 | hp->happy_block, hp->hblock_dvma); |
| 3236 | hp->happy_block, | ||
| 3237 | hp->hblock_dvma); | ||
| 3238 | iounmap(hp->gregs); | 3173 | iounmap(hp->gregs); |
| 3239 | pci_release_regions(hp->happy_dev); | 3174 | pci_release_regions(hp->happy_dev); |
| 3240 | 3175 | ||
| @@ -3279,46 +3214,45 @@ static void happy_meal_pci_exit(void) | |||
| 3279 | #endif | 3214 | #endif |
| 3280 | 3215 | ||
| 3281 | #ifdef CONFIG_SBUS | 3216 | #ifdef CONFIG_SBUS |
| 3282 | static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 3217 | static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match) |
| 3283 | { | 3218 | { |
| 3284 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 3219 | struct device_node *dp = op->node; |
| 3285 | struct device_node *dp = dev->node; | ||
| 3286 | const char *model = of_get_property(dp, "model", NULL); | 3220 | const char *model = of_get_property(dp, "model", NULL); |
| 3287 | int is_qfe = (match->data != NULL); | 3221 | int is_qfe = (match->data != NULL); |
| 3288 | 3222 | ||
| 3289 | if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) | 3223 | if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) |
| 3290 | is_qfe = 1; | 3224 | is_qfe = 1; |
| 3291 | 3225 | ||
| 3292 | return happy_meal_sbus_probe_one(sdev, is_qfe); | 3226 | return happy_meal_sbus_probe_one(op, is_qfe); |
| 3293 | } | 3227 | } |
| 3294 | 3228 | ||
| 3295 | static int __devexit hme_sbus_remove(struct of_device *dev) | 3229 | static int __devexit hme_sbus_remove(struct of_device *op) |
| 3296 | { | 3230 | { |
| 3297 | struct happy_meal *hp = dev_get_drvdata(&dev->dev); | 3231 | struct happy_meal *hp = dev_get_drvdata(&op->dev); |
| 3298 | struct net_device *net_dev = hp->dev; | 3232 | struct net_device *net_dev = hp->dev; |
| 3299 | 3233 | ||
| 3300 | unregister_netdev(net_dev); | 3234 | unregister_netdev(net_dev); |
| 3301 | 3235 | ||
| 3302 | /* XXX qfe parent interrupt... */ | 3236 | /* XXX qfe parent interrupt... */ |
| 3303 | 3237 | ||
| 3304 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | 3238 | of_iounmap(&op->resource[0], hp->gregs, GREG_REG_SIZE); |
| 3305 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | 3239 | of_iounmap(&op->resource[1], hp->etxregs, ETX_REG_SIZE); |
| 3306 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | 3240 | of_iounmap(&op->resource[2], hp->erxregs, ERX_REG_SIZE); |
| 3307 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | 3241 | of_iounmap(&op->resource[3], hp->bigmacregs, BMAC_REG_SIZE); |
| 3308 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | 3242 | of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE); |
| 3309 | sbus_free_consistent(hp->happy_dev, | 3243 | dma_free_coherent(hp->dma_dev, |
| 3310 | PAGE_SIZE, | 3244 | PAGE_SIZE, |
| 3311 | hp->happy_block, | 3245 | hp->happy_block, |
| 3312 | hp->hblock_dvma); | 3246 | hp->hblock_dvma); |
| 3313 | 3247 | ||
| 3314 | free_netdev(net_dev); | 3248 | free_netdev(net_dev); |
| 3315 | 3249 | ||
| 3316 | dev_set_drvdata(&dev->dev, NULL); | 3250 | dev_set_drvdata(&op->dev, NULL); |
| 3317 | 3251 | ||
| 3318 | return 0; | 3252 | return 0; |
| 3319 | } | 3253 | } |
| 3320 | 3254 | ||
| 3321 | static struct of_device_id hme_sbus_match[] = { | 3255 | static const struct of_device_id hme_sbus_match[] = { |
| 3322 | { | 3256 | { |
| 3323 | .name = "SUNW,hme", | 3257 | .name = "SUNW,hme", |
| 3324 | }, | 3258 | }, |
| @@ -3346,7 +3280,7 @@ static int __init happy_meal_sbus_init(void) | |||
| 3346 | { | 3280 | { |
| 3347 | int err; | 3281 | int err; |
| 3348 | 3282 | ||
| 3349 | err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); | 3283 | err = of_register_driver(&hme_sbus_driver, &of_bus_type); |
| 3350 | if (!err) | 3284 | if (!err) |
| 3351 | quattro_sbus_register_irqs(); | 3285 | quattro_sbus_register_irqs(); |
| 3352 | 3286 | ||
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index 4da5539fac7b..efd2ca0fcad3 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h | |||
| @@ -405,14 +405,11 @@ struct happy_meal { | |||
| 405 | u32 (*read_desc32)(hme32 *); | 405 | u32 (*read_desc32)(hme32 *); |
| 406 | void (*write_txd)(struct happy_meal_txd *, u32, u32); | 406 | void (*write_txd)(struct happy_meal_txd *, u32, u32); |
| 407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); | 407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); |
| 408 | u32 (*dma_map)(void *, void *, long, int); | ||
| 409 | void (*dma_unmap)(void *, u32, long, int); | ||
| 410 | void (*dma_sync_for_cpu)(void *, u32, long, int); | ||
| 411 | void (*dma_sync_for_device)(void *, u32, long, int); | ||
| 412 | #endif | 408 | #endif |
| 413 | 409 | ||
| 414 | /* This is either a sbus_dev or a pci_dev. */ | 410 | /* This is either an of_device or a pci_dev. */ |
| 415 | void *happy_dev; | 411 | void *happy_dev; |
| 412 | struct device *dma_dev; | ||
| 416 | 413 | ||
| 417 | spinlock_t happy_lock; | 414 | spinlock_t happy_lock; |
| 418 | 415 | ||
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 4e994f87469e..704301a5a7ff 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c | |||
| @@ -91,6 +91,9 @@ static char lancestr[] = "LANCE"; | |||
| 91 | #include <linux/skbuff.h> | 91 | #include <linux/skbuff.h> |
| 92 | #include <linux/ethtool.h> | 92 | #include <linux/ethtool.h> |
| 93 | #include <linux/bitops.h> | 93 | #include <linux/bitops.h> |
| 94 | #include <linux/dma-mapping.h> | ||
| 95 | #include <linux/of.h> | ||
| 96 | #include <linux/of_device.h> | ||
| 94 | 97 | ||
| 95 | #include <asm/system.h> | 98 | #include <asm/system.h> |
| 96 | #include <asm/io.h> | 99 | #include <asm/io.h> |
| @@ -98,7 +101,6 @@ static char lancestr[] = "LANCE"; | |||
| 98 | #include <asm/pgtable.h> | 101 | #include <asm/pgtable.h> |
| 99 | #include <asm/byteorder.h> /* Used by the checksum routines */ | 102 | #include <asm/byteorder.h> /* Used by the checksum routines */ |
| 100 | #include <asm/idprom.h> | 103 | #include <asm/idprom.h> |
| 101 | #include <asm/sbus.h> | ||
| 102 | #include <asm/prom.h> | 104 | #include <asm/prom.h> |
| 103 | #include <asm/auxio.h> /* For tpe-link-test? setting */ | 105 | #include <asm/auxio.h> /* For tpe-link-test? setting */ |
| 104 | #include <asm/irq.h> | 106 | #include <asm/irq.h> |
| @@ -248,7 +250,7 @@ struct lance_private { | |||
| 248 | int rx_new, tx_new; | 250 | int rx_new, tx_new; |
| 249 | int rx_old, tx_old; | 251 | int rx_old, tx_old; |
| 250 | 252 | ||
| 251 | struct sbus_dma *ledma; /* If set this points to ledma */ | 253 | struct of_device *ledma; /* If set this points to ledma */ |
| 252 | char tpe; /* cable-selection is TPE */ | 254 | char tpe; /* cable-selection is TPE */ |
| 253 | char auto_select; /* cable-selection by carrier */ | 255 | char auto_select; /* cable-selection by carrier */ |
| 254 | char burst_sizes; /* ledma SBus burst sizes */ | 256 | char burst_sizes; /* ledma SBus burst sizes */ |
| @@ -263,7 +265,8 @@ struct lance_private { | |||
| 263 | char *name; | 265 | char *name; |
| 264 | dma_addr_t init_block_dvma; | 266 | dma_addr_t init_block_dvma; |
| 265 | struct net_device *dev; /* Backpointer */ | 267 | struct net_device *dev; /* Backpointer */ |
| 266 | struct sbus_dev *sdev; | 268 | struct of_device *op; |
| 269 | struct of_device *lebuffer; | ||
| 267 | struct timer_list multicast_timer; | 270 | struct timer_list multicast_timer; |
| 268 | }; | 271 | }; |
| 269 | 272 | ||
| @@ -1272,27 +1275,29 @@ static void lance_set_multicast_retry(unsigned long _opaque) | |||
| 1272 | static void lance_free_hwresources(struct lance_private *lp) | 1275 | static void lance_free_hwresources(struct lance_private *lp) |
| 1273 | { | 1276 | { |
| 1274 | if (lp->lregs) | 1277 | if (lp->lregs) |
| 1275 | sbus_iounmap(lp->lregs, LANCE_REG_SIZE); | 1278 | of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); |
| 1279 | if (lp->dregs) { | ||
| 1280 | struct of_device *ledma = lp->ledma; | ||
| 1281 | |||
| 1282 | of_iounmap(&ledma->resource[0], lp->dregs, | ||
| 1283 | resource_size(&ledma->resource[0])); | ||
| 1284 | } | ||
| 1276 | if (lp->init_block_iomem) { | 1285 | if (lp->init_block_iomem) { |
| 1277 | sbus_iounmap(lp->init_block_iomem, | 1286 | of_iounmap(&lp->lebuffer->resource[0], lp->init_block_iomem, |
| 1278 | sizeof(struct lance_init_block)); | 1287 | sizeof(struct lance_init_block)); |
| 1279 | } else if (lp->init_block_mem) { | 1288 | } else if (lp->init_block_mem) { |
| 1280 | sbus_free_consistent(lp->sdev, | 1289 | dma_free_coherent(&lp->op->dev, |
| 1281 | sizeof(struct lance_init_block), | 1290 | sizeof(struct lance_init_block), |
| 1282 | lp->init_block_mem, | 1291 | lp->init_block_mem, |
| 1283 | lp->init_block_dvma); | 1292 | lp->init_block_dvma); |
| 1284 | } | 1293 | } |
| 1285 | } | 1294 | } |
| 1286 | 1295 | ||
| 1287 | /* Ethtool support... */ | 1296 | /* Ethtool support... */ |
| 1288 | static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 1297 | static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
| 1289 | { | 1298 | { |
| 1290 | struct lance_private *lp = netdev_priv(dev); | ||
| 1291 | |||
| 1292 | strcpy(info->driver, "sunlance"); | 1299 | strcpy(info->driver, "sunlance"); |
| 1293 | strcpy(info->version, "2.02"); | 1300 | strcpy(info->version, "2.02"); |
| 1294 | sprintf(info->bus_info, "SBUS:%d", | ||
| 1295 | lp->sdev->slot); | ||
| 1296 | } | 1301 | } |
| 1297 | 1302 | ||
| 1298 | static u32 sparc_lance_get_link(struct net_device *dev) | 1303 | static u32 sparc_lance_get_link(struct net_device *dev) |
| @@ -1308,16 +1313,16 @@ static const struct ethtool_ops sparc_lance_ethtool_ops = { | |||
| 1308 | .get_link = sparc_lance_get_link, | 1313 | .get_link = sparc_lance_get_link, |
| 1309 | }; | 1314 | }; |
| 1310 | 1315 | ||
| 1311 | static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | 1316 | static int __devinit sparc_lance_probe_one(struct of_device *op, |
| 1312 | struct sbus_dma *ledma, | 1317 | struct of_device *ledma, |
| 1313 | struct sbus_dev *lebuffer) | 1318 | struct of_device *lebuffer) |
| 1314 | { | 1319 | { |
| 1320 | struct device_node *dp = op->node; | ||
| 1315 | static unsigned version_printed; | 1321 | static unsigned version_printed; |
| 1316 | struct device_node *dp = sdev->ofdev.node; | ||
| 1317 | struct net_device *dev; | ||
| 1318 | struct lance_private *lp; | 1322 | struct lance_private *lp; |
| 1319 | int i; | 1323 | struct net_device *dev; |
| 1320 | DECLARE_MAC_BUF(mac); | 1324 | DECLARE_MAC_BUF(mac); |
| 1325 | int i; | ||
| 1321 | 1326 | ||
| 1322 | dev = alloc_etherdev(sizeof(struct lance_private) + 8); | 1327 | dev = alloc_etherdev(sizeof(struct lance_private) + 8); |
| 1323 | if (!dev) | 1328 | if (!dev) |
| @@ -1338,14 +1343,27 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
| 1338 | dev->dev_addr[i] = idprom->id_ethaddr[i]; | 1343 | dev->dev_addr[i] = idprom->id_ethaddr[i]; |
| 1339 | 1344 | ||
| 1340 | /* Get the IO region */ | 1345 | /* Get the IO region */ |
| 1341 | lp->lregs = sbus_ioremap(&sdev->resource[0], 0, | 1346 | lp->lregs = of_ioremap(&op->resource[0], 0, |
| 1342 | LANCE_REG_SIZE, lancestr); | 1347 | LANCE_REG_SIZE, lancestr); |
| 1343 | if (!lp->lregs) { | 1348 | if (!lp->lregs) { |
| 1344 | printk(KERN_ERR "SunLance: Cannot map registers.\n"); | 1349 | printk(KERN_ERR "SunLance: Cannot map registers.\n"); |
| 1345 | goto fail; | 1350 | goto fail; |
| 1346 | } | 1351 | } |
| 1347 | 1352 | ||
| 1348 | lp->sdev = sdev; | 1353 | lp->ledma = ledma; |
| 1354 | if (lp->ledma) { | ||
| 1355 | lp->dregs = of_ioremap(&ledma->resource[0], 0, | ||
| 1356 | resource_size(&ledma->resource[0]), | ||
| 1357 | "ledma"); | ||
| 1358 | if (!lp->dregs) { | ||
| 1359 | printk(KERN_ERR "SunLance: Cannot map " | ||
| 1360 | "ledma registers.\n"); | ||
| 1361 | goto fail; | ||
| 1362 | } | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | lp->op = op; | ||
| 1366 | lp->lebuffer = lebuffer; | ||
| 1349 | if (lebuffer) { | 1367 | if (lebuffer) { |
| 1350 | /* sanity check */ | 1368 | /* sanity check */ |
| 1351 | if (lebuffer->resource[0].start & 7) { | 1369 | if (lebuffer->resource[0].start & 7) { |
| @@ -1353,8 +1371,8 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
| 1353 | goto fail; | 1371 | goto fail; |
| 1354 | } | 1372 | } |
| 1355 | lp->init_block_iomem = | 1373 | lp->init_block_iomem = |
| 1356 | sbus_ioremap(&lebuffer->resource[0], 0, | 1374 | of_ioremap(&lebuffer->resource[0], 0, |
| 1357 | sizeof(struct lance_init_block), "lebuffer"); | 1375 | sizeof(struct lance_init_block), "lebuffer"); |
| 1358 | if (!lp->init_block_iomem) { | 1376 | if (!lp->init_block_iomem) { |
| 1359 | printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n"); | 1377 | printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n"); |
| 1360 | goto fail; | 1378 | goto fail; |
| @@ -1366,9 +1384,10 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
| 1366 | lp->tx = lance_tx_pio; | 1384 | lp->tx = lance_tx_pio; |
| 1367 | } else { | 1385 | } else { |
| 1368 | lp->init_block_mem = | 1386 | lp->init_block_mem = |
| 1369 | sbus_alloc_consistent(sdev, sizeof(struct lance_init_block), | 1387 | dma_alloc_coherent(&op->dev, |
| 1370 | &lp->init_block_dvma); | 1388 | sizeof(struct lance_init_block), |
| 1371 | if (!lp->init_block_mem || lp->init_block_dvma == 0) { | 1389 | &lp->init_block_dvma, GFP_ATOMIC); |
| 1390 | if (!lp->init_block_mem) { | ||
| 1372 | printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n"); | 1391 | printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n"); |
| 1373 | goto fail; | 1392 | goto fail; |
| 1374 | } | 1393 | } |
| @@ -1383,13 +1402,13 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
| 1383 | LE_C3_BCON)); | 1402 | LE_C3_BCON)); |
| 1384 | 1403 | ||
| 1385 | lp->name = lancestr; | 1404 | lp->name = lancestr; |
| 1386 | lp->ledma = ledma; | ||
| 1387 | 1405 | ||
| 1388 | lp->burst_sizes = 0; | 1406 | lp->burst_sizes = 0; |
| 1389 | if (lp->ledma) { | 1407 | if (lp->ledma) { |
| 1390 | struct device_node *ledma_dp = ledma->sdev->ofdev.node; | 1408 | struct device_node *ledma_dp = ledma->node; |
| 1391 | const char *prop; | 1409 | struct device_node *sbus_dp; |
| 1392 | unsigned int sbmask; | 1410 | unsigned int sbmask; |
| 1411 | const char *prop; | ||
| 1393 | u32 csr; | 1412 | u32 csr; |
| 1394 | 1413 | ||
| 1395 | /* Find burst-size property for ledma */ | 1414 | /* Find burst-size property for ledma */ |
| @@ -1397,7 +1416,8 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
| 1397 | "burst-sizes", 0); | 1416 | "burst-sizes", 0); |
| 1398 | 1417 | ||
| 1399 | /* ledma may be capable of fast bursts, but sbus may not. */ | 1418 | /* ledma may be capable of fast bursts, but sbus may not. */ |
| 1400 | sbmask = of_getintprop_default(ledma_dp, "burst-sizes", | 1419 | sbus_dp = ledma_dp->parent; |
| 1420 | sbmask = of_getintprop_default(sbus_dp, "burst-sizes", | ||
| 1401 | DMA_BURSTBITS); | 1421 | DMA_BURSTBITS); |
| 1402 | lp->burst_sizes &= sbmask; | 1422 | lp->burst_sizes &= sbmask; |
| 1403 | 1423 | ||
| @@ -1435,8 +1455,6 @@ no_link_test: | |||
| 1435 | lp->tpe = 1; | 1455 | lp->tpe = 1; |
| 1436 | } | 1456 | } |
| 1437 | 1457 | ||
| 1438 | lp->dregs = ledma->regs; | ||
| 1439 | |||
| 1440 | /* Reset ledma */ | 1458 | /* Reset ledma */ |
| 1441 | csr = sbus_readl(lp->dregs + DMA_CSR); | 1459 | csr = sbus_readl(lp->dregs + DMA_CSR); |
| 1442 | sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR); | 1460 | sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR); |
| @@ -1446,7 +1464,7 @@ no_link_test: | |||
| 1446 | lp->dregs = NULL; | 1464 | lp->dregs = NULL; |
| 1447 | 1465 | ||
| 1448 | lp->dev = dev; | 1466 | lp->dev = dev; |
| 1449 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 1467 | SET_NETDEV_DEV(dev, &op->dev); |
| 1450 | dev->open = &lance_open; | 1468 | dev->open = &lance_open; |
| 1451 | dev->stop = &lance_close; | 1469 | dev->stop = &lance_close; |
| 1452 | dev->hard_start_xmit = &lance_start_xmit; | 1470 | dev->hard_start_xmit = &lance_start_xmit; |
| @@ -1455,9 +1473,7 @@ no_link_test: | |||
| 1455 | dev->set_multicast_list = &lance_set_multicast; | 1473 | dev->set_multicast_list = &lance_set_multicast; |
| 1456 | dev->ethtool_ops = &sparc_lance_ethtool_ops; | 1474 | dev->ethtool_ops = &sparc_lance_ethtool_ops; |
| 1457 | 1475 | ||
| 1458 | dev->irq = sdev->irqs[0]; | 1476 | dev->irq = op->irqs[0]; |
| 1459 | |||
| 1460 | dev->dma = 0; | ||
| 1461 | 1477 | ||
| 1462 | /* We cannot sleep if the chip is busy during a | 1478 | /* We cannot sleep if the chip is busy during a |
| 1463 | * multicast list update event, because such events | 1479 | * multicast list update event, because such events |
| @@ -1473,7 +1489,7 @@ no_link_test: | |||
| 1473 | goto fail; | 1489 | goto fail; |
| 1474 | } | 1490 | } |
| 1475 | 1491 | ||
| 1476 | dev_set_drvdata(&sdev->ofdev.dev, lp); | 1492 | dev_set_drvdata(&op->dev, lp); |
| 1477 | 1493 | ||
| 1478 | printk(KERN_INFO "%s: LANCE %s\n", | 1494 | printk(KERN_INFO "%s: LANCE %s\n", |
| 1479 | dev->name, print_mac(mac, dev->dev_addr)); | 1495 | dev->name, print_mac(mac, dev->dev_addr)); |
| @@ -1486,80 +1502,25 @@ fail: | |||
| 1486 | return -ENODEV; | 1502 | return -ENODEV; |
| 1487 | } | 1503 | } |
| 1488 | 1504 | ||
| 1489 | /* On 4m, find the associated dma for the lance chip */ | 1505 | static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match) |
| 1490 | static struct sbus_dma * __devinit find_ledma(struct sbus_dev *sdev) | ||
| 1491 | { | ||
| 1492 | struct sbus_dma *p; | ||
| 1493 | |||
| 1494 | for_each_dvma(p) { | ||
| 1495 | if (p->sdev == sdev) | ||
| 1496 | return p; | ||
| 1497 | } | ||
| 1498 | return NULL; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | #ifdef CONFIG_SUN4 | ||
| 1502 | |||
| 1503 | #include <asm/sun4paddr.h> | ||
| 1504 | #include <asm/machines.h> | ||
| 1505 | |||
| 1506 | /* Find all the lance cards on the system and initialize them */ | ||
| 1507 | static struct sbus_dev sun4_sdev; | ||
| 1508 | static int __devinit sparc_lance_init(void) | ||
| 1509 | { | ||
| 1510 | if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || | ||
| 1511 | (idprom->id_machtype == (SM_SUN4|SM_4_470))) { | ||
| 1512 | memset(&sun4_sdev, 0, sizeof(struct sbus_dev)); | ||
| 1513 | sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; | ||
| 1514 | sun4_sdev.irqs[0] = 6; | ||
| 1515 | return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); | ||
| 1516 | } | ||
| 1517 | return -ENODEV; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | static int __exit sunlance_sun4_remove(void) | ||
| 1521 | { | 1506 | { |
| 1522 | struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev); | 1507 | struct of_device *parent = to_of_device(op->dev.parent); |
| 1523 | struct net_device *net_dev = lp->dev; | 1508 | struct device_node *parent_dp = parent->node; |
| 1524 | |||
| 1525 | unregister_netdev(net_dev); | ||
| 1526 | |||
| 1527 | lance_free_hwresources(lp); | ||
| 1528 | |||
| 1529 | free_netdev(net_dev); | ||
| 1530 | |||
| 1531 | dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL); | ||
| 1532 | |||
| 1533 | return 0; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | #else /* !CONFIG_SUN4 */ | ||
| 1537 | |||
| 1538 | static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
| 1539 | { | ||
| 1540 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
| 1541 | int err; | 1509 | int err; |
| 1542 | 1510 | ||
| 1543 | if (sdev->parent) { | 1511 | if (!strcmp(parent_dp->name, "ledma")) { |
| 1544 | struct of_device *parent = &sdev->parent->ofdev; | 1512 | err = sparc_lance_probe_one(op, parent, NULL); |
| 1545 | 1513 | } else if (!strcmp(parent_dp->name, "lebuffer")) { | |
| 1546 | if (!strcmp(parent->node->name, "ledma")) { | 1514 | err = sparc_lance_probe_one(op, NULL, parent); |
| 1547 | struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev)); | ||
| 1548 | |||
| 1549 | err = sparc_lance_probe_one(sdev, ledma, NULL); | ||
| 1550 | } else if (!strcmp(parent->node->name, "lebuffer")) { | ||
| 1551 | err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev)); | ||
| 1552 | } else | ||
| 1553 | err = sparc_lance_probe_one(sdev, NULL, NULL); | ||
| 1554 | } else | 1515 | } else |
| 1555 | err = sparc_lance_probe_one(sdev, NULL, NULL); | 1516 | err = sparc_lance_probe_one(op, NULL, NULL); |
| 1556 | 1517 | ||
| 1557 | return err; | 1518 | return err; |
| 1558 | } | 1519 | } |
| 1559 | 1520 | ||
| 1560 | static int __devexit sunlance_sbus_remove(struct of_device *dev) | 1521 | static int __devexit sunlance_sbus_remove(struct of_device *op) |
| 1561 | { | 1522 | { |
| 1562 | struct lance_private *lp = dev_get_drvdata(&dev->dev); | 1523 | struct lance_private *lp = dev_get_drvdata(&op->dev); |
| 1563 | struct net_device *net_dev = lp->dev; | 1524 | struct net_device *net_dev = lp->dev; |
| 1564 | 1525 | ||
| 1565 | unregister_netdev(net_dev); | 1526 | unregister_netdev(net_dev); |
| @@ -1568,12 +1529,12 @@ static int __devexit sunlance_sbus_remove(struct of_device *dev) | |||
| 1568 | 1529 | ||
| 1569 | free_netdev(net_dev); | 1530 | free_netdev(net_dev); |
| 1570 | 1531 | ||
| 1571 | dev_set_drvdata(&dev->dev, NULL); | 1532 | dev_set_drvdata(&op->dev, NULL); |
| 1572 | 1533 | ||
| 1573 | return 0; | 1534 | return 0; |
| 1574 | } | 1535 | } |
| 1575 | 1536 | ||
| 1576 | static struct of_device_id sunlance_sbus_match[] = { | 1537 | static const struct of_device_id sunlance_sbus_match[] = { |
| 1577 | { | 1538 | { |
| 1578 | .name = "le", | 1539 | .name = "le", |
| 1579 | }, | 1540 | }, |
| @@ -1593,17 +1554,12 @@ static struct of_platform_driver sunlance_sbus_driver = { | |||
| 1593 | /* Find all the lance cards on the system and initialize them */ | 1554 | /* Find all the lance cards on the system and initialize them */ |
| 1594 | static int __init sparc_lance_init(void) | 1555 | static int __init sparc_lance_init(void) |
| 1595 | { | 1556 | { |
| 1596 | return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type); | 1557 | return of_register_driver(&sunlance_sbus_driver, &of_bus_type); |
| 1597 | } | 1558 | } |
| 1598 | #endif /* !CONFIG_SUN4 */ | ||
| 1599 | 1559 | ||
| 1600 | static void __exit sparc_lance_exit(void) | 1560 | static void __exit sparc_lance_exit(void) |
| 1601 | { | 1561 | { |
| 1602 | #ifdef CONFIG_SUN4 | ||
| 1603 | sunlance_sun4_remove(); | ||
| 1604 | #else | ||
| 1605 | of_unregister_driver(&sunlance_sbus_driver); | 1562 | of_unregister_driver(&sunlance_sbus_driver); |
| 1606 | #endif | ||
| 1607 | } | 1563 | } |
| 1608 | 1564 | ||
| 1609 | module_init(sparc_lance_init); | 1565 | module_init(sparc_lance_init); |
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index e811331d4608..f63644744ff9 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * controller out there can be most efficiently programmed | 3 | * controller out there can be most efficiently programmed |
| 4 | * if you make it look like a LANCE. | 4 | * if you make it look like a LANCE. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1996, 1999, 2003, 2006 David S. Miller (davem@davemloft.net) | 6 | * Copyright (C) 1996, 1999, 2003, 2006, 2008 David S. Miller (davem@davemloft.net) |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| @@ -24,13 +24,15 @@ | |||
| 24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
| 25 | #include <linux/ethtool.h> | 25 | #include <linux/ethtool.h> |
| 26 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
| 27 | #include <linux/dma-mapping.h> | ||
| 28 | #include <linux/of.h> | ||
| 29 | #include <linux/of_device.h> | ||
| 27 | 30 | ||
| 28 | #include <asm/system.h> | 31 | #include <asm/system.h> |
| 29 | #include <asm/io.h> | 32 | #include <asm/io.h> |
| 30 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
| 31 | #include <asm/byteorder.h> | 34 | #include <asm/byteorder.h> |
| 32 | #include <asm/idprom.h> | 35 | #include <asm/idprom.h> |
| 33 | #include <asm/sbus.h> | ||
| 34 | #include <asm/openprom.h> | 36 | #include <asm/openprom.h> |
| 35 | #include <asm/oplib.h> | 37 | #include <asm/oplib.h> |
| 36 | #include <asm/auxio.h> | 38 | #include <asm/auxio.h> |
| @@ -40,8 +42,8 @@ | |||
| 40 | #include "sunqe.h" | 42 | #include "sunqe.h" |
| 41 | 43 | ||
| 42 | #define DRV_NAME "sunqe" | 44 | #define DRV_NAME "sunqe" |
| 43 | #define DRV_VERSION "4.0" | 45 | #define DRV_VERSION "4.1" |
| 44 | #define DRV_RELDATE "June 23, 2006" | 46 | #define DRV_RELDATE "August 27, 2008" |
| 45 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" | 47 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
| 46 | 48 | ||
| 47 | static char version[] = | 49 | static char version[] = |
| @@ -690,12 +692,18 @@ static void qe_set_multicast(struct net_device *dev) | |||
| 690 | /* Ethtool support... */ | 692 | /* Ethtool support... */ |
| 691 | static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 693 | static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
| 692 | { | 694 | { |
| 695 | const struct linux_prom_registers *regs; | ||
| 693 | struct sunqe *qep = dev->priv; | 696 | struct sunqe *qep = dev->priv; |
| 697 | struct of_device *op; | ||
| 694 | 698 | ||
| 695 | strcpy(info->driver, "sunqe"); | 699 | strcpy(info->driver, "sunqe"); |
| 696 | strcpy(info->version, "3.0"); | 700 | strcpy(info->version, "3.0"); |
| 697 | sprintf(info->bus_info, "SBUS:%d", | 701 | |
| 698 | qep->qe_sdev->slot); | 702 | op = qep->op; |
| 703 | regs = of_get_property(op->node, "reg", NULL); | ||
| 704 | if (regs) | ||
| 705 | sprintf(info->bus_info, "SBUS:%d", regs->which_io); | ||
| 706 | |||
| 699 | } | 707 | } |
| 700 | 708 | ||
| 701 | static u32 qe_get_link(struct net_device *dev) | 709 | static u32 qe_get_link(struct net_device *dev) |
| @@ -717,11 +725,11 @@ static const struct ethtool_ops qe_ethtool_ops = { | |||
| 717 | }; | 725 | }; |
| 718 | 726 | ||
| 719 | /* This is only called once at boot time for each card probed. */ | 727 | /* This is only called once at boot time for each card probed. */ |
| 720 | static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) | 728 | static void qec_init_once(struct sunqec *qecp, struct of_device *op) |
| 721 | { | 729 | { |
| 722 | u8 bsizes = qecp->qec_bursts; | 730 | u8 bsizes = qecp->qec_bursts; |
| 723 | 731 | ||
| 724 | if (sbus_can_burst64(qsdev) && (bsizes & DMA_BURST64)) { | 732 | if (sbus_can_burst64() && (bsizes & DMA_BURST64)) { |
| 725 | sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL); | 733 | sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL); |
| 726 | } else if (bsizes & DMA_BURST32) { | 734 | } else if (bsizes & DMA_BURST32) { |
| 727 | sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL); | 735 | sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL); |
| @@ -735,15 +743,15 @@ static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) | |||
| 735 | sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE); | 743 | sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE); |
| 736 | 744 | ||
| 737 | /* Set the local memsize register, divided up to one piece per QE channel. */ | 745 | /* Set the local memsize register, divided up to one piece per QE channel. */ |
| 738 | sbus_writel((qsdev->reg_addrs[1].reg_size >> 2), | 746 | sbus_writel((resource_size(&op->resource[1]) >> 2), |
| 739 | qecp->gregs + GLOB_MSIZE); | 747 | qecp->gregs + GLOB_MSIZE); |
| 740 | 748 | ||
| 741 | /* Divide up the local QEC memory amongst the 4 QE receiver and | 749 | /* Divide up the local QEC memory amongst the 4 QE receiver and |
| 742 | * transmitter FIFOs. Basically it is (total / 2 / num_channels). | 750 | * transmitter FIFOs. Basically it is (total / 2 / num_channels). |
| 743 | */ | 751 | */ |
| 744 | sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1, | 752 | sbus_writel((resource_size(&op->resource[1]) >> 2) >> 1, |
| 745 | qecp->gregs + GLOB_TSIZE); | 753 | qecp->gregs + GLOB_TSIZE); |
| 746 | sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1, | 754 | sbus_writel((resource_size(&op->resource[1]) >> 2) >> 1, |
| 747 | qecp->gregs + GLOB_RSIZE); | 755 | qecp->gregs + GLOB_RSIZE); |
| 748 | } | 756 | } |
| 749 | 757 | ||
| @@ -767,24 +775,21 @@ static u8 __devinit qec_get_burst(struct device_node *dp) | |||
| 767 | return bsizes; | 775 | return bsizes; |
| 768 | } | 776 | } |
| 769 | 777 | ||
| 770 | static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev) | 778 | static struct sunqec * __devinit get_qec(struct of_device *child) |
| 771 | { | 779 | { |
| 772 | struct sbus_dev *qec_sdev = child_sdev->parent; | 780 | struct of_device *op = to_of_device(child->dev.parent); |
| 773 | struct sunqec *qecp; | 781 | struct sunqec *qecp; |
| 774 | 782 | ||
| 775 | for (qecp = root_qec_dev; qecp; qecp = qecp->next_module) { | 783 | qecp = dev_get_drvdata(&op->dev); |
| 776 | if (qecp->qec_sdev == qec_sdev) | ||
| 777 | break; | ||
| 778 | } | ||
| 779 | if (!qecp) { | 784 | if (!qecp) { |
| 780 | qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); | 785 | qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); |
| 781 | if (qecp) { | 786 | if (qecp) { |
| 782 | u32 ctrl; | 787 | u32 ctrl; |
| 783 | 788 | ||
| 784 | qecp->qec_sdev = qec_sdev; | 789 | qecp->op = op; |
| 785 | qecp->gregs = sbus_ioremap(&qec_sdev->resource[0], 0, | 790 | qecp->gregs = of_ioremap(&op->resource[0], 0, |
| 786 | GLOB_REG_SIZE, | 791 | GLOB_REG_SIZE, |
| 787 | "QEC Global Registers"); | 792 | "QEC Global Registers"); |
| 788 | if (!qecp->gregs) | 793 | if (!qecp->gregs) |
| 789 | goto fail; | 794 | goto fail; |
| 790 | 795 | ||
| @@ -799,16 +804,18 @@ static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev) | |||
| 799 | if (qec_global_reset(qecp->gregs)) | 804 | if (qec_global_reset(qecp->gregs)) |
| 800 | goto fail; | 805 | goto fail; |
| 801 | 806 | ||
| 802 | qecp->qec_bursts = qec_get_burst(qec_sdev->ofdev.node); | 807 | qecp->qec_bursts = qec_get_burst(op->node); |
| 803 | 808 | ||
| 804 | qec_init_once(qecp, qec_sdev); | 809 | qec_init_once(qecp, op); |
| 805 | 810 | ||
| 806 | if (request_irq(qec_sdev->irqs[0], &qec_interrupt, | 811 | if (request_irq(op->irqs[0], &qec_interrupt, |
| 807 | IRQF_SHARED, "qec", (void *) qecp)) { | 812 | IRQF_SHARED, "qec", (void *) qecp)) { |
| 808 | printk(KERN_ERR "qec: Can't register irq.\n"); | 813 | printk(KERN_ERR "qec: Can't register irq.\n"); |
| 809 | goto fail; | 814 | goto fail; |
| 810 | } | 815 | } |
| 811 | 816 | ||
| 817 | dev_set_drvdata(&op->dev, qecp); | ||
| 818 | |||
| 812 | qecp->next_module = root_qec_dev; | 819 | qecp->next_module = root_qec_dev; |
| 813 | root_qec_dev = qecp; | 820 | root_qec_dev = qecp; |
| 814 | } | 821 | } |
| @@ -818,17 +825,17 @@ static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev) | |||
| 818 | 825 | ||
| 819 | fail: | 826 | fail: |
| 820 | if (qecp->gregs) | 827 | if (qecp->gregs) |
| 821 | sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); | 828 | of_iounmap(&op->resource[0], qecp->gregs, GLOB_REG_SIZE); |
| 822 | kfree(qecp); | 829 | kfree(qecp); |
| 823 | return NULL; | 830 | return NULL; |
| 824 | } | 831 | } |
| 825 | 832 | ||
| 826 | static int __devinit qec_ether_init(struct sbus_dev *sdev) | 833 | static int __devinit qec_ether_init(struct of_device *op) |
| 827 | { | 834 | { |
| 828 | static unsigned version_printed; | 835 | static unsigned version_printed; |
| 829 | struct net_device *dev; | 836 | struct net_device *dev; |
| 830 | struct sunqe *qe; | ||
| 831 | struct sunqec *qecp; | 837 | struct sunqec *qecp; |
| 838 | struct sunqe *qe; | ||
| 832 | int i, res; | 839 | int i, res; |
| 833 | 840 | ||
| 834 | if (version_printed++ == 0) | 841 | if (version_printed++ == 0) |
| @@ -842,49 +849,42 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
| 842 | 849 | ||
| 843 | qe = netdev_priv(dev); | 850 | qe = netdev_priv(dev); |
| 844 | 851 | ||
| 845 | i = of_getintprop_default(sdev->ofdev.node, "channel#", -1); | 852 | res = -ENODEV; |
| 846 | if (i == -1) { | 853 | |
| 847 | struct sbus_dev *td = sdev->parent->child; | 854 | i = of_getintprop_default(op->node, "channel#", -1); |
| 848 | i = 0; | 855 | if (i == -1) |
| 849 | while (td != sdev) { | 856 | goto fail; |
| 850 | td = td->next; | ||
| 851 | i++; | ||
| 852 | } | ||
| 853 | } | ||
| 854 | qe->channel = i; | 857 | qe->channel = i; |
| 855 | spin_lock_init(&qe->lock); | 858 | spin_lock_init(&qe->lock); |
| 856 | 859 | ||
| 857 | res = -ENODEV; | 860 | qecp = get_qec(op); |
| 858 | qecp = get_qec(sdev); | ||
| 859 | if (!qecp) | 861 | if (!qecp) |
| 860 | goto fail; | 862 | goto fail; |
| 861 | 863 | ||
| 862 | qecp->qes[qe->channel] = qe; | 864 | qecp->qes[qe->channel] = qe; |
| 863 | qe->dev = dev; | 865 | qe->dev = dev; |
| 864 | qe->parent = qecp; | 866 | qe->parent = qecp; |
| 865 | qe->qe_sdev = sdev; | 867 | qe->op = op; |
| 866 | 868 | ||
| 867 | res = -ENOMEM; | 869 | res = -ENOMEM; |
| 868 | qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0, | 870 | qe->qcregs = of_ioremap(&op->resource[0], 0, |
| 869 | CREG_REG_SIZE, "QEC Channel Registers"); | 871 | CREG_REG_SIZE, "QEC Channel Registers"); |
| 870 | if (!qe->qcregs) { | 872 | if (!qe->qcregs) { |
| 871 | printk(KERN_ERR "qe: Cannot map channel registers.\n"); | 873 | printk(KERN_ERR "qe: Cannot map channel registers.\n"); |
| 872 | goto fail; | 874 | goto fail; |
| 873 | } | 875 | } |
| 874 | 876 | ||
| 875 | qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0, | 877 | qe->mregs = of_ioremap(&op->resource[1], 0, |
| 876 | MREGS_REG_SIZE, "QE MACE Registers"); | 878 | MREGS_REG_SIZE, "QE MACE Registers"); |
| 877 | if (!qe->mregs) { | 879 | if (!qe->mregs) { |
| 878 | printk(KERN_ERR "qe: Cannot map MACE registers.\n"); | 880 | printk(KERN_ERR "qe: Cannot map MACE registers.\n"); |
| 879 | goto fail; | 881 | goto fail; |
| 880 | } | 882 | } |
| 881 | 883 | ||
| 882 | qe->qe_block = sbus_alloc_consistent(qe->qe_sdev, | 884 | qe->qe_block = dma_alloc_coherent(&op->dev, PAGE_SIZE, |
| 883 | PAGE_SIZE, | 885 | &qe->qblock_dvma, GFP_ATOMIC); |
| 884 | &qe->qblock_dvma); | 886 | qe->buffers = dma_alloc_coherent(&op->dev, sizeof(struct sunqe_buffers), |
| 885 | qe->buffers = sbus_alloc_consistent(qe->qe_sdev, | 887 | &qe->buffers_dvma, GFP_ATOMIC); |
| 886 | sizeof(struct sunqe_buffers), | ||
| 887 | &qe->buffers_dvma); | ||
| 888 | if (qe->qe_block == NULL || qe->qblock_dvma == 0 || | 888 | if (qe->qe_block == NULL || qe->qblock_dvma == 0 || |
| 889 | qe->buffers == NULL || qe->buffers_dvma == 0) | 889 | qe->buffers == NULL || qe->buffers_dvma == 0) |
| 890 | goto fail; | 890 | goto fail; |
| @@ -892,7 +892,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
| 892 | /* Stop this QE. */ | 892 | /* Stop this QE. */ |
| 893 | qe_stop(qe); | 893 | qe_stop(qe); |
| 894 | 894 | ||
| 895 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 895 | SET_NETDEV_DEV(dev, &op->dev); |
| 896 | 896 | ||
| 897 | dev->open = qe_open; | 897 | dev->open = qe_open; |
| 898 | dev->stop = qe_close; | 898 | dev->stop = qe_close; |
| @@ -900,7 +900,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
| 900 | dev->set_multicast_list = qe_set_multicast; | 900 | dev->set_multicast_list = qe_set_multicast; |
| 901 | dev->tx_timeout = qe_tx_timeout; | 901 | dev->tx_timeout = qe_tx_timeout; |
| 902 | dev->watchdog_timeo = 5*HZ; | 902 | dev->watchdog_timeo = 5*HZ; |
| 903 | dev->irq = sdev->irqs[0]; | 903 | dev->irq = op->irqs[0]; |
| 904 | dev->dma = 0; | 904 | dev->dma = 0; |
| 905 | dev->ethtool_ops = &qe_ethtool_ops; | 905 | dev->ethtool_ops = &qe_ethtool_ops; |
| 906 | 906 | ||
| @@ -908,7 +908,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
| 908 | if (res) | 908 | if (res) |
| 909 | goto fail; | 909 | goto fail; |
| 910 | 910 | ||
| 911 | dev_set_drvdata(&sdev->ofdev.dev, qe); | 911 | dev_set_drvdata(&op->dev, qe); |
| 912 | 912 | ||
| 913 | printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel); | 913 | printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel); |
| 914 | for (i = 0; i < 6; i++) | 914 | for (i = 0; i < 6; i++) |
| @@ -922,58 +922,50 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
| 922 | 922 | ||
| 923 | fail: | 923 | fail: |
| 924 | if (qe->qcregs) | 924 | if (qe->qcregs) |
| 925 | sbus_iounmap(qe->qcregs, CREG_REG_SIZE); | 925 | of_iounmap(&op->resource[0], qe->qcregs, CREG_REG_SIZE); |
| 926 | if (qe->mregs) | 926 | if (qe->mregs) |
| 927 | sbus_iounmap(qe->mregs, MREGS_REG_SIZE); | 927 | of_iounmap(&op->resource[1], qe->mregs, MREGS_REG_SIZE); |
| 928 | if (qe->qe_block) | 928 | if (qe->qe_block) |
| 929 | sbus_free_consistent(qe->qe_sdev, | 929 | dma_free_coherent(&op->dev, PAGE_SIZE, |
| 930 | PAGE_SIZE, | 930 | qe->qe_block, qe->qblock_dvma); |
| 931 | qe->qe_block, | ||
| 932 | qe->qblock_dvma); | ||
| 933 | if (qe->buffers) | 931 | if (qe->buffers) |
| 934 | sbus_free_consistent(qe->qe_sdev, | 932 | dma_free_coherent(&op->dev, |
| 935 | sizeof(struct sunqe_buffers), | 933 | sizeof(struct sunqe_buffers), |
| 936 | qe->buffers, | 934 | qe->buffers, |
| 937 | qe->buffers_dvma); | 935 | qe->buffers_dvma); |
| 938 | 936 | ||
| 939 | free_netdev(dev); | 937 | free_netdev(dev); |
| 940 | 938 | ||
| 941 | return res; | 939 | return res; |
| 942 | } | 940 | } |
| 943 | 941 | ||
| 944 | static int __devinit qec_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 942 | static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match) |
| 945 | { | 943 | { |
| 946 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 944 | return qec_ether_init(op); |
| 947 | |||
| 948 | return qec_ether_init(sdev); | ||
| 949 | } | 945 | } |
| 950 | 946 | ||
| 951 | static int __devexit qec_sbus_remove(struct of_device *dev) | 947 | static int __devexit qec_sbus_remove(struct of_device *op) |
| 952 | { | 948 | { |
| 953 | struct sunqe *qp = dev_get_drvdata(&dev->dev); | 949 | struct sunqe *qp = dev_get_drvdata(&op->dev); |
| 954 | struct net_device *net_dev = qp->dev; | 950 | struct net_device *net_dev = qp->dev; |
| 955 | 951 | ||
| 956 | unregister_netdev(net_dev); | 952 | unregister_netdev(net_dev); |
| 957 | 953 | ||
| 958 | sbus_iounmap(qp->qcregs, CREG_REG_SIZE); | 954 | of_iounmap(&op->resource[0], qp->qcregs, CREG_REG_SIZE); |
| 959 | sbus_iounmap(qp->mregs, MREGS_REG_SIZE); | 955 | of_iounmap(&op->resource[1], qp->mregs, MREGS_REG_SIZE); |
| 960 | sbus_free_consistent(qp->qe_sdev, | 956 | dma_free_coherent(&op->dev, PAGE_SIZE, |
| 961 | PAGE_SIZE, | 957 | qp->qe_block, qp->qblock_dvma); |
| 962 | qp->qe_block, | 958 | dma_free_coherent(&op->dev, sizeof(struct sunqe_buffers), |
| 963 | qp->qblock_dvma); | 959 | qp->buffers, qp->buffers_dvma); |
| 964 | sbus_free_consistent(qp->qe_sdev, | ||
| 965 | sizeof(struct sunqe_buffers), | ||
| 966 | qp->buffers, | ||
| 967 | qp->buffers_dvma); | ||
| 968 | 960 | ||
| 969 | free_netdev(net_dev); | 961 | free_netdev(net_dev); |
| 970 | 962 | ||
| 971 | dev_set_drvdata(&dev->dev, NULL); | 963 | dev_set_drvdata(&op->dev, NULL); |
| 972 | 964 | ||
| 973 | return 0; | 965 | return 0; |
| 974 | } | 966 | } |
| 975 | 967 | ||
| 976 | static struct of_device_id qec_sbus_match[] = { | 968 | static const struct of_device_id qec_sbus_match[] = { |
| 977 | { | 969 | { |
| 978 | .name = "qe", | 970 | .name = "qe", |
| 979 | }, | 971 | }, |
| @@ -991,7 +983,7 @@ static struct of_platform_driver qec_sbus_driver = { | |||
| 991 | 983 | ||
| 992 | static int __init qec_init(void) | 984 | static int __init qec_init(void) |
| 993 | { | 985 | { |
| 994 | return of_register_driver(&qec_sbus_driver, &sbus_bus_type); | 986 | return of_register_driver(&qec_sbus_driver, &of_bus_type); |
| 995 | } | 987 | } |
| 996 | 988 | ||
| 997 | static void __exit qec_exit(void) | 989 | static void __exit qec_exit(void) |
| @@ -1000,11 +992,11 @@ static void __exit qec_exit(void) | |||
| 1000 | 992 | ||
| 1001 | while (root_qec_dev) { | 993 | while (root_qec_dev) { |
| 1002 | struct sunqec *next = root_qec_dev->next_module; | 994 | struct sunqec *next = root_qec_dev->next_module; |
| 995 | struct of_device *op = root_qec_dev->op; | ||
| 1003 | 996 | ||
| 1004 | free_irq(root_qec_dev->qec_sdev->irqs[0], | 997 | free_irq(op->irqs[0], (void *) root_qec_dev); |
| 1005 | (void *) root_qec_dev); | 998 | of_iounmap(&op->resource[0], root_qec_dev->gregs, |
| 1006 | sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE); | 999 | GLOB_REG_SIZE); |
| 1007 | |||
| 1008 | kfree(root_qec_dev); | 1000 | kfree(root_qec_dev); |
| 1009 | 1001 | ||
| 1010 | root_qec_dev = next; | 1002 | root_qec_dev = next; |
diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index 347c8ddc1592..5813a7b2faa5 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h | |||
| @@ -314,7 +314,7 @@ struct sunqec { | |||
| 314 | void __iomem *gregs; /* QEC Global Registers */ | 314 | void __iomem *gregs; /* QEC Global Registers */ |
| 315 | struct sunqe *qes[4]; /* Each child MACE */ | 315 | struct sunqe *qes[4]; /* Each child MACE */ |
| 316 | unsigned int qec_bursts; /* Support burst sizes */ | 316 | unsigned int qec_bursts; /* Support burst sizes */ |
| 317 | struct sbus_dev *qec_sdev; /* QEC's SBUS device */ | 317 | struct of_device *op; /* QEC's OF device */ |
| 318 | struct sunqec *next_module; /* List of all QECs in system */ | 318 | struct sunqec *next_module; /* List of all QECs in system */ |
| 319 | }; | 319 | }; |
| 320 | 320 | ||
| @@ -342,7 +342,7 @@ struct sunqe { | |||
| 342 | __u32 buffers_dvma; /* DVMA visible address. */ | 342 | __u32 buffers_dvma; /* DVMA visible address. */ |
| 343 | struct sunqec *parent; | 343 | struct sunqec *parent; |
| 344 | u8 mconfig; /* Base MACE mconfig value */ | 344 | u8 mconfig; /* Base MACE mconfig value */ |
| 345 | struct sbus_dev *qe_sdev; /* QE's SBUS device struct */ | 345 | struct of_device *op; /* QE's OF device struct */ |
| 346 | struct net_device *dev; /* QE's netdevice struct */ | 346 | struct net_device *dev; /* QE's netdevice struct */ |
| 347 | int channel; /* Who am I? */ | 347 | int channel; /* Who am I? */ |
| 348 | }; | 348 | }; |
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 6415ce15c2ef..a720065553df 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* sunvnet.c: Sun LDOM Virtual Network Driver. | 1 | /* sunvnet.c: Sun LDOM Virtual Network Driver. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
| @@ -1260,7 +1260,7 @@ static int vnet_port_remove(struct vio_dev *vdev) | |||
| 1260 | return 0; | 1260 | return 0; |
| 1261 | } | 1261 | } |
| 1262 | 1262 | ||
| 1263 | static struct vio_device_id vnet_port_match[] = { | 1263 | static const struct vio_device_id vnet_port_match[] = { |
| 1264 | { | 1264 | { |
| 1265 | .type = "vnet-port", | 1265 | .type = "vnet-port", |
| 1266 | }, | 1266 | }, |
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 9d595aa91e46..065f229580d5 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 29 | #include <linux/of.h> | ||
| 30 | #include <linux/of_device.h> | ||
| 29 | 31 | ||
| 30 | #include <linux/parport.h> | 32 | #include <linux/parport.h> |
| 31 | 33 | ||
| @@ -34,7 +36,6 @@ | |||
| 34 | 36 | ||
| 35 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 36 | #include <asm/oplib.h> /* OpenProm Library */ | 38 | #include <asm/oplib.h> /* OpenProm Library */ |
| 37 | #include <asm/sbus.h> | ||
| 38 | #include <asm/dma.h> /* BPP uses LSI 64854 for DMA */ | 39 | #include <asm/dma.h> /* BPP uses LSI 64854 for DMA */ |
| 39 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
| 40 | #include <asm/sunbpp.h> | 41 | #include <asm/sunbpp.h> |
| @@ -285,38 +286,37 @@ static struct parport_operations parport_sunbpp_ops = | |||
| 285 | .owner = THIS_MODULE, | 286 | .owner = THIS_MODULE, |
| 286 | }; | 287 | }; |
| 287 | 288 | ||
| 288 | static int __devinit init_one_port(struct sbus_dev *sdev) | 289 | static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match) |
| 289 | { | 290 | { |
| 290 | struct parport *p; | ||
| 291 | /* at least in theory there may be a "we don't dma" case */ | ||
| 292 | struct parport_operations *ops; | 291 | struct parport_operations *ops; |
| 293 | void __iomem *base; | ||
| 294 | int irq, dma, err = 0, size; | ||
| 295 | struct bpp_regs __iomem *regs; | 292 | struct bpp_regs __iomem *regs; |
| 293 | int irq, dma, err = 0, size; | ||
| 296 | unsigned char value_tcr; | 294 | unsigned char value_tcr; |
| 295 | void __iomem *base; | ||
| 296 | struct parport *p; | ||
| 297 | 297 | ||
| 298 | irq = sdev->irqs[0]; | 298 | irq = op->irqs[0]; |
| 299 | base = sbus_ioremap(&sdev->resource[0], 0, | 299 | base = of_ioremap(&op->resource[0], 0, |
| 300 | sdev->reg_addrs[0].reg_size, | 300 | resource_size(&op->resource[0]), |
| 301 | "sunbpp"); | 301 | "sunbpp"); |
| 302 | if (!base) | 302 | if (!base) |
| 303 | return -ENODEV; | 303 | return -ENODEV; |
| 304 | 304 | ||
| 305 | size = sdev->reg_addrs[0].reg_size; | 305 | size = resource_size(&op->resource[0]); |
| 306 | dma = PARPORT_DMA_NONE; | 306 | dma = PARPORT_DMA_NONE; |
| 307 | 307 | ||
| 308 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); | 308 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); |
| 309 | if (!ops) | 309 | if (!ops) |
| 310 | goto out_unmap; | 310 | goto out_unmap; |
| 311 | 311 | ||
| 312 | memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); | 312 | memcpy (ops, &parport_sunbpp_ops, sizeof(struct parport_operations)); |
| 313 | 313 | ||
| 314 | dprintk(("register_port\n")); | 314 | dprintk(("register_port\n")); |
| 315 | if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) | 315 | if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) |
| 316 | goto out_free_ops; | 316 | goto out_free_ops; |
| 317 | 317 | ||
| 318 | p->size = size; | 318 | p->size = size; |
| 319 | p->dev = &sdev->ofdev.dev; | 319 | p->dev = &op->dev; |
| 320 | 320 | ||
| 321 | if ((err = request_irq(p->irq, parport_irq_handler, | 321 | if ((err = request_irq(p->irq, parport_irq_handler, |
| 322 | IRQF_SHARED, p->name, p)) != 0) { | 322 | IRQF_SHARED, p->name, p)) != 0) { |
| @@ -333,7 +333,7 @@ static int __devinit init_one_port(struct sbus_dev *sdev) | |||
| 333 | 333 | ||
| 334 | printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); | 334 | printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); |
| 335 | 335 | ||
| 336 | dev_set_drvdata(&sdev->ofdev.dev, p); | 336 | dev_set_drvdata(&op->dev, p); |
| 337 | 337 | ||
| 338 | parport_announce_port(p); | 338 | parport_announce_port(p); |
| 339 | 339 | ||
| @@ -346,21 +346,14 @@ out_free_ops: | |||
| 346 | kfree(ops); | 346 | kfree(ops); |
| 347 | 347 | ||
| 348 | out_unmap: | 348 | out_unmap: |
| 349 | sbus_iounmap(base, size); | 349 | of_iounmap(&op->resource[0], base, size); |
| 350 | 350 | ||
| 351 | return err; | 351 | return err; |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) | 354 | static int __devexit bpp_remove(struct of_device *op) |
| 355 | { | ||
| 356 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
| 357 | |||
| 358 | return init_one_port(sdev); | ||
| 359 | } | ||
| 360 | |||
| 361 | static int __devexit bpp_remove(struct of_device *dev) | ||
| 362 | { | 355 | { |
| 363 | struct parport *p = dev_get_drvdata(&dev->dev); | 356 | struct parport *p = dev_get_drvdata(&op->dev); |
| 364 | struct parport_operations *ops = p->ops; | 357 | struct parport_operations *ops = p->ops; |
| 365 | 358 | ||
| 366 | parport_remove_port(p); | 359 | parport_remove_port(p); |
| @@ -370,16 +363,16 @@ static int __devexit bpp_remove(struct of_device *dev) | |||
| 370 | free_irq(p->irq, p); | 363 | free_irq(p->irq, p); |
| 371 | } | 364 | } |
| 372 | 365 | ||
| 373 | sbus_iounmap((void __iomem *) p->base, p->size); | 366 | of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size); |
| 374 | parport_put_port(p); | 367 | parport_put_port(p); |
| 375 | kfree(ops); | 368 | kfree(ops); |
| 376 | 369 | ||
| 377 | dev_set_drvdata(&dev->dev, NULL); | 370 | dev_set_drvdata(&op->dev, NULL); |
| 378 | 371 | ||
| 379 | return 0; | 372 | return 0; |
| 380 | } | 373 | } |
| 381 | 374 | ||
| 382 | static struct of_device_id bpp_match[] = { | 375 | static const struct of_device_id bpp_match[] = { |
| 383 | { | 376 | { |
| 384 | .name = "SUNW,bpp", | 377 | .name = "SUNW,bpp", |
| 385 | }, | 378 | }, |
| @@ -397,7 +390,7 @@ static struct of_platform_driver bpp_sbus_driver = { | |||
| 397 | 390 | ||
| 398 | static int __init parport_sunbpp_init(void) | 391 | static int __init parport_sunbpp_init(void) |
| 399 | { | 392 | { |
| 400 | return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); | 393 | return of_register_driver(&bpp_sbus_driver, &of_bus_type); |
| 401 | } | 394 | } |
| 402 | 395 | ||
| 403 | static void __exit parport_sunbpp_exit(void) | 396 | static void __exit parport_sunbpp_exit(void) |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9a9755c92fad..b57fba5c6d02 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -329,7 +329,7 @@ comment "Platform RTC drivers" | |||
| 329 | 329 | ||
| 330 | config RTC_DRV_CMOS | 330 | config RTC_DRV_CMOS |
| 331 | tristate "PC-style 'CMOS'" | 331 | tristate "PC-style 'CMOS'" |
| 332 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS | 332 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64 |
| 333 | default y if X86 | 333 | default y if X86 |
| 334 | help | 334 | help |
| 335 | Say "yes" here to get direct support for the real time clock | 335 | Say "yes" here to get direct support for the real time clock |
| @@ -406,14 +406,26 @@ config RTC_DRV_M48T86 | |||
| 406 | will be called rtc-m48t86. | 406 | will be called rtc-m48t86. |
| 407 | 407 | ||
| 408 | config RTC_DRV_M48T59 | 408 | config RTC_DRV_M48T59 |
| 409 | tristate "ST M48T59" | 409 | tristate "ST M48T59/M48T08/M48T02" |
| 410 | help | 410 | help |
| 411 | If you say Y here you will get support for the | 411 | If you say Y here you will get support for the |
| 412 | ST M48T59 RTC chip. | 412 | ST M48T59 RTC chip and compatible ST M48T08 and M48T02. |
| 413 | |||
| 414 | These chips are usually found in Sun SPARC and UltraSPARC | ||
| 415 | workstations. | ||
| 413 | 416 | ||
| 414 | This driver can also be built as a module, if so, the module | 417 | This driver can also be built as a module, if so, the module |
| 415 | will be called "rtc-m48t59". | 418 | will be called "rtc-m48t59". |
| 416 | 419 | ||
| 420 | config RTC_DRV_BQ4802 | ||
| 421 | tristate "TI BQ4802" | ||
| 422 | help | ||
| 423 | If you say Y here you will get support for the TI | ||
| 424 | BQ4802 RTC chip. | ||
| 425 | |||
| 426 | This driver can also be built as a module. If so, the module | ||
| 427 | will be called rtc-bq4802. | ||
| 428 | |||
| 417 | config RTC_DRV_V3020 | 429 | config RTC_DRV_V3020 |
| 418 | tristate "EM Microelectronic V3020" | 430 | tristate "EM Microelectronic V3020" |
| 419 | help | 431 | help |
| @@ -583,4 +595,18 @@ config RTC_DRV_PPC | |||
| 583 | the RTC. This exposes that functionality through the generic RTC | 595 | the RTC. This exposes that functionality through the generic RTC |
| 584 | class. | 596 | class. |
| 585 | 597 | ||
| 598 | config RTC_DRV_SUN4V | ||
| 599 | bool "SUN4V Hypervisor RTC" | ||
| 600 | depends on SPARC64 | ||
| 601 | help | ||
| 602 | If you say Y here you will get support for the Hypervisor | ||
| 603 | based RTC on SUN4V systems. | ||
| 604 | |||
| 605 | config RTC_DRV_STARFIRE | ||
| 606 | bool "Starfire RTC" | ||
| 607 | depends on SPARC64 | ||
| 608 | help | ||
| 609 | If you say Y here you will get support for the RTC found on | ||
| 610 | Starfire systems. | ||
| 611 | |||
| 586 | endif # RTC_CLASS | 612 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 18622ef84cab..10f41f85c38a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -38,6 +38,9 @@ obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | |||
| 38 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 38 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
| 39 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 39 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
| 40 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 40 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 41 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | ||
| 42 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | ||
| 43 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | ||
| 41 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 44 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
| 42 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 45 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
| 43 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 46 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c new file mode 100644 index 000000000000..189a018bdf34 --- /dev/null +++ b/drivers/rtc/rtc-bq4802.c | |||
| @@ -0,0 +1,230 @@ | |||
| 1 | /* rtc-bq4802.c: TI BQ4802 RTC driver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/io.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/rtc.h> | ||
| 12 | #include <linux/bcd.h> | ||
| 13 | |||
| 14 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 15 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); | ||
| 16 | MODULE_LICENSE("GPL"); | ||
| 17 | |||
| 18 | struct bq4802 { | ||
| 19 | void __iomem *regs; | ||
| 20 | unsigned long ioport; | ||
| 21 | struct rtc_device *rtc; | ||
| 22 | spinlock_t lock; | ||
| 23 | struct resource *r; | ||
| 24 | u8 (*read)(struct bq4802 *, int); | ||
| 25 | void (*write)(struct bq4802 *, int, u8); | ||
| 26 | }; | ||
| 27 | |||
| 28 | static u8 bq4802_read_io(struct bq4802 *p, int off) | ||
| 29 | { | ||
| 30 | return inb(p->ioport + off); | ||
| 31 | } | ||
| 32 | |||
| 33 | static void bq4802_write_io(struct bq4802 *p, int off, u8 val) | ||
| 34 | { | ||
| 35 | outb(val, p->ioport + off); | ||
| 36 | } | ||
| 37 | |||
| 38 | static u8 bq4802_read_mem(struct bq4802 *p, int off) | ||
| 39 | { | ||
| 40 | return readb(p->regs + off); | ||
| 41 | } | ||
| 42 | |||
| 43 | static void bq4802_write_mem(struct bq4802 *p, int off, u8 val) | ||
| 44 | { | ||
| 45 | writeb(val, p->regs + off); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int bq4802_read_time(struct device *dev, struct rtc_time *tm) | ||
| 49 | { | ||
| 50 | struct platform_device *pdev = to_platform_device(dev); | ||
| 51 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
| 52 | unsigned long flags; | ||
| 53 | unsigned int century; | ||
| 54 | u8 val; | ||
| 55 | |||
| 56 | spin_lock_irqsave(&p->lock, flags); | ||
| 57 | |||
| 58 | val = p->read(p, 0x0e); | ||
| 59 | p->write(p, 0xe, val | 0x08); | ||
| 60 | |||
| 61 | tm->tm_sec = p->read(p, 0x00); | ||
| 62 | tm->tm_min = p->read(p, 0x02); | ||
| 63 | tm->tm_hour = p->read(p, 0x04); | ||
| 64 | tm->tm_mday = p->read(p, 0x06); | ||
| 65 | tm->tm_mon = p->read(p, 0x09); | ||
| 66 | tm->tm_year = p->read(p, 0x0a); | ||
| 67 | tm->tm_wday = p->read(p, 0x08); | ||
| 68 | century = p->read(p, 0x0f); | ||
| 69 | |||
| 70 | p->write(p, 0x0e, val); | ||
| 71 | |||
| 72 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 73 | |||
| 74 | BCD_TO_BIN(tm->tm_sec); | ||
| 75 | BCD_TO_BIN(tm->tm_min); | ||
| 76 | BCD_TO_BIN(tm->tm_hour); | ||
| 77 | BCD_TO_BIN(tm->tm_mday); | ||
| 78 | BCD_TO_BIN(tm->tm_mon); | ||
| 79 | BCD_TO_BIN(tm->tm_year); | ||
| 80 | BCD_TO_BIN(tm->tm_wday); | ||
| 81 | BCD_TO_BIN(century); | ||
| 82 | |||
| 83 | tm->tm_year += (century * 100); | ||
| 84 | tm->tm_year -= 1900; | ||
| 85 | |||
| 86 | tm->tm_mon--; | ||
| 87 | |||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int bq4802_set_time(struct device *dev, struct rtc_time *tm) | ||
| 92 | { | ||
| 93 | struct platform_device *pdev = to_platform_device(dev); | ||
| 94 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
| 95 | u8 sec, min, hrs, day, mon, yrs, century, val; | ||
| 96 | unsigned long flags; | ||
| 97 | unsigned int year; | ||
| 98 | |||
| 99 | year = tm->tm_year + 1900; | ||
| 100 | century = year / 100; | ||
| 101 | yrs = year % 100; | ||
| 102 | |||
| 103 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
| 104 | day = tm->tm_mday; | ||
| 105 | hrs = tm->tm_hour; | ||
| 106 | min = tm->tm_min; | ||
| 107 | sec = tm->tm_sec; | ||
| 108 | |||
| 109 | BIN_TO_BCD(sec); | ||
| 110 | BIN_TO_BCD(min); | ||
| 111 | BIN_TO_BCD(hrs); | ||
| 112 | BIN_TO_BCD(day); | ||
| 113 | BIN_TO_BCD(mon); | ||
| 114 | BIN_TO_BCD(yrs); | ||
| 115 | BIN_TO_BCD(century); | ||
| 116 | |||
| 117 | spin_lock_irqsave(&p->lock, flags); | ||
| 118 | |||
| 119 | val = p->read(p, 0x0e); | ||
| 120 | p->write(p, 0x0e, val | 0x08); | ||
| 121 | |||
| 122 | p->write(p, 0x00, sec); | ||
| 123 | p->write(p, 0x02, min); | ||
| 124 | p->write(p, 0x04, hrs); | ||
| 125 | p->write(p, 0x06, day); | ||
| 126 | p->write(p, 0x09, mon); | ||
| 127 | p->write(p, 0x0a, yrs); | ||
| 128 | p->write(p, 0x0f, century); | ||
| 129 | |||
| 130 | p->write(p, 0x0e, val); | ||
| 131 | |||
| 132 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static const struct rtc_class_ops bq4802_ops = { | ||
| 138 | .read_time = bq4802_read_time, | ||
| 139 | .set_time = bq4802_set_time, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int __devinit bq4802_probe(struct platform_device *pdev) | ||
| 143 | { | ||
| 144 | struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 145 | int err = -ENOMEM; | ||
| 146 | |||
| 147 | if (!p) | ||
| 148 | goto out; | ||
| 149 | |||
| 150 | spin_lock_init(&p->lock); | ||
| 151 | |||
| 152 | p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 153 | if (!p->r) { | ||
| 154 | p->r = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 155 | err = -EINVAL; | ||
| 156 | if (!p->r) | ||
| 157 | goto out_free; | ||
| 158 | } | ||
| 159 | if (p->r->flags & IORESOURCE_IO) { | ||
| 160 | p->ioport = p->r->start; | ||
| 161 | p->read = bq4802_read_io; | ||
| 162 | p->write = bq4802_write_io; | ||
| 163 | } else if (p->r->flags & IORESOURCE_MEM) { | ||
| 164 | p->regs = ioremap(p->r->start, resource_size(p->r)); | ||
| 165 | p->read = bq4802_read_mem; | ||
| 166 | p->write = bq4802_write_mem; | ||
| 167 | } else { | ||
| 168 | err = -EINVAL; | ||
| 169 | goto out_free; | ||
| 170 | } | ||
| 171 | |||
| 172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | ||
| 173 | &bq4802_ops, THIS_MODULE); | ||
| 174 | if (IS_ERR(p->rtc)) { | ||
| 175 | err = PTR_ERR(p->rtc); | ||
| 176 | goto out_iounmap; | ||
| 177 | } | ||
| 178 | |||
| 179 | platform_set_drvdata(pdev, p); | ||
| 180 | err = 0; | ||
| 181 | out: | ||
| 182 | return err; | ||
| 183 | |||
| 184 | out_iounmap: | ||
| 185 | if (p->r->flags & IORESOURCE_MEM) | ||
| 186 | iounmap(p->regs); | ||
| 187 | out_free: | ||
| 188 | kfree(p); | ||
| 189 | goto out; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int __devexit bq4802_remove(struct platform_device *pdev) | ||
| 193 | { | ||
| 194 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
| 195 | |||
| 196 | rtc_device_unregister(p->rtc); | ||
| 197 | if (p->r->flags & IORESOURCE_MEM) | ||
| 198 | iounmap(p->regs); | ||
| 199 | |||
| 200 | platform_set_drvdata(pdev, NULL); | ||
| 201 | |||
| 202 | kfree(p); | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* work with hotplug and coldplug */ | ||
| 208 | MODULE_ALIAS("platform:rtc-bq4802"); | ||
| 209 | |||
| 210 | static struct platform_driver bq4802_driver = { | ||
| 211 | .driver = { | ||
| 212 | .name = "rtc-bq4802", | ||
| 213 | .owner = THIS_MODULE, | ||
| 214 | }, | ||
| 215 | .probe = bq4802_probe, | ||
| 216 | .remove = __devexit_p(bq4802_remove), | ||
| 217 | }; | ||
| 218 | |||
| 219 | static int __init bq4802_init(void) | ||
| 220 | { | ||
| 221 | return platform_driver_register(&bq4802_driver); | ||
| 222 | } | ||
| 223 | |||
| 224 | static void __exit bq4802_exit(void) | ||
| 225 | { | ||
| 226 | platform_driver_unregister(&bq4802_driver); | ||
| 227 | } | ||
| 228 | |||
| 229 | module_init(bq4802_init); | ||
| 230 | module_exit(bq4802_exit); | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b184367637d0..b23af0c2a869 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -636,7 +636,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 636 | */ | 636 | */ |
| 637 | #if defined(CONFIG_ATARI) | 637 | #if defined(CONFIG_ATARI) |
| 638 | address_space = 64; | 638 | address_space = 64; |
| 639 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | 639 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) |
| 640 | address_space = 128; | 640 | address_space = 128; |
| 641 | #else | 641 | #else |
| 642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
| @@ -699,7 +699,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 699 | /* FIXME teach the alarm code how to handle binary mode; | 699 | /* FIXME teach the alarm code how to handle binary mode; |
| 700 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 700 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
| 701 | */ | 701 | */ |
| 702 | if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) { | 702 | if (is_valid_irq(rtc_irq) && |
| 703 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | ||
| 703 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | 704 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); |
| 704 | retval = -ENXIO; | 705 | retval = -ENXIO; |
| 705 | goto cleanup1; | 706 | goto cleanup1; |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 013e6c103b9c..ce4eff6a8d51 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
| @@ -24,8 +24,9 @@ | |||
| 24 | #define NO_IRQ (-1) | 24 | #define NO_IRQ (-1) |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | #define M48T59_READ(reg) pdata->read_byte(dev, reg) | 27 | #define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg)) |
| 28 | #define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) | 28 | #define M48T59_WRITE(val, reg) \ |
| 29 | (pdata->write_byte(dev, pdata->offset + reg, val)) | ||
| 29 | 30 | ||
| 30 | #define M48T59_SET_BITS(mask, reg) \ | 31 | #define M48T59_SET_BITS(mask, reg) \ |
| 31 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) | 32 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) |
| @@ -34,7 +35,6 @@ | |||
| 34 | 35 | ||
| 35 | struct m48t59_private { | 36 | struct m48t59_private { |
| 36 | void __iomem *ioaddr; | 37 | void __iomem *ioaddr; |
| 37 | unsigned int size; /* iomem size */ | ||
| 38 | int irq; | 38 | int irq; |
| 39 | struct rtc_device *rtc; | 39 | struct rtc_device *rtc; |
| 40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ | 40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ |
| @@ -82,7 +82,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); | 82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); |
| 83 | 83 | ||
| 84 | val = M48T59_READ(M48T59_WDAY); | 84 | val = M48T59_READ(M48T59_WDAY); |
| 85 | if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | 85 | if ((pdata->type == M48T59RTC_TYPE_M48T59) && |
| 86 | (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | ||
| 86 | dev_dbg(dev, "Century bit is enabled\n"); | 87 | dev_dbg(dev, "Century bit is enabled\n"); |
| 87 | tm->tm_year += 100; /* one century */ | 88 | tm->tm_year += 100; /* one century */ |
| 88 | } | 89 | } |
| @@ -126,7 +127,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 126 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); | 127 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); |
| 127 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); | 128 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); |
| 128 | 129 | ||
| 129 | if (tm->tm_year/100) | 130 | if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100)) |
| 130 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); | 131 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); |
| 131 | val |= (BIN2BCD(tm->tm_wday) & 0x07); | 132 | val |= (BIN2BCD(tm->tm_wday) & 0x07); |
| 132 | M48T59_WRITE(val, M48T59_WDAY); | 133 | M48T59_WRITE(val, M48T59_WDAY); |
| @@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = { | |||
| 310 | .proc = m48t59_rtc_proc, | 311 | .proc = m48t59_rtc_proc, |
| 311 | }; | 312 | }; |
| 312 | 313 | ||
| 314 | static const struct rtc_class_ops m48t02_rtc_ops = { | ||
| 315 | .read_time = m48t59_rtc_read_time, | ||
| 316 | .set_time = m48t59_rtc_set_time, | ||
| 317 | }; | ||
| 318 | |||
| 313 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 319 | static ssize_t m48t59_nvram_read(struct kobject *kobj, |
| 314 | struct bin_attribute *bin_attr, | 320 | struct bin_attribute *bin_attr, |
| 315 | char *buf, loff_t pos, size_t size) | 321 | char *buf, loff_t pos, size_t size) |
| @@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
| 321 | ssize_t cnt = 0; | 327 | ssize_t cnt = 0; |
| 322 | unsigned long flags; | 328 | unsigned long flags; |
| 323 | 329 | ||
| 324 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 330 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
| 325 | spin_lock_irqsave(&m48t59->lock, flags); | 331 | spin_lock_irqsave(&m48t59->lock, flags); |
| 326 | *buf++ = M48T59_READ(cnt); | 332 | *buf++ = M48T59_READ(cnt); |
| 327 | spin_unlock_irqrestore(&m48t59->lock, flags); | 333 | spin_unlock_irqrestore(&m48t59->lock, flags); |
| @@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, | |||
| 341 | ssize_t cnt = 0; | 347 | ssize_t cnt = 0; |
| 342 | unsigned long flags; | 348 | unsigned long flags; |
| 343 | 349 | ||
| 344 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 350 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
| 345 | spin_lock_irqsave(&m48t59->lock, flags); | 351 | spin_lock_irqsave(&m48t59->lock, flags); |
| 346 | M48T59_WRITE(*buf++, cnt); | 352 | M48T59_WRITE(*buf++, cnt); |
| 347 | spin_unlock_irqrestore(&m48t59->lock, flags); | 353 | spin_unlock_irqrestore(&m48t59->lock, flags); |
| @@ -358,7 +364,6 @@ static struct bin_attribute m48t59_nvram_attr = { | |||
| 358 | }, | 364 | }, |
| 359 | .read = m48t59_nvram_read, | 365 | .read = m48t59_nvram_read, |
| 360 | .write = m48t59_nvram_write, | 366 | .write = m48t59_nvram_write, |
| 361 | .size = M48T59_NVRAM_SIZE, | ||
| 362 | }; | 367 | }; |
| 363 | 368 | ||
| 364 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | 369 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) |
| @@ -367,6 +372,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 367 | struct m48t59_private *m48t59 = NULL; | 372 | struct m48t59_private *m48t59 = NULL; |
| 368 | struct resource *res; | 373 | struct resource *res; |
| 369 | int ret = -ENOMEM; | 374 | int ret = -ENOMEM; |
| 375 | char *name; | ||
| 376 | const struct rtc_class_ops *ops; | ||
| 370 | 377 | ||
| 371 | /* This chip could be memory-mapped or I/O-mapped */ | 378 | /* This chip could be memory-mapped or I/O-mapped */ |
| 372 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 379 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -391,6 +398,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 391 | /* Ensure we only kmalloc platform data once */ | 398 | /* Ensure we only kmalloc platform data once */ |
| 392 | pdev->dev.platform_data = pdata; | 399 | pdev->dev.platform_data = pdata; |
| 393 | } | 400 | } |
| 401 | if (!pdata->type) | ||
| 402 | pdata->type = M48T59RTC_TYPE_M48T59; | ||
| 394 | 403 | ||
| 395 | /* Try to use the generic memory read/write ops */ | 404 | /* Try to use the generic memory read/write ops */ |
| 396 | if (!pdata->write_byte) | 405 | if (!pdata->write_byte) |
| @@ -403,10 +412,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 403 | if (!m48t59) | 412 | if (!m48t59) |
| 404 | return -ENOMEM; | 413 | return -ENOMEM; |
| 405 | 414 | ||
| 406 | m48t59->size = res->end - res->start + 1; | 415 | m48t59->ioaddr = pdata->ioaddr; |
| 407 | m48t59->ioaddr = ioremap(res->start, m48t59->size); | 416 | |
| 408 | if (!m48t59->ioaddr) | 417 | if (!m48t59->ioaddr) { |
| 409 | goto out; | 418 | /* ioaddr not mapped externally */ |
| 419 | m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); | ||
| 420 | if (!m48t59->ioaddr) | ||
| 421 | goto out; | ||
| 422 | } | ||
| 410 | 423 | ||
| 411 | /* Try to get irq number. We also can work in | 424 | /* Try to get irq number. We also can work in |
| 412 | * the mode without IRQ. | 425 | * the mode without IRQ. |
| @@ -421,14 +434,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 421 | if (ret) | 434 | if (ret) |
| 422 | goto out; | 435 | goto out; |
| 423 | } | 436 | } |
| 437 | switch (pdata->type) { | ||
| 438 | case M48T59RTC_TYPE_M48T59: | ||
| 439 | name = "m48t59"; | ||
| 440 | ops = &m48t59_rtc_ops; | ||
| 441 | pdata->offset = 0x1ff0; | ||
| 442 | break; | ||
| 443 | case M48T59RTC_TYPE_M48T02: | ||
| 444 | name = "m48t02"; | ||
| 445 | ops = &m48t02_rtc_ops; | ||
| 446 | pdata->offset = 0x7f0; | ||
| 447 | break; | ||
| 448 | case M48T59RTC_TYPE_M48T08: | ||
| 449 | name = "m48t08"; | ||
| 450 | ops = &m48t02_rtc_ops; | ||
| 451 | pdata->offset = 0x1ff0; | ||
| 452 | break; | ||
| 453 | default: | ||
| 454 | dev_err(&pdev->dev, "Unknown RTC type\n"); | ||
| 455 | ret = -ENODEV; | ||
| 456 | goto out; | ||
| 457 | } | ||
| 424 | 458 | ||
| 425 | m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, | 459 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
| 426 | &m48t59_rtc_ops, THIS_MODULE); | ||
| 427 | if (IS_ERR(m48t59->rtc)) { | 460 | if (IS_ERR(m48t59->rtc)) { |
| 428 | ret = PTR_ERR(m48t59->rtc); | 461 | ret = PTR_ERR(m48t59->rtc); |
| 429 | goto out; | 462 | goto out; |
| 430 | } | 463 | } |
| 431 | 464 | ||
| 465 | m48t59_nvram_attr.size = pdata->offset; | ||
| 466 | |||
| 432 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 467 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
| 433 | if (ret) | 468 | if (ret) |
| 434 | goto out; | 469 | goto out; |
| @@ -452,11 +487,12 @@ out: | |||
| 452 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) | 487 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) |
| 453 | { | 488 | { |
| 454 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); | 489 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); |
| 490 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; | ||
| 455 | 491 | ||
| 456 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 492 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
| 457 | if (!IS_ERR(m48t59->rtc)) | 493 | if (!IS_ERR(m48t59->rtc)) |
| 458 | rtc_device_unregister(m48t59->rtc); | 494 | rtc_device_unregister(m48t59->rtc); |
| 459 | if (m48t59->ioaddr) | 495 | if (m48t59->ioaddr && !pdata->ioaddr) |
| 460 | iounmap(m48t59->ioaddr); | 496 | iounmap(m48t59->ioaddr); |
| 461 | if (m48t59->irq != NO_IRQ) | 497 | if (m48t59->irq != NO_IRQ) |
| 462 | free_irq(m48t59->irq, &pdev->dev); | 498 | free_irq(m48t59->irq, &pdev->dev); |
| @@ -491,5 +527,5 @@ module_init(m48t59_rtc_init); | |||
| 491 | module_exit(m48t59_rtc_exit); | 527 | module_exit(m48t59_rtc_exit); |
| 492 | 528 | ||
| 493 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); | 529 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
| 494 | MODULE_DESCRIPTION("M48T59 RTC driver"); | 530 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
| 495 | MODULE_LICENSE("GPL"); | 531 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c new file mode 100644 index 000000000000..7ccb0dd700af --- /dev/null +++ b/drivers/rtc/rtc-starfire.c | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | /* rtc-starfire.c: Starfire platform RTC driver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/time.h> | ||
| 10 | #include <linux/rtc.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | |||
| 13 | #include <asm/oplib.h> | ||
| 14 | |||
| 15 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 16 | MODULE_DESCRIPTION("Starfire RTC driver"); | ||
| 17 | MODULE_LICENSE("GPL"); | ||
| 18 | |||
| 19 | struct starfire_rtc { | ||
| 20 | struct rtc_device *rtc; | ||
| 21 | spinlock_t lock; | ||
| 22 | }; | ||
| 23 | |||
| 24 | static u32 starfire_get_time(void) | ||
| 25 | { | ||
| 26 | static char obp_gettod[32]; | ||
| 27 | static u32 unix_tod; | ||
| 28 | |||
| 29 | sprintf(obp_gettod, "h# %08x unix-gettod", | ||
| 30 | (unsigned int) (long) &unix_tod); | ||
| 31 | prom_feval(obp_gettod); | ||
| 32 | |||
| 33 | return unix_tod; | ||
| 34 | } | ||
| 35 | |||
| 36 | static int starfire_read_time(struct device *dev, struct rtc_time *tm) | ||
| 37 | { | ||
| 38 | struct starfire_rtc *p = dev_get_drvdata(dev); | ||
| 39 | unsigned long flags, secs; | ||
| 40 | |||
| 41 | spin_lock_irqsave(&p->lock, flags); | ||
| 42 | secs = starfire_get_time(); | ||
| 43 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 44 | |||
| 45 | rtc_time_to_tm(secs, tm); | ||
| 46 | |||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int starfire_set_time(struct device *dev, struct rtc_time *tm) | ||
| 51 | { | ||
| 52 | unsigned long secs; | ||
| 53 | int err; | ||
| 54 | |||
| 55 | err = rtc_tm_to_time(tm, &secs); | ||
| 56 | if (err) | ||
| 57 | return err; | ||
| 58 | |||
| 59 | /* Do nothing, time is set using the service processor | ||
| 60 | * console on this platform. | ||
| 61 | */ | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static const struct rtc_class_ops starfire_rtc_ops = { | ||
| 66 | .read_time = starfire_read_time, | ||
| 67 | .set_time = starfire_set_time, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static int __devinit starfire_rtc_probe(struct platform_device *pdev) | ||
| 71 | { | ||
| 72 | struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 73 | |||
| 74 | if (!p) | ||
| 75 | return -ENOMEM; | ||
| 76 | |||
| 77 | spin_lock_init(&p->lock); | ||
| 78 | |||
| 79 | p->rtc = rtc_device_register("starfire", &pdev->dev, | ||
| 80 | &starfire_rtc_ops, THIS_MODULE); | ||
| 81 | if (IS_ERR(p->rtc)) { | ||
| 82 | int err = PTR_ERR(p->rtc); | ||
| 83 | kfree(p); | ||
| 84 | return err; | ||
| 85 | } | ||
| 86 | platform_set_drvdata(pdev, p); | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int __devexit starfire_rtc_remove(struct platform_device *pdev) | ||
| 91 | { | ||
| 92 | struct starfire_rtc *p = platform_get_drvdata(pdev); | ||
| 93 | |||
| 94 | rtc_device_unregister(p->rtc); | ||
| 95 | kfree(p); | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static struct platform_driver starfire_rtc_driver = { | ||
| 101 | .driver = { | ||
| 102 | .name = "rtc-starfire", | ||
| 103 | .owner = THIS_MODULE, | ||
| 104 | }, | ||
| 105 | .probe = starfire_rtc_probe, | ||
| 106 | .remove = __devexit_p(starfire_rtc_remove), | ||
| 107 | }; | ||
| 108 | |||
| 109 | static int __init starfire_rtc_init(void) | ||
| 110 | { | ||
| 111 | return platform_driver_register(&starfire_rtc_driver); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void __exit starfire_rtc_exit(void) | ||
| 115 | { | ||
| 116 | platform_driver_unregister(&starfire_rtc_driver); | ||
| 117 | } | ||
| 118 | |||
| 119 | module_init(starfire_rtc_init); | ||
| 120 | module_exit(starfire_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c new file mode 100644 index 000000000000..2012ccbb4a53 --- /dev/null +++ b/drivers/rtc/rtc-sun4v.c | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/time.h> | ||
| 11 | #include <linux/rtc.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | |||
| 14 | #include <asm/hypervisor.h> | ||
| 15 | |||
| 16 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 17 | MODULE_DESCRIPTION("SUN4V RTC driver"); | ||
| 18 | MODULE_LICENSE("GPL"); | ||
| 19 | |||
| 20 | struct sun4v_rtc { | ||
| 21 | struct rtc_device *rtc; | ||
| 22 | spinlock_t lock; | ||
| 23 | }; | ||
| 24 | |||
| 25 | static unsigned long hypervisor_get_time(void) | ||
| 26 | { | ||
| 27 | unsigned long ret, time; | ||
| 28 | int retries = 10000; | ||
| 29 | |||
| 30 | retry: | ||
| 31 | ret = sun4v_tod_get(&time); | ||
| 32 | if (ret == HV_EOK) | ||
| 33 | return time; | ||
| 34 | if (ret == HV_EWOULDBLOCK) { | ||
| 35 | if (--retries > 0) { | ||
| 36 | udelay(100); | ||
| 37 | goto retry; | ||
| 38 | } | ||
| 39 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int sun4v_read_time(struct device *dev, struct rtc_time *tm) | ||
| 47 | { | ||
| 48 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
| 49 | unsigned long flags, secs; | ||
| 50 | |||
| 51 | spin_lock_irqsave(&p->lock, flags); | ||
| 52 | secs = hypervisor_get_time(); | ||
| 53 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 54 | |||
| 55 | rtc_time_to_tm(secs, tm); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static int hypervisor_set_time(unsigned long secs) | ||
| 61 | { | ||
| 62 | unsigned long ret; | ||
| 63 | int retries = 10000; | ||
| 64 | |||
| 65 | retry: | ||
| 66 | ret = sun4v_tod_set(secs); | ||
| 67 | if (ret == HV_EOK) | ||
| 68 | return 0; | ||
| 69 | if (ret == HV_EWOULDBLOCK) { | ||
| 70 | if (--retries > 0) { | ||
| 71 | udelay(100); | ||
| 72 | goto retry; | ||
| 73 | } | ||
| 74 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | ||
| 75 | return -EAGAIN; | ||
| 76 | } | ||
| 77 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | ||
| 78 | return -EOPNOTSUPP; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int sun4v_set_time(struct device *dev, struct rtc_time *tm) | ||
| 82 | { | ||
| 83 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
| 84 | unsigned long flags, secs; | ||
| 85 | int err; | ||
| 86 | |||
| 87 | err = rtc_tm_to_time(tm, &secs); | ||
| 88 | if (err) | ||
| 89 | return err; | ||
| 90 | |||
| 91 | spin_lock_irqsave(&p->lock, flags); | ||
| 92 | err = hypervisor_set_time(secs); | ||
| 93 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 94 | |||
| 95 | return err; | ||
| 96 | } | ||
| 97 | |||
| 98 | static const struct rtc_class_ops sun4v_rtc_ops = { | ||
| 99 | .read_time = sun4v_read_time, | ||
| 100 | .set_time = sun4v_set_time, | ||
| 101 | }; | ||
| 102 | |||
| 103 | static int __devinit sun4v_rtc_probe(struct platform_device *pdev) | ||
| 104 | { | ||
| 105 | struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 106 | |||
| 107 | if (!p) | ||
| 108 | return -ENOMEM; | ||
| 109 | |||
| 110 | spin_lock_init(&p->lock); | ||
| 111 | |||
| 112 | p->rtc = rtc_device_register("sun4v", &pdev->dev, | ||
| 113 | &sun4v_rtc_ops, THIS_MODULE); | ||
| 114 | if (IS_ERR(p->rtc)) { | ||
| 115 | int err = PTR_ERR(p->rtc); | ||
| 116 | kfree(p); | ||
| 117 | return err; | ||
| 118 | } | ||
| 119 | platform_set_drvdata(pdev, p); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int __devexit sun4v_rtc_remove(struct platform_device *pdev) | ||
| 124 | { | ||
| 125 | struct sun4v_rtc *p = platform_get_drvdata(pdev); | ||
| 126 | |||
| 127 | rtc_device_unregister(p->rtc); | ||
| 128 | kfree(p); | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static struct platform_driver sun4v_rtc_driver = { | ||
| 134 | .driver = { | ||
| 135 | .name = "rtc-sun4v", | ||
| 136 | .owner = THIS_MODULE, | ||
| 137 | }, | ||
| 138 | .probe = sun4v_rtc_probe, | ||
| 139 | .remove = __devexit_p(sun4v_rtc_remove), | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int __init sun4v_rtc_init(void) | ||
| 143 | { | ||
| 144 | return platform_driver_register(&sun4v_rtc_driver); | ||
| 145 | } | ||
| 146 | |||
| 147 | static void __exit sun4v_rtc_exit(void) | ||
| 148 | { | ||
| 149 | platform_driver_unregister(&sun4v_rtc_driver); | ||
| 150 | } | ||
| 151 | |||
| 152 | module_init(sun4v_rtc_init); | ||
| 153 | module_exit(sun4v_rtc_exit); | ||
diff --git a/drivers/sbus/Makefile b/drivers/sbus/Makefile index 7b1d24d95308..e94dc25805f9 100644 --- a/drivers/sbus/Makefile +++ b/drivers/sbus/Makefile | |||
| @@ -2,8 +2,4 @@ | |||
| 2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | ifneq ($(ARCH),m68k) | ||
| 6 | obj-y := sbus.o dvma.o | ||
| 7 | endif | ||
| 8 | |||
| 9 | obj-$(CONFIG_SBUSCHAR) += char/ | 5 | obj-$(CONFIG_SBUSCHAR) += char/ |
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index 400c65bfb8c7..73cde85d04d8 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig | |||
| @@ -13,16 +13,6 @@ config SUN_OPENPROMIO | |||
| 13 | 13 | ||
| 14 | If unsure, say Y. | 14 | If unsure, say Y. |
| 15 | 15 | ||
| 16 | config SUN_MOSTEK_RTC | ||
| 17 | tristate "Mostek real time clock support" | ||
| 18 | depends on SPARC32 | ||
| 19 | help | ||
| 20 | The Mostek RTC chip is used on all known Sun computers except | ||
| 21 | some JavaStations. For a JavaStation you need to say Y both here | ||
| 22 | and to "Enhanced Real Time Clock Support". | ||
| 23 | |||
| 24 | Say Y here unless you are building a special purpose kernel. | ||
| 25 | |||
| 26 | config OBP_FLASH | 16 | config OBP_FLASH |
| 27 | tristate "OBP Flash Device support" | 17 | tristate "OBP Flash Device support" |
| 28 | depends on SPARC64 | 18 | depends on SPARC64 |
| @@ -30,26 +20,9 @@ config OBP_FLASH | |||
| 30 | The OpenBoot PROM on Ultra systems is flashable. If you want to be | 20 | The OpenBoot PROM on Ultra systems is flashable. If you want to be |
| 31 | able to upgrade the OBP firmware, say Y here. | 21 | able to upgrade the OBP firmware, say Y here. |
| 32 | 22 | ||
| 33 | config SUN_BPP | ||
| 34 | tristate "Bidirectional parallel port support (OBSOLETE)" | ||
| 35 | depends on EXPERIMENTAL | ||
| 36 | help | ||
| 37 | Say Y here to support Sun's obsolete variant of IEEE1284 | ||
| 38 | bidirectional parallel port protocol as /dev/bppX. Can be built on | ||
| 39 | x86 machines. | ||
| 40 | |||
| 41 | config SUN_VIDEOPIX | ||
| 42 | tristate "Videopix Frame Grabber (EXPERIMENTAL)" | ||
| 43 | depends on EXPERIMENTAL && (BROKEN || !64BIT) | ||
| 44 | help | ||
| 45 | Say Y here to support the Videopix Frame Grabber from Sun | ||
| 46 | Microsystems, commonly found on SPARCstations. This card, which is | ||
| 47 | based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and | ||
| 48 | SVIDEO signals. | ||
| 49 | |||
| 50 | config TADPOLE_TS102_UCTRL | 23 | config TADPOLE_TS102_UCTRL |
| 51 | tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" | 24 | tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" |
| 52 | depends on EXPERIMENTAL && SPARC32 | 25 | depends on EXPERIMENTAL |
| 53 | help | 26 | help |
| 54 | Say Y here to directly support the TS102 Microcontroller interface | 27 | Say Y here to directly support the TS102 Microcontroller interface |
| 55 | on the Tadpole Sparcbook 3. This device handles power-management | 28 | on the Tadpole Sparcbook 3. This device handles power-management |
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index 7ab060e9a5fe..78b6183c9866 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile | |||
| @@ -7,18 +7,12 @@ | |||
| 7 | # Rewritten to use lists instead of if-statements. | 7 | # Rewritten to use lists instead of if-statements. |
| 8 | # | 8 | # |
| 9 | 9 | ||
| 10 | vfc-objs := vfc_dev.o vfc_i2c.o | ||
| 11 | bbc-objs := bbc_i2c.o bbc_envctrl.o | 10 | bbc-objs := bbc_i2c.o bbc_envctrl.o |
| 12 | 11 | ||
| 13 | obj-$(CONFIG_ENVCTRL) += envctrl.o | 12 | obj-$(CONFIG_ENVCTRL) += envctrl.o |
| 14 | obj-$(CONFIG_DISPLAY7SEG) += display7seg.o | 13 | obj-$(CONFIG_DISPLAY7SEG) += display7seg.o |
| 15 | obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwatchdog.o | ||
| 16 | obj-$(CONFIG_WATCHDOG_RIO) += riowatchdog.o | ||
| 17 | obj-$(CONFIG_OBP_FLASH) += flash.o | 14 | obj-$(CONFIG_OBP_FLASH) += flash.o |
| 18 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o | 15 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o |
| 19 | obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o | ||
| 20 | obj-$(CONFIG_SUN_BPP) += bpp.o | ||
| 21 | obj-$(CONFIG_SUN_VIDEOPIX) += vfc.o | ||
| 22 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o | 16 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o |
| 23 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o | 17 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o |
| 24 | obj-$(CONFIG_BBC_I2C) += bbc.o | 18 | obj-$(CONFIG_BBC_I2C) += bbc.o |
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 0bde26989a23..15dab96d05e3 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c | |||
| @@ -1,15 +1,15 @@ | |||
| 1 | /* $Id: bbc_envctrl.c,v 1.4 2001/04/06 16:48:08 davem Exp $ | 1 | /* bbc_envctrl.c: UltraSPARC-III environment control driver. |
| 2 | * bbc_envctrl.c: UltraSPARC-III environment control driver. | ||
| 3 | * | 2 | * |
| 4 | * Copyright (C) 2001 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) |
| 5 | */ | 4 | */ |
| 6 | 5 | ||
| 7 | #include <linux/kthread.h> | 6 | #include <linux/kthread.h> |
| 8 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
| 9 | #include <linux/kmod.h> | 8 | #include <linux/kmod.h> |
| 10 | #include <linux/reboot.h> | 9 | #include <linux/reboot.h> |
| 10 | #include <linux/of.h> | ||
| 11 | #include <linux/of_device.h> | ||
| 11 | #include <asm/oplib.h> | 12 | #include <asm/oplib.h> |
| 12 | #include <asm/ebus.h> | ||
| 13 | 13 | ||
| 14 | #include "bbc_i2c.h" | 14 | #include "bbc_i2c.h" |
| 15 | #include "max1617.h" | 15 | #include "max1617.h" |
| @@ -75,43 +75,8 @@ static struct temp_limits amb_temp_limits[2] = { | |||
| 75 | { 65, 55, 40, 5, -5, -10 }, | 75 | { 65, 55, 40, 5, -5, -10 }, |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; | 78 | static LIST_HEAD(all_temps); |
| 79 | 79 | static LIST_HEAD(all_fans); | |
| 80 | struct bbc_cpu_temperature { | ||
| 81 | struct bbc_cpu_temperature *next; | ||
| 82 | |||
| 83 | struct bbc_i2c_client *client; | ||
| 84 | int index; | ||
| 85 | |||
| 86 | /* Current readings, and history. */ | ||
| 87 | s8 curr_cpu_temp; | ||
| 88 | s8 curr_amb_temp; | ||
| 89 | s8 prev_cpu_temp; | ||
| 90 | s8 prev_amb_temp; | ||
| 91 | s8 avg_cpu_temp; | ||
| 92 | s8 avg_amb_temp; | ||
| 93 | |||
| 94 | int sample_tick; | ||
| 95 | |||
| 96 | enum fan_action fan_todo[2]; | ||
| 97 | #define FAN_AMBIENT 0 | ||
| 98 | #define FAN_CPU 1 | ||
| 99 | }; | ||
| 100 | |||
| 101 | struct bbc_cpu_temperature *all_bbc_temps; | ||
| 102 | |||
| 103 | struct bbc_fan_control { | ||
| 104 | struct bbc_fan_control *next; | ||
| 105 | |||
| 106 | struct bbc_i2c_client *client; | ||
| 107 | int index; | ||
| 108 | |||
| 109 | int psupply_fan_on; | ||
| 110 | int cpu_fan_speed; | ||
| 111 | int system_fan_speed; | ||
| 112 | }; | ||
| 113 | |||
| 114 | struct bbc_fan_control *all_bbc_fans; | ||
| 115 | 80 | ||
| 116 | #define CPU_FAN_REG 0xf0 | 81 | #define CPU_FAN_REG 0xf0 |
| 117 | #define SYS_FAN_REG 0xf2 | 82 | #define SYS_FAN_REG 0xf2 |
| @@ -330,7 +295,7 @@ static enum fan_action prioritize_fan_action(int which_fan) | |||
| 330 | * recommend we do, and perform that action on all the | 295 | * recommend we do, and perform that action on all the |
| 331 | * fans. | 296 | * fans. |
| 332 | */ | 297 | */ |
| 333 | for (tp = all_bbc_temps; tp; tp = tp->next) { | 298 | list_for_each_entry(tp, &all_temps, glob_list) { |
| 334 | if (tp->fan_todo[which_fan] == FAN_FULLBLAST) { | 299 | if (tp->fan_todo[which_fan] == FAN_FULLBLAST) { |
| 335 | decision = FAN_FULLBLAST; | 300 | decision = FAN_FULLBLAST; |
| 336 | break; | 301 | break; |
| @@ -439,7 +404,7 @@ static void fans_full_blast(void) | |||
| 439 | /* Since we will not be monitoring things anymore, put | 404 | /* Since we will not be monitoring things anymore, put |
| 440 | * the fans on full blast. | 405 | * the fans on full blast. |
| 441 | */ | 406 | */ |
| 442 | for (fp = all_bbc_fans; fp; fp = fp->next) { | 407 | list_for_each_entry(fp, &all_fans, glob_list) { |
| 443 | fp->cpu_fan_speed = FAN_SPEED_MAX; | 408 | fp->cpu_fan_speed = FAN_SPEED_MAX; |
| 444 | fp->system_fan_speed = FAN_SPEED_MAX; | 409 | fp->system_fan_speed = FAN_SPEED_MAX; |
| 445 | fp->psupply_fan_on = 1; | 410 | fp->psupply_fan_on = 1; |
| @@ -463,11 +428,11 @@ static int kenvctrld(void *__unused) | |||
| 463 | if (kthread_should_stop()) | 428 | if (kthread_should_stop()) |
| 464 | break; | 429 | break; |
| 465 | 430 | ||
| 466 | for (tp = all_bbc_temps; tp; tp = tp->next) { | 431 | list_for_each_entry(tp, &all_temps, glob_list) { |
| 467 | get_current_temps(tp); | 432 | get_current_temps(tp); |
| 468 | analyze_temps(tp, &last_warning_jiffies); | 433 | analyze_temps(tp, &last_warning_jiffies); |
| 469 | } | 434 | } |
| 470 | for (fp = all_bbc_fans; fp; fp = fp->next) | 435 | list_for_each_entry(fp, &all_fans, glob_list) |
| 471 | maybe_new_fan_speeds(fp); | 436 | maybe_new_fan_speeds(fp); |
| 472 | } | 437 | } |
| 473 | printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n"); | 438 | printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n"); |
| @@ -477,7 +442,8 @@ static int kenvctrld(void *__unused) | |||
| 477 | return 0; | 442 | return 0; |
| 478 | } | 443 | } |
| 479 | 444 | ||
| 480 | static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | 445 | static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, |
| 446 | int temp_idx) | ||
| 481 | { | 447 | { |
| 482 | struct bbc_cpu_temperature *tp; | 448 | struct bbc_cpu_temperature *tp; |
| 483 | 449 | ||
| @@ -485,20 +451,17 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | |||
| 485 | if (!tp) | 451 | if (!tp) |
| 486 | return; | 452 | return; |
| 487 | 453 | ||
| 488 | tp->client = bbc_i2c_attach(echild); | 454 | tp->client = bbc_i2c_attach(bp, op); |
| 489 | if (!tp->client) { | 455 | if (!tp->client) { |
| 490 | kfree(tp); | 456 | kfree(tp); |
| 491 | return; | 457 | return; |
| 492 | } | 458 | } |
| 493 | 459 | ||
| 460 | |||
| 494 | tp->index = temp_idx; | 461 | tp->index = temp_idx; |
| 495 | { | 462 | |
| 496 | struct bbc_cpu_temperature **tpp = &all_bbc_temps; | 463 | list_add(&tp->glob_list, &all_temps); |
| 497 | while (*tpp) | 464 | list_add(&tp->bp_list, &bp->temps); |
| 498 | tpp = &((*tpp)->next); | ||
| 499 | tp->next = NULL; | ||
| 500 | *tpp = tp; | ||
| 501 | } | ||
| 502 | 465 | ||
| 503 | /* Tell it to convert once every 5 seconds, clear all cfg | 466 | /* Tell it to convert once every 5 seconds, clear all cfg |
| 504 | * bits. | 467 | * bits. |
| @@ -524,7 +487,8 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | |||
| 524 | tp->fan_todo[FAN_CPU] = FAN_SAME; | 487 | tp->fan_todo[FAN_CPU] = FAN_SAME; |
| 525 | } | 488 | } |
| 526 | 489 | ||
| 527 | static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | 490 | static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, |
| 491 | int fan_idx) | ||
| 528 | { | 492 | { |
| 529 | struct bbc_fan_control *fp; | 493 | struct bbc_fan_control *fp; |
| 530 | 494 | ||
| @@ -532,7 +496,7 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | |||
| 532 | if (!fp) | 496 | if (!fp) |
| 533 | return; | 497 | return; |
| 534 | 498 | ||
| 535 | fp->client = bbc_i2c_attach(echild); | 499 | fp->client = bbc_i2c_attach(bp, op); |
| 536 | if (!fp->client) { | 500 | if (!fp->client) { |
| 537 | kfree(fp); | 501 | kfree(fp); |
| 538 | return; | 502 | return; |
| @@ -540,13 +504,8 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | |||
| 540 | 504 | ||
| 541 | fp->index = fan_idx; | 505 | fp->index = fan_idx; |
| 542 | 506 | ||
| 543 | { | 507 | list_add(&fp->glob_list, &all_fans); |
| 544 | struct bbc_fan_control **fpp = &all_bbc_fans; | 508 | list_add(&fp->bp_list, &bp->fans); |
| 545 | while (*fpp) | ||
| 546 | fpp = &((*fpp)->next); | ||
| 547 | fp->next = NULL; | ||
| 548 | *fpp = fp; | ||
| 549 | } | ||
| 550 | 509 | ||
| 551 | /* The i2c device controlling the fans is write-only. | 510 | /* The i2c device controlling the fans is write-only. |
| 552 | * So the only way to keep track of the current power | 511 | * So the only way to keep track of the current power |
| @@ -563,18 +522,18 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | |||
| 563 | set_fan_speeds(fp); | 522 | set_fan_speeds(fp); |
| 564 | } | 523 | } |
| 565 | 524 | ||
| 566 | int bbc_envctrl_init(void) | 525 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) |
| 567 | { | 526 | { |
| 568 | struct linux_ebus_child *echild; | 527 | struct of_device *op; |
| 569 | int temp_index = 0; | 528 | int temp_index = 0; |
| 570 | int fan_index = 0; | 529 | int fan_index = 0; |
| 571 | int devidx = 0; | 530 | int devidx = 0; |
| 572 | 531 | ||
| 573 | while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { | 532 | while ((op = bbc_i2c_getdev(bp, devidx++)) != NULL) { |
| 574 | if (!strcmp(echild->prom_node->name, "temperature")) | 533 | if (!strcmp(op->node->name, "temperature")) |
| 575 | attach_one_temp(echild, temp_index++); | 534 | attach_one_temp(bp, op, temp_index++); |
| 576 | if (!strcmp(echild->prom_node->name, "fan-control")) | 535 | if (!strcmp(op->node->name, "fan-control")) |
| 577 | attach_one_fan(echild, fan_index++); | 536 | attach_one_fan(bp, op, fan_index++); |
| 578 | } | 537 | } |
| 579 | if (temp_index != 0 && fan_index != 0) { | 538 | if (temp_index != 0 && fan_index != 0) { |
| 580 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); | 539 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
| @@ -597,26 +556,22 @@ static void destroy_one_fan(struct bbc_fan_control *fp) | |||
| 597 | kfree(fp); | 556 | kfree(fp); |
| 598 | } | 557 | } |
| 599 | 558 | ||
| 600 | void bbc_envctrl_cleanup(void) | 559 | void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) |
| 601 | { | 560 | { |
| 602 | struct bbc_cpu_temperature *tp; | 561 | struct bbc_cpu_temperature *tp, *tpos; |
| 603 | struct bbc_fan_control *fp; | 562 | struct bbc_fan_control *fp, *fpos; |
| 604 | 563 | ||
| 605 | kthread_stop(kenvctrld_task); | 564 | kthread_stop(kenvctrld_task); |
| 606 | 565 | ||
| 607 | tp = all_bbc_temps; | 566 | list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { |
| 608 | while (tp != NULL) { | 567 | list_del(&tp->bp_list); |
| 609 | struct bbc_cpu_temperature *next = tp->next; | 568 | list_del(&tp->glob_list); |
| 610 | destroy_one_temp(tp); | 569 | destroy_one_temp(tp); |
| 611 | tp = next; | ||
| 612 | } | 570 | } |
| 613 | all_bbc_temps = NULL; | ||
| 614 | 571 | ||
| 615 | fp = all_bbc_fans; | 572 | list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) { |
| 616 | while (fp != NULL) { | 573 | list_del(&fp->bp_list); |
| 617 | struct bbc_fan_control *next = fp->next; | 574 | list_del(&fp->glob_list); |
| 618 | destroy_one_fan(fp); | 575 | destroy_one_fan(fp); |
| 619 | fp = next; | ||
| 620 | } | 576 | } |
| 621 | all_bbc_fans = NULL; | ||
| 622 | } | 577 | } |
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index ac8ef2ce07fb..f08e169ba1b5 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c | |||
| @@ -1,8 +1,7 @@ | |||
| 1 | /* $Id: bbc_i2c.c,v 1.2 2001/04/02 09:59:08 davem Exp $ | 1 | /* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III |
| 2 | * bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III | ||
| 3 | * platforms. | 2 | * platforms. |
| 4 | * | 3 | * |
| 5 | * Copyright (C) 2001 David S. Miller (davem@redhat.com) | 4 | * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) |
| 6 | */ | 5 | */ |
| 7 | 6 | ||
| 8 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| @@ -14,9 +13,8 @@ | |||
| 14 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 17 | #include <asm/oplib.h> | 16 | #include <linux/of.h> |
| 18 | #include <asm/ebus.h> | 17 | #include <linux/of_device.h> |
| 19 | #include <asm/spitfire.h> | ||
| 20 | #include <asm/bbc.h> | 18 | #include <asm/bbc.h> |
| 21 | #include <asm/io.h> | 19 | #include <asm/io.h> |
| 22 | 20 | ||
| @@ -53,54 +51,12 @@ | |||
| 53 | * The second controller also connects to the smartcard reader, if present. | 51 | * The second controller also connects to the smartcard reader, if present. |
| 54 | */ | 52 | */ |
| 55 | 53 | ||
| 56 | #define NUM_CHILDREN 8 | 54 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val) |
| 57 | struct bbc_i2c_bus { | ||
| 58 | struct bbc_i2c_bus *next; | ||
| 59 | int index; | ||
| 60 | spinlock_t lock; | ||
| 61 | void __iomem *i2c_bussel_reg; | ||
| 62 | void __iomem *i2c_control_regs; | ||
| 63 | unsigned char own, clock; | ||
| 64 | |||
| 65 | wait_queue_head_t wq; | ||
| 66 | volatile int waiting; | ||
| 67 | |||
| 68 | struct linux_ebus_device *bus_edev; | ||
| 69 | struct { | ||
| 70 | struct linux_ebus_child *device; | ||
| 71 | int client_claimed; | ||
| 72 | } devs[NUM_CHILDREN]; | ||
| 73 | }; | ||
| 74 | |||
| 75 | static struct bbc_i2c_bus *all_bbc_i2c; | ||
| 76 | |||
| 77 | struct bbc_i2c_client { | ||
| 78 | struct bbc_i2c_bus *bp; | ||
| 79 | struct linux_ebus_child *echild; | ||
| 80 | int bus; | ||
| 81 | int address; | ||
| 82 | }; | ||
| 83 | |||
| 84 | static int find_device(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild) | ||
| 85 | { | 55 | { |
| 86 | int i; | 56 | int i; |
| 87 | 57 | ||
| 88 | for (i = 0; i < NUM_CHILDREN; i++) { | 58 | for (i = 0; i < NUM_CHILDREN; i++) { |
| 89 | if (bp->devs[i].device == echild) { | 59 | if (bp->devs[i].device == op) { |
| 90 | if (bp->devs[i].client_claimed) | ||
| 91 | return 0; | ||
| 92 | return 1; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild, int val) | ||
| 99 | { | ||
| 100 | int i; | ||
| 101 | |||
| 102 | for (i = 0; i < NUM_CHILDREN; i++) { | ||
| 103 | if (bp->devs[i].device == echild) { | ||
| 104 | bp->devs[i].client_claimed = val; | 60 | bp->devs[i].client_claimed = val; |
| 105 | return; | 61 | return; |
| 106 | } | 62 | } |
| @@ -110,61 +66,47 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child | |||
| 110 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) | 66 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) |
| 111 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) | 67 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) |
| 112 | 68 | ||
| 113 | static struct bbc_i2c_bus *find_bus_for_device(struct linux_ebus_child *echild) | 69 | struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) |
| 114 | { | 70 | { |
| 115 | struct bbc_i2c_bus *bp = all_bbc_i2c; | 71 | struct of_device *op = NULL; |
| 72 | int curidx = 0, i; | ||
| 116 | 73 | ||
| 117 | while (bp != NULL) { | 74 | for (i = 0; i < NUM_CHILDREN; i++) { |
| 118 | if (find_device(bp, echild) != 0) | 75 | if (!(op = bp->devs[i].device)) |
| 119 | break; | 76 | break; |
| 120 | bp = bp->next; | 77 | if (curidx == index) |
| 78 | goto out; | ||
| 79 | op = NULL; | ||
| 80 | curidx++; | ||
| 121 | } | 81 | } |
| 122 | 82 | ||
| 123 | return bp; | ||
| 124 | } | ||
| 125 | |||
| 126 | struct linux_ebus_child *bbc_i2c_getdev(int index) | ||
| 127 | { | ||
| 128 | struct bbc_i2c_bus *bp = all_bbc_i2c; | ||
| 129 | struct linux_ebus_child *echild = NULL; | ||
| 130 | int curidx = 0; | ||
| 131 | |||
| 132 | while (bp != NULL) { | ||
| 133 | struct bbc_i2c_bus *next = bp->next; | ||
| 134 | int i; | ||
| 135 | |||
| 136 | for (i = 0; i < NUM_CHILDREN; i++) { | ||
| 137 | if (!(echild = bp->devs[i].device)) | ||
| 138 | break; | ||
| 139 | if (curidx == index) | ||
| 140 | goto out; | ||
| 141 | echild = NULL; | ||
| 142 | curidx++; | ||
| 143 | } | ||
| 144 | bp = next; | ||
| 145 | } | ||
| 146 | out: | 83 | out: |
| 147 | if (curidx == index) | 84 | if (curidx == index) |
| 148 | return echild; | 85 | return op; |
| 149 | return NULL; | 86 | return NULL; |
| 150 | } | 87 | } |
| 151 | 88 | ||
| 152 | struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) | 89 | struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op) |
| 153 | { | 90 | { |
| 154 | struct bbc_i2c_bus *bp = find_bus_for_device(echild); | ||
| 155 | struct bbc_i2c_client *client; | 91 | struct bbc_i2c_client *client; |
| 92 | const u32 *reg; | ||
| 156 | 93 | ||
| 157 | if (!bp) | ||
| 158 | return NULL; | ||
| 159 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 94 | client = kzalloc(sizeof(*client), GFP_KERNEL); |
| 160 | if (!client) | 95 | if (!client) |
| 161 | return NULL; | 96 | return NULL; |
| 162 | client->bp = bp; | 97 | client->bp = bp; |
| 163 | client->echild = echild; | 98 | client->op = op; |
| 164 | client->bus = echild->resource[0].start; | 99 | |
| 165 | client->address = echild->resource[1].start; | 100 | reg = of_get_property(op->node, "reg", NULL); |
| 101 | if (!reg) { | ||
| 102 | kfree(client); | ||
| 103 | return NULL; | ||
| 104 | } | ||
| 166 | 105 | ||
| 167 | claim_device(bp, echild); | 106 | client->bus = reg[0]; |
| 107 | client->address = reg[1]; | ||
| 108 | |||
| 109 | claim_device(bp, op); | ||
| 168 | 110 | ||
| 169 | return client; | 111 | return client; |
| 170 | } | 112 | } |
| @@ -172,9 +114,9 @@ struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) | |||
| 172 | void bbc_i2c_detach(struct bbc_i2c_client *client) | 114 | void bbc_i2c_detach(struct bbc_i2c_client *client) |
| 173 | { | 115 | { |
| 174 | struct bbc_i2c_bus *bp = client->bp; | 116 | struct bbc_i2c_bus *bp = client->bp; |
| 175 | struct linux_ebus_child *echild = client->echild; | 117 | struct of_device *op = client->op; |
| 176 | 118 | ||
| 177 | release_device(bp, echild); | 119 | release_device(bp, op); |
| 178 | kfree(client); | 120 | kfree(client); |
| 179 | } | 121 | } |
| 180 | 122 | ||
| @@ -355,44 +297,43 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) | |||
| 355 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); | 297 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); |
| 356 | } | 298 | } |
| 357 | 299 | ||
| 358 | static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) | 300 | static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index) |
| 359 | { | 301 | { |
| 360 | struct bbc_i2c_bus *bp; | 302 | struct bbc_i2c_bus *bp; |
| 361 | struct linux_ebus_child *echild; | 303 | struct device_node *dp; |
| 362 | int entry; | 304 | int entry; |
| 363 | 305 | ||
| 364 | bp = kzalloc(sizeof(*bp), GFP_KERNEL); | 306 | bp = kzalloc(sizeof(*bp), GFP_KERNEL); |
| 365 | if (!bp) | 307 | if (!bp) |
| 366 | return -ENOMEM; | 308 | return NULL; |
| 367 | 309 | ||
| 368 | bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2); | 310 | bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs"); |
| 369 | if (!bp->i2c_control_regs) | 311 | if (!bp->i2c_control_regs) |
| 370 | goto fail; | 312 | goto fail; |
| 371 | 313 | ||
| 372 | if (edev->num_addrs == 2) { | 314 | bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); |
| 373 | bp->i2c_bussel_reg = ioremap(edev->resource[1].start, 0x1); | 315 | if (!bp->i2c_bussel_reg) |
| 374 | if (!bp->i2c_bussel_reg) | 316 | goto fail; |
| 375 | goto fail; | ||
| 376 | } | ||
| 377 | 317 | ||
| 378 | bp->waiting = 0; | 318 | bp->waiting = 0; |
| 379 | init_waitqueue_head(&bp->wq); | 319 | init_waitqueue_head(&bp->wq); |
| 380 | if (request_irq(edev->irqs[0], bbc_i2c_interrupt, | 320 | if (request_irq(op->irqs[0], bbc_i2c_interrupt, |
| 381 | IRQF_SHARED, "bbc_i2c", bp)) | 321 | IRQF_SHARED, "bbc_i2c", bp)) |
| 382 | goto fail; | 322 | goto fail; |
| 383 | 323 | ||
| 384 | bp->index = index; | 324 | bp->index = index; |
| 385 | bp->bus_edev = edev; | 325 | bp->op = op; |
| 386 | 326 | ||
| 387 | spin_lock_init(&bp->lock); | 327 | spin_lock_init(&bp->lock); |
| 388 | bp->next = all_bbc_i2c; | ||
| 389 | all_bbc_i2c = bp; | ||
| 390 | 328 | ||
| 391 | entry = 0; | 329 | entry = 0; |
| 392 | for (echild = edev->children; | 330 | for (dp = op->node->child; |
| 393 | echild && entry < 8; | 331 | dp && entry < 8; |
| 394 | echild = echild->next, entry++) { | 332 | dp = dp->sibling, entry++) { |
| 395 | bp->devs[entry].device = echild; | 333 | struct of_device *child_op; |
| 334 | |||
| 335 | child_op = of_find_device_by_node(dp); | ||
| 336 | bp->devs[entry].device = child_op; | ||
| 396 | bp->devs[entry].client_claimed = 0; | 337 | bp->devs[entry].client_claimed = 0; |
| 397 | } | 338 | } |
| 398 | 339 | ||
| @@ -406,86 +347,90 @@ static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) | |||
| 406 | 347 | ||
| 407 | reset_one_i2c(bp); | 348 | reset_one_i2c(bp); |
| 408 | 349 | ||
| 409 | return 0; | 350 | return bp; |
| 410 | 351 | ||
| 411 | fail: | 352 | fail: |
| 412 | if (bp->i2c_bussel_reg) | 353 | if (bp->i2c_bussel_reg) |
| 413 | iounmap(bp->i2c_bussel_reg); | 354 | of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1); |
| 414 | if (bp->i2c_control_regs) | 355 | if (bp->i2c_control_regs) |
| 415 | iounmap(bp->i2c_control_regs); | 356 | of_iounmap(&op->resource[0], bp->i2c_control_regs, 2); |
| 416 | kfree(bp); | 357 | kfree(bp); |
| 417 | return -EINVAL; | 358 | return NULL; |
| 418 | } | ||
| 419 | |||
| 420 | static int __init bbc_present(void) | ||
| 421 | { | ||
| 422 | struct linux_ebus *ebus = NULL; | ||
| 423 | struct linux_ebus_device *edev = NULL; | ||
| 424 | |||
| 425 | for_each_ebus(ebus) { | ||
| 426 | for_each_ebusdev(edev, ebus) { | ||
| 427 | if (!strcmp(edev->prom_node->name, "bbc")) | ||
| 428 | return 1; | ||
| 429 | } | ||
| 430 | } | ||
| 431 | return 0; | ||
| 432 | } | 359 | } |
| 433 | 360 | ||
| 434 | extern int bbc_envctrl_init(void); | 361 | extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); |
| 435 | extern void bbc_envctrl_cleanup(void); | 362 | extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); |
| 436 | static void bbc_i2c_cleanup(void); | ||
| 437 | 363 | ||
| 438 | static int __init bbc_i2c_init(void) | 364 | static int __devinit bbc_i2c_probe(struct of_device *op, |
| 365 | const struct of_device_id *match) | ||
| 439 | { | 366 | { |
| 440 | struct linux_ebus *ebus = NULL; | 367 | struct bbc_i2c_bus *bp; |
| 441 | struct linux_ebus_device *edev = NULL; | ||
| 442 | int err, index = 0; | 368 | int err, index = 0; |
| 443 | 369 | ||
| 444 | if ((tlb_type != cheetah && tlb_type != cheetah_plus) || | 370 | bp = attach_one_i2c(op, index); |
| 445 | !bbc_present()) | 371 | if (!bp) |
| 446 | return -ENODEV; | 372 | return -EINVAL; |
| 447 | 373 | ||
| 448 | for_each_ebus(ebus) { | 374 | err = bbc_envctrl_init(bp); |
| 449 | for_each_ebusdev(edev, ebus) { | 375 | if (err) { |
| 450 | if (!strcmp(edev->prom_node->name, "i2c")) { | 376 | free_irq(op->irqs[0], bp); |
| 451 | if (!attach_one_i2c(edev, index)) | 377 | if (bp->i2c_bussel_reg) |
| 452 | index++; | 378 | of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); |
| 453 | } | 379 | if (bp->i2c_control_regs) |
| 454 | } | 380 | of_iounmap(&op->resource[1], bp->i2c_control_regs, 2); |
| 381 | kfree(bp); | ||
| 382 | } else { | ||
| 383 | dev_set_drvdata(&op->dev, bp); | ||
| 455 | } | 384 | } |
| 456 | 385 | ||
| 457 | if (!index) | ||
| 458 | return -ENODEV; | ||
| 459 | |||
| 460 | err = bbc_envctrl_init(); | ||
| 461 | if (err) | ||
| 462 | bbc_i2c_cleanup(); | ||
| 463 | return err; | 386 | return err; |
| 464 | } | 387 | } |
| 465 | 388 | ||
| 466 | static void bbc_i2c_cleanup(void) | 389 | static int __devexit bbc_i2c_remove(struct of_device *op) |
| 467 | { | 390 | { |
| 468 | struct bbc_i2c_bus *bp = all_bbc_i2c; | 391 | struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); |
| 392 | |||
| 393 | bbc_envctrl_cleanup(bp); | ||
| 394 | |||
| 395 | free_irq(op->irqs[0], bp); | ||
| 469 | 396 | ||
| 470 | bbc_envctrl_cleanup(); | 397 | if (bp->i2c_bussel_reg) |
| 398 | of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); | ||
| 399 | if (bp->i2c_control_regs) | ||
| 400 | of_iounmap(&op->resource[1], bp->i2c_control_regs, 2); | ||
| 471 | 401 | ||
| 472 | while (bp != NULL) { | 402 | kfree(bp); |
| 473 | struct bbc_i2c_bus *next = bp->next; | ||
| 474 | 403 | ||
| 475 | free_irq(bp->bus_edev->irqs[0], bp); | 404 | return 0; |
| 405 | } | ||
| 476 | 406 | ||
| 477 | if (bp->i2c_bussel_reg) | 407 | static const struct of_device_id bbc_i2c_match[] = { |
| 478 | iounmap(bp->i2c_bussel_reg); | 408 | { |
| 479 | if (bp->i2c_control_regs) | 409 | .name = "i2c", |
| 480 | iounmap(bp->i2c_control_regs); | 410 | .compatible = "SUNW,bbc-i2c", |
| 411 | }, | ||
| 412 | {}, | ||
| 413 | }; | ||
| 414 | MODULE_DEVICE_TABLE(of, bbc_i2c_match); | ||
| 481 | 415 | ||
| 482 | kfree(bp); | 416 | static struct of_platform_driver bbc_i2c_driver = { |
| 417 | .name = "bbc_i2c", | ||
| 418 | .match_table = bbc_i2c_match, | ||
| 419 | .probe = bbc_i2c_probe, | ||
| 420 | .remove = __devexit_p(bbc_i2c_remove), | ||
| 421 | }; | ||
| 483 | 422 | ||
| 484 | bp = next; | 423 | static int __init bbc_i2c_init(void) |
| 485 | } | 424 | { |
| 486 | all_bbc_i2c = NULL; | 425 | return of_register_driver(&bbc_i2c_driver, &of_bus_type); |
| 426 | } | ||
| 427 | |||
| 428 | static void __exit bbc_i2c_exit(void) | ||
| 429 | { | ||
| 430 | of_unregister_driver(&bbc_i2c_driver); | ||
| 487 | } | 431 | } |
| 488 | 432 | ||
| 489 | module_init(bbc_i2c_init); | 433 | module_init(bbc_i2c_init); |
| 490 | module_exit(bbc_i2c_cleanup); | 434 | module_exit(bbc_i2c_exit); |
| 435 | |||
| 491 | MODULE_LICENSE("GPL"); | 436 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index fb01bd17704b..83c4811b7b5e 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h | |||
| @@ -1,14 +1,79 @@ | |||
| 1 | /* $Id: bbc_i2c.h,v 1.2 2001/04/02 09:59:25 davem Exp $ */ | ||
| 2 | #ifndef _BBC_I2C_H | 1 | #ifndef _BBC_I2C_H |
| 3 | #define _BBC_I2C_H | 2 | #define _BBC_I2C_H |
| 4 | 3 | ||
| 5 | #include <asm/ebus.h> | 4 | #include <linux/of.h> |
| 5 | #include <linux/of_device.h> | ||
| 6 | #include <linux/list.h> | ||
| 6 | 7 | ||
| 7 | struct bbc_i2c_client; | 8 | struct bbc_i2c_client { |
| 9 | struct bbc_i2c_bus *bp; | ||
| 10 | struct of_device *op; | ||
| 11 | int bus; | ||
| 12 | int address; | ||
| 13 | }; | ||
| 14 | |||
| 15 | enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; | ||
| 16 | |||
| 17 | struct bbc_cpu_temperature { | ||
| 18 | struct list_head bp_list; | ||
| 19 | struct list_head glob_list; | ||
| 20 | |||
| 21 | struct bbc_i2c_client *client; | ||
| 22 | int index; | ||
| 23 | |||
| 24 | /* Current readings, and history. */ | ||
| 25 | s8 curr_cpu_temp; | ||
| 26 | s8 curr_amb_temp; | ||
| 27 | s8 prev_cpu_temp; | ||
| 28 | s8 prev_amb_temp; | ||
| 29 | s8 avg_cpu_temp; | ||
| 30 | s8 avg_amb_temp; | ||
| 31 | |||
| 32 | int sample_tick; | ||
| 33 | |||
| 34 | enum fan_action fan_todo[2]; | ||
| 35 | #define FAN_AMBIENT 0 | ||
| 36 | #define FAN_CPU 1 | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct bbc_fan_control { | ||
| 40 | struct list_head bp_list; | ||
| 41 | struct list_head glob_list; | ||
| 42 | |||
| 43 | struct bbc_i2c_client *client; | ||
| 44 | int index; | ||
| 45 | |||
| 46 | int psupply_fan_on; | ||
| 47 | int cpu_fan_speed; | ||
| 48 | int system_fan_speed; | ||
| 49 | }; | ||
| 50 | |||
| 51 | #define NUM_CHILDREN 8 | ||
| 52 | |||
| 53 | struct bbc_i2c_bus { | ||
| 54 | struct bbc_i2c_bus *next; | ||
| 55 | int index; | ||
| 56 | spinlock_t lock; | ||
| 57 | void __iomem *i2c_bussel_reg; | ||
| 58 | void __iomem *i2c_control_regs; | ||
| 59 | unsigned char own, clock; | ||
| 60 | |||
| 61 | wait_queue_head_t wq; | ||
| 62 | volatile int waiting; | ||
| 63 | |||
| 64 | struct list_head temps; | ||
| 65 | struct list_head fans; | ||
| 66 | |||
| 67 | struct of_device *op; | ||
| 68 | struct { | ||
| 69 | struct of_device *device; | ||
| 70 | int client_claimed; | ||
| 71 | } devs[NUM_CHILDREN]; | ||
| 72 | }; | ||
| 8 | 73 | ||
| 9 | /* Probing and attachment. */ | 74 | /* Probing and attachment. */ |
| 10 | extern struct linux_ebus_child *bbc_i2c_getdev(int); | 75 | extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); |
| 11 | extern struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *); | 76 | extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *); |
| 12 | extern void bbc_i2c_detach(struct bbc_i2c_client *); | 77 | extern void bbc_i2c_detach(struct bbc_i2c_client *); |
| 13 | 78 | ||
| 14 | /* Register read/write. NOTE: Blocking! */ | 79 | /* Register read/write. NOTE: Blocking! */ |
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c deleted file mode 100644 index bba21e053a1b..000000000000 --- a/drivers/sbus/char/bpp.c +++ /dev/null | |||
| @@ -1,1055 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * drivers/sbus/char/bpp.c | ||
| 3 | * | ||
| 4 | * Copyright (c) 1995 Picture Elements | ||
| 5 | * Stephen Williams (steve@icarus.com) | ||
| 6 | * Gus Baldauf (gbaldauf@ix.netcom.com) | ||
| 7 | * | ||
| 8 | * Linux/SPARC port by Peter Zaitcev. | ||
| 9 | * Integration into SPARC tree by Tom Dyas. | ||
| 10 | */ | ||
| 11 | |||
| 12 | |||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/fs.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <linux/spinlock.h> | ||
| 19 | #include <linux/timer.h> | ||
| 20 | #include <linux/ioport.h> | ||
| 21 | #include <linux/major.h> | ||
| 22 | #include <linux/smp_lock.h> | ||
| 23 | |||
| 24 | #include <asm/uaccess.h> | ||
| 25 | #include <asm/io.h> | ||
| 26 | |||
| 27 | #if defined(__i386__) | ||
| 28 | # include <asm/system.h> | ||
| 29 | #endif | ||
| 30 | |||
| 31 | #if defined(__sparc__) | ||
| 32 | # include <linux/init.h> | ||
| 33 | # include <linux/delay.h> /* udelay() */ | ||
| 34 | |||
| 35 | # include <asm/oplib.h> /* OpenProm Library */ | ||
| 36 | # include <asm/sbus.h> | ||
| 37 | #endif | ||
| 38 | |||
| 39 | #include <asm/bpp.h> | ||
| 40 | |||
| 41 | #define BPP_PROBE_CODE 0x55 | ||
| 42 | #define BPP_DELAY 100 | ||
| 43 | |||
| 44 | static const unsigned BPP_MAJOR = LP_MAJOR; | ||
| 45 | static const char *bpp_dev_name = "bpp"; | ||
| 46 | |||
| 47 | /* When switching from compatibility to a mode where I can read, try | ||
| 48 | the following mode first. */ | ||
| 49 | |||
| 50 | /* const unsigned char DEFAULT_ECP = 0x10; */ | ||
| 51 | static const unsigned char DEFAULT_ECP = 0x30; | ||
| 52 | static const unsigned char DEFAULT_NIBBLE = 0x00; | ||
| 53 | |||
| 54 | /* | ||
| 55 | * These are 1284 time constraints, in units of jiffies. | ||
| 56 | */ | ||
| 57 | |||
| 58 | static const unsigned long TIME_PSetup = 1; | ||
| 59 | static const unsigned long TIME_PResponse = 6; | ||
| 60 | static const unsigned long TIME_IDLE_LIMIT = 2000; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * One instance per supported subdevice... | ||
| 64 | */ | ||
| 65 | # define BPP_NO 3 | ||
| 66 | |||
| 67 | enum IEEE_Mode { COMPATIBILITY, NIBBLE, ECP, ECP_RLE, EPP }; | ||
| 68 | |||
| 69 | struct inst { | ||
| 70 | unsigned present : 1; /* True if the hardware exists */ | ||
| 71 | unsigned enhanced : 1; /* True if the hardware in "enhanced" */ | ||
| 72 | unsigned opened : 1; /* True if the device is opened already */ | ||
| 73 | unsigned run_flag : 1; /* True if waiting for a repeate byte */ | ||
| 74 | |||
| 75 | unsigned char direction; /* 0 --> out, 0x20 --> IN */ | ||
| 76 | unsigned char pp_state; /* State of host controlled pins. */ | ||
| 77 | enum IEEE_Mode mode; | ||
| 78 | |||
| 79 | unsigned char run_length; | ||
| 80 | unsigned char repeat_byte; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static struct inst instances[BPP_NO]; | ||
| 84 | |||
| 85 | #if defined(__i386__) | ||
| 86 | |||
| 87 | static const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc }; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * These are for data access. | ||
| 91 | * Control lines accesses are hidden in set_bits() and get_bits(). | ||
| 92 | * The exception is the probe procedure, which is system-dependent. | ||
| 93 | */ | ||
| 94 | #define bpp_outb_p(data, base) outb_p((data), (base)) | ||
| 95 | #define bpp_inb(base) inb(base) | ||
| 96 | #define bpp_inb_p(base) inb_p(base) | ||
| 97 | |||
| 98 | /* | ||
| 99 | * This method takes the pin values mask and sets the hardware pins to | ||
| 100 | * the requested value: 1 == high voltage, 0 == low voltage. This | ||
| 101 | * burries the annoying PC bit inversion and preserves the direction | ||
| 102 | * flag. | ||
| 103 | */ | ||
| 104 | static void set_pins(unsigned short pins, unsigned minor) | ||
| 105 | { | ||
| 106 | unsigned char bits = instances[minor].direction; /* == 0x20 */ | ||
| 107 | |||
| 108 | if (! (pins & BPP_PP_nStrobe)) bits |= 1; | ||
| 109 | if (! (pins & BPP_PP_nAutoFd)) bits |= 2; | ||
| 110 | if ( pins & BPP_PP_nInit) bits |= 4; | ||
| 111 | if (! (pins & BPP_PP_nSelectIn)) bits |= 8; | ||
| 112 | |||
| 113 | instances[minor].pp_state = bits; | ||
| 114 | |||
| 115 | outb_p(bits, base_addrs[minor]+2); | ||
| 116 | } | ||
| 117 | |||
| 118 | static unsigned short get_pins(unsigned minor) | ||
| 119 | { | ||
| 120 | unsigned short bits = 0; | ||
| 121 | |||
| 122 | unsigned value = instances[minor].pp_state; | ||
| 123 | if (! (value & 0x01)) bits |= BPP_PP_nStrobe; | ||
| 124 | if (! (value & 0x02)) bits |= BPP_PP_nAutoFd; | ||
| 125 | if (value & 0x04) bits |= BPP_PP_nInit; | ||
| 126 | if (! (value & 0x08)) bits |= BPP_PP_nSelectIn; | ||
| 127 | |||
| 128 | value = inb_p(base_addrs[minor]+1); | ||
| 129 | if (value & 0x08) bits |= BPP_GP_nFault; | ||
| 130 | if (value & 0x10) bits |= BPP_GP_Select; | ||
| 131 | if (value & 0x20) bits |= BPP_GP_PError; | ||
| 132 | if (value & 0x40) bits |= BPP_GP_nAck; | ||
| 133 | if (! (value & 0x80)) bits |= BPP_GP_Busy; | ||
| 134 | |||
| 135 | return bits; | ||
| 136 | } | ||
| 137 | |||
| 138 | #endif /* __i386__ */ | ||
| 139 | |||
| 140 | #if defined(__sparc__) | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Register block | ||
| 144 | */ | ||
| 145 | /* DMA registers */ | ||
| 146 | #define BPP_CSR 0x00 | ||
| 147 | #define BPP_ADDR 0x04 | ||
| 148 | #define BPP_BCNT 0x08 | ||
| 149 | #define BPP_TST_CSR 0x0C | ||
| 150 | /* Parallel Port registers */ | ||
| 151 | #define BPP_HCR 0x10 | ||
| 152 | #define BPP_OCR 0x12 | ||
| 153 | #define BPP_DR 0x14 | ||
| 154 | #define BPP_TCR 0x15 | ||
| 155 | #define BPP_OR 0x16 | ||
| 156 | #define BPP_IR 0x17 | ||
| 157 | #define BPP_ICR 0x18 | ||
| 158 | #define BPP_SIZE 0x1A | ||
| 159 | |||
| 160 | /* BPP_CSR. Bits of type RW1 are cleared with writing '1'. */ | ||
| 161 | #define P_DEV_ID_MASK 0xf0000000 /* R */ | ||
| 162 | #define P_DEV_ID_ZEBRA 0x40000000 | ||
| 163 | #define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ | ||
| 164 | #define P_NA_LOADED 0x08000000 /* R NA wirtten but was not used */ | ||
| 165 | #define P_A_LOADED 0x04000000 /* R */ | ||
| 166 | #define P_DMA_ON 0x02000000 /* R DMA is not disabled */ | ||
| 167 | #define P_EN_NEXT 0x01000000 /* RW */ | ||
| 168 | #define P_TCI_DIS 0x00800000 /* RW TCI forbidden from interrupts */ | ||
| 169 | #define P_DIAG 0x00100000 /* RW Disables draining and resetting | ||
| 170 | of P-FIFO on loading of P_ADDR*/ | ||
| 171 | #define P_BURST_SIZE 0x000c0000 /* RW SBus burst size */ | ||
| 172 | #define P_BURST_8 0x00000000 | ||
| 173 | #define P_BURST_4 0x00040000 | ||
| 174 | #define P_BURST_1 0x00080000 /* "No burst" write */ | ||
| 175 | #define P_TC 0x00004000 /* RW1 Term Count, can be cleared when | ||
| 176 | P_EN_NEXT=1 */ | ||
| 177 | #define P_EN_CNT 0x00002000 /* RW */ | ||
| 178 | #define P_EN_DMA 0x00000200 /* RW */ | ||
| 179 | #define P_WRITE 0x00000100 /* R DMA dir, 1=to ram, 0=to port */ | ||
| 180 | #define P_RESET 0x00000080 /* RW */ | ||
| 181 | #define P_SLAVE_ERR 0x00000040 /* RW1 Access size error */ | ||
| 182 | #define P_INVALIDATE 0x00000020 /* W Drop P-FIFO */ | ||
| 183 | #define P_INT_EN 0x00000010 /* RW OK to P_INT_PEND||P_ERR_PEND */ | ||
| 184 | #define P_DRAINING 0x0000000c /* R P-FIFO is draining to memory */ | ||
| 185 | #define P_ERR_PEND 0x00000002 /* R */ | ||
| 186 | #define P_INT_PEND 0x00000001 /* R */ | ||
| 187 | |||
| 188 | /* BPP_HCR. Time is in increments of SBus clock. */ | ||
| 189 | #define P_HCR_TEST 0x8000 /* Allows buried counters to be read */ | ||
| 190 | #define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */ | ||
| 191 | #define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */ | ||
| 192 | |||
| 193 | /* BPP_OCR. */ | ||
| 194 | #define P_OCR_MEM_CLR 0x8000 | ||
| 195 | #define P_OCR_DATA_SRC 0x4000 /* ) */ | ||
| 196 | #define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */ | ||
| 197 | #define P_OCR_BUSY_DSEL 0x1000 /* ) selects */ | ||
| 198 | #define P_OCR_ACK_DSEL 0x0800 /* ) */ | ||
| 199 | #define P_OCR_EN_DIAG 0x0400 | ||
| 200 | #define P_OCR_BUSY_OP 0x0200 /* Busy operation */ | ||
| 201 | #define P_OCR_ACK_OP 0x0100 /* Ack operation */ | ||
| 202 | #define P_OCR_SRST 0x0080 /* Reset state machines. Not selfcleaning. */ | ||
| 203 | #define P_OCR_IDLE 0x0008 /* PP data transfer state machine is idle */ | ||
| 204 | #define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */ | ||
| 205 | #define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */ | ||
| 206 | |||
| 207 | /* BPP_TCR */ | ||
| 208 | #define P_TCR_DIR 0x08 | ||
| 209 | #define P_TCR_BUSY 0x04 | ||
| 210 | #define P_TCR_ACK 0x02 | ||
| 211 | #define P_TCR_DS 0x01 /* Strobe */ | ||
| 212 | |||
| 213 | /* BPP_OR */ | ||
| 214 | #define P_OR_V3 0x20 /* ) */ | ||
| 215 | #define P_OR_V2 0x10 /* ) on Zebra only */ | ||
| 216 | #define P_OR_V1 0x08 /* ) */ | ||
| 217 | #define P_OR_INIT 0x04 | ||
| 218 | #define P_OR_AFXN 0x02 /* Auto Feed */ | ||
| 219 | #define P_OR_SLCT_IN 0x01 | ||
| 220 | |||
| 221 | /* BPP_IR */ | ||
| 222 | #define P_IR_PE 0x04 | ||
| 223 | #define P_IR_SLCT 0x02 | ||
| 224 | #define P_IR_ERR 0x01 | ||
| 225 | |||
| 226 | /* BPP_ICR */ | ||
| 227 | #define P_DS_IRQ 0x8000 /* RW1 */ | ||
| 228 | #define P_ACK_IRQ 0x4000 /* RW1 */ | ||
| 229 | #define P_BUSY_IRQ 0x2000 /* RW1 */ | ||
| 230 | #define P_PE_IRQ 0x1000 /* RW1 */ | ||
| 231 | #define P_SLCT_IRQ 0x0800 /* RW1 */ | ||
| 232 | #define P_ERR_IRQ 0x0400 /* RW1 */ | ||
| 233 | #define P_DS_IRQ_EN 0x0200 /* RW Always on rising edge */ | ||
| 234 | #define P_ACK_IRQ_EN 0x0100 /* RW Always on rising edge */ | ||
| 235 | #define P_BUSY_IRP 0x0080 /* RW 1= rising edge */ | ||
| 236 | #define P_BUSY_IRQ_EN 0x0040 /* RW */ | ||
| 237 | #define P_PE_IRP 0x0020 /* RW 1= rising edge */ | ||
| 238 | #define P_PE_IRQ_EN 0x0010 /* RW */ | ||
| 239 | #define P_SLCT_IRP 0x0008 /* RW 1= rising edge */ | ||
| 240 | #define P_SLCT_IRQ_EN 0x0004 /* RW */ | ||
| 241 | #define P_ERR_IRP 0x0002 /* RW1 1= rising edge */ | ||
| 242 | #define P_ERR_IRQ_EN 0x0001 /* RW */ | ||
| 243 | |||
| 244 | static void __iomem *base_addrs[BPP_NO]; | ||
| 245 | |||
| 246 | #define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR) | ||
| 247 | #define bpp_inb_p(base) sbus_readb((base) + BPP_DR) | ||
| 248 | #define bpp_inb(base) sbus_readb((base) + BPP_DR) | ||
| 249 | |||
| 250 | static void set_pins(unsigned short pins, unsigned minor) | ||
| 251 | { | ||
| 252 | void __iomem *base = base_addrs[minor]; | ||
| 253 | unsigned char bits_tcr = 0, bits_or = 0; | ||
| 254 | |||
| 255 | if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR; | ||
| 256 | if ( pins & BPP_PP_nStrobe) bits_tcr |= P_TCR_DS; | ||
| 257 | |||
| 258 | if ( pins & BPP_PP_nAutoFd) bits_or |= P_OR_AFXN; | ||
| 259 | if (! (pins & BPP_PP_nInit)) bits_or |= P_OR_INIT; | ||
| 260 | if (! (pins & BPP_PP_nSelectIn)) bits_or |= P_OR_SLCT_IN; | ||
| 261 | |||
| 262 | sbus_writeb(bits_or, base + BPP_OR); | ||
| 263 | sbus_writeb(bits_tcr, base + BPP_TCR); | ||
| 264 | } | ||
| 265 | |||
| 266 | /* | ||
| 267 | * i386 people read output pins from a software image. | ||
| 268 | * We may get them back from hardware. | ||
| 269 | * Again, inversion of pins must he buried here. | ||
| 270 | */ | ||
| 271 | static unsigned short get_pins(unsigned minor) | ||
| 272 | { | ||
| 273 | void __iomem *base = base_addrs[minor]; | ||
| 274 | unsigned short bits = 0; | ||
| 275 | unsigned value_tcr = sbus_readb(base + BPP_TCR); | ||
| 276 | unsigned value_ir = sbus_readb(base + BPP_IR); | ||
| 277 | unsigned value_or = sbus_readb(base + BPP_OR); | ||
| 278 | |||
| 279 | if (value_tcr & P_TCR_DS) bits |= BPP_PP_nStrobe; | ||
| 280 | if (value_or & P_OR_AFXN) bits |= BPP_PP_nAutoFd; | ||
| 281 | if (! (value_or & P_OR_INIT)) bits |= BPP_PP_nInit; | ||
| 282 | if (! (value_or & P_OR_SLCT_IN)) bits |= BPP_PP_nSelectIn; | ||
| 283 | |||
| 284 | if (value_ir & P_IR_ERR) bits |= BPP_GP_nFault; | ||
| 285 | if (! (value_ir & P_IR_SLCT)) bits |= BPP_GP_Select; | ||
| 286 | if (! (value_ir & P_IR_PE)) bits |= BPP_GP_PError; | ||
| 287 | if (! (value_tcr & P_TCR_ACK)) bits |= BPP_GP_nAck; | ||
| 288 | if (value_tcr & P_TCR_BUSY) bits |= BPP_GP_Busy; | ||
| 289 | |||
| 290 | return bits; | ||
| 291 | } | ||
| 292 | |||
| 293 | #endif /* __sparc__ */ | ||
| 294 | |||
| 295 | static void snooze(unsigned long snooze_time, unsigned minor) | ||
| 296 | { | ||
| 297 | schedule_timeout_uninterruptible(snooze_time + 1); | ||
| 298 | } | ||
| 299 | |||
| 300 | static int wait_for(unsigned short set, unsigned short clr, | ||
| 301 | unsigned long delay, unsigned minor) | ||
| 302 | { | ||
| 303 | unsigned short pins = get_pins(minor); | ||
| 304 | |||
| 305 | unsigned long extime = 0; | ||
| 306 | |||
| 307 | /* | ||
| 308 | * Try a real fast scan for the first jiffy, in case the device | ||
| 309 | * responds real good. The first while loop guesses an expire | ||
| 310 | * time accounting for possible wraparound of jiffies. | ||
| 311 | */ | ||
| 312 | while (time_after_eq(jiffies, extime)) extime = jiffies + 1; | ||
| 313 | while ( (time_before(jiffies, extime)) | ||
| 314 | && (((pins & set) != set) || ((pins & clr) != 0)) ) { | ||
| 315 | pins = get_pins(minor); | ||
| 316 | } | ||
| 317 | |||
| 318 | delay -= 1; | ||
| 319 | |||
| 320 | /* | ||
| 321 | * If my delay expired or the pins are still not where I want | ||
| 322 | * them, then resort to using the timer and greatly reduce my | ||
| 323 | * sample rate. If the peripheral is going to be slow, this will | ||
| 324 | * give the CPU up to some more worthy process. | ||
| 325 | */ | ||
| 326 | while ( delay && (((pins & set) != set) || ((pins & clr) != 0)) ) { | ||
| 327 | |||
| 328 | snooze(1, minor); | ||
| 329 | pins = get_pins(minor); | ||
| 330 | delay -= 1; | ||
| 331 | } | ||
| 332 | |||
| 333 | if (delay == 0) return -1; | ||
| 334 | else return pins; | ||
| 335 | } | ||
| 336 | |||
| 337 | /* | ||
| 338 | * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An | ||
| 339 | * errno means something broke, and I do not yet know how to fix it. | ||
| 340 | */ | ||
| 341 | static int negotiate(unsigned char mode, unsigned minor) | ||
| 342 | { | ||
| 343 | int rc; | ||
| 344 | unsigned short pins = get_pins(minor); | ||
| 345 | if (pins & BPP_PP_nSelectIn) return -EIO; | ||
| 346 | |||
| 347 | |||
| 348 | /* Event 0: Write the mode to the data lines */ | ||
| 349 | bpp_outb_p(mode, base_addrs[minor]); | ||
| 350 | |||
| 351 | snooze(TIME_PSetup, minor); | ||
| 352 | |||
| 353 | /* Event 1: Strobe the mode code into the peripheral */ | ||
| 354 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
| 355 | |||
| 356 | /* Wait for Event 2: Peripheral responds as a 1284 device. */ | ||
| 357 | rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault, | ||
| 358 | BPP_GP_nAck, | ||
| 359 | TIME_PResponse, | ||
| 360 | minor); | ||
| 361 | |||
| 362 | if (rc == -1) return -ETIMEDOUT; | ||
| 363 | |||
| 364 | /* Event 3: latch extensibility request */ | ||
| 365 | set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor); | ||
| 366 | |||
| 367 | /* ... quick nap while peripheral ponders the byte i'm sending...*/ | ||
| 368 | snooze(1, minor); | ||
| 369 | |||
| 370 | /* Event 4: restore strobe, to ACK peripheral's response. */ | ||
| 371 | set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
| 372 | |||
| 373 | /* Wait for Event 6: Peripheral latches response bits */ | ||
| 374 | rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor); | ||
| 375 | if (rc == -1) return -EIO; | ||
| 376 | |||
| 377 | /* A 1284 device cannot refuse nibble mode */ | ||
| 378 | if (mode == DEFAULT_NIBBLE) return 0; | ||
| 379 | |||
| 380 | if (pins & BPP_GP_Select) return 0; | ||
| 381 | |||
| 382 | return -EPROTONOSUPPORT; | ||
| 383 | } | ||
| 384 | |||
| 385 | static int terminate(unsigned minor) | ||
| 386 | { | ||
| 387 | int rc; | ||
| 388 | |||
| 389 | /* Event 22: Request termination of 1284 mode */ | ||
| 390 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
| 391 | |||
| 392 | /* Wait for Events 23 and 24: ACK termination request. */ | ||
| 393 | rc = wait_for(BPP_GP_Busy|BPP_GP_nFault, | ||
| 394 | BPP_GP_nAck, | ||
| 395 | TIME_PSetup+TIME_PResponse, | ||
| 396 | minor); | ||
| 397 | |||
| 398 | instances[minor].direction = 0; | ||
| 399 | instances[minor].mode = COMPATIBILITY; | ||
| 400 | |||
| 401 | if (rc == -1) { | ||
| 402 | return -EIO; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* Event 25: Handshake by lowering nAutoFd */ | ||
| 406 | set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
| 407 | |||
| 408 | /* Event 26: Peripheral wiggles lines... */ | ||
| 409 | |||
| 410 | /* Event 27: Peripheral sets nAck HIGH to ack handshake */ | ||
| 411 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
| 412 | if (rc == -1) { | ||
| 413 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
| 414 | return -EIO; | ||
| 415 | } | ||
| 416 | |||
| 417 | /* Event 28: Finish phase by raising nAutoFd */ | ||
| 418 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
| 419 | |||
| 420 | return 0; | ||
| 421 | } | ||
| 422 | |||
| 423 | static DEFINE_SPINLOCK(bpp_open_lock); | ||
| 424 | |||
| 425 | /* | ||
| 426 | * Allow only one process to open the device at a time. | ||
| 427 | */ | ||
| 428 | static int bpp_open(struct inode *inode, struct file *f) | ||
| 429 | { | ||
| 430 | unsigned minor = iminor(inode); | ||
| 431 | int ret; | ||
| 432 | |||
| 433 | lock_kernel(); | ||
| 434 | spin_lock(&bpp_open_lock); | ||
| 435 | ret = 0; | ||
| 436 | if (minor >= BPP_NO) { | ||
| 437 | ret = -ENODEV; | ||
| 438 | } else { | ||
| 439 | if (! instances[minor].present) { | ||
| 440 | ret = -ENODEV; | ||
| 441 | } else { | ||
| 442 | if (instances[minor].opened) | ||
| 443 | ret = -EBUSY; | ||
| 444 | else | ||
| 445 | instances[minor].opened = 1; | ||
| 446 | } | ||
| 447 | } | ||
| 448 | spin_unlock(&bpp_open_lock); | ||
| 449 | unlock_kernel(); | ||
| 450 | |||
| 451 | return ret; | ||
| 452 | } | ||
| 453 | |||
| 454 | /* | ||
| 455 | * When the process closes the device, this method is called to clean | ||
| 456 | * up and reset the hardware. Always leave the device in compatibility | ||
| 457 | * mode as this is a reasonable place to clean up from messes made by | ||
| 458 | * ioctls, or other mayhem. | ||
| 459 | */ | ||
| 460 | static int bpp_release(struct inode *inode, struct file *f) | ||
| 461 | { | ||
| 462 | unsigned minor = iminor(inode); | ||
| 463 | |||
| 464 | spin_lock(&bpp_open_lock); | ||
| 465 | instances[minor].opened = 0; | ||
| 466 | |||
| 467 | if (instances[minor].mode != COMPATIBILITY) | ||
| 468 | terminate(minor); | ||
| 469 | |||
| 470 | spin_unlock(&bpp_open_lock); | ||
| 471 | |||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 475 | static long read_nibble(unsigned minor, char __user *c, unsigned long cnt) | ||
| 476 | { | ||
| 477 | unsigned long remaining = cnt; | ||
| 478 | long rc; | ||
| 479 | |||
| 480 | while (remaining > 0) { | ||
| 481 | unsigned char byte = 0; | ||
| 482 | int pins; | ||
| 483 | |||
| 484 | /* Event 7: request nibble */ | ||
| 485 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); | ||
| 486 | |||
| 487 | /* Wait for event 9: Peripher strobes first nibble */ | ||
| 488 | pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); | ||
| 489 | if (pins == -1) return -ETIMEDOUT; | ||
| 490 | |||
| 491 | /* Event 10: I handshake nibble */ | ||
| 492 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); | ||
| 493 | if (pins & BPP_GP_nFault) byte |= 0x01; | ||
| 494 | if (pins & BPP_GP_Select) byte |= 0x02; | ||
| 495 | if (pins & BPP_GP_PError) byte |= 0x04; | ||
| 496 | if (pins & BPP_GP_Busy) byte |= 0x08; | ||
| 497 | |||
| 498 | /* Wait for event 11: Peripheral handshakes nibble */ | ||
| 499 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
| 500 | |||
| 501 | /* Event 7: request nibble */ | ||
| 502 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); | ||
| 503 | |||
| 504 | /* Wait for event 9: Peripher strobes first nibble */ | ||
| 505 | pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor); | ||
| 506 | if (rc == -1) return -ETIMEDOUT; | ||
| 507 | |||
| 508 | /* Event 10: I handshake nibble */ | ||
| 509 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); | ||
| 510 | if (pins & BPP_GP_nFault) byte |= 0x10; | ||
| 511 | if (pins & BPP_GP_Select) byte |= 0x20; | ||
| 512 | if (pins & BPP_GP_PError) byte |= 0x40; | ||
| 513 | if (pins & BPP_GP_Busy) byte |= 0x80; | ||
| 514 | |||
| 515 | if (put_user(byte, c)) | ||
| 516 | return -EFAULT; | ||
| 517 | c += 1; | ||
| 518 | remaining -= 1; | ||
| 519 | |||
| 520 | /* Wait for event 11: Peripheral handshakes nibble */ | ||
| 521 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
| 522 | if (rc == -1) return -EIO; | ||
| 523 | } | ||
| 524 | |||
| 525 | return cnt - remaining; | ||
| 526 | } | ||
| 527 | |||
| 528 | static long read_ecp(unsigned minor, char __user *c, unsigned long cnt) | ||
| 529 | { | ||
| 530 | unsigned long remaining; | ||
| 531 | long rc; | ||
| 532 | |||
| 533 | /* Turn ECP mode from forward to reverse if needed. */ | ||
| 534 | if (! instances[minor].direction) { | ||
| 535 | unsigned short pins = get_pins(minor); | ||
| 536 | |||
| 537 | /* Event 38: Turn the bus around */ | ||
| 538 | instances[minor].direction = 0x20; | ||
| 539 | pins &= ~BPP_PP_nAutoFd; | ||
| 540 | set_pins(pins, minor); | ||
| 541 | |||
| 542 | /* Event 39: Set pins for reverse mode. */ | ||
| 543 | snooze(TIME_PSetup, minor); | ||
| 544 | set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); | ||
| 545 | |||
| 546 | /* Wait for event 40: Peripheral ready to be strobed */ | ||
| 547 | rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor); | ||
| 548 | if (rc == -1) return -ETIMEDOUT; | ||
| 549 | } | ||
| 550 | |||
| 551 | remaining = cnt; | ||
| 552 | |||
| 553 | while (remaining > 0) { | ||
| 554 | |||
| 555 | /* If there is a run length for a repeated byte, repeat */ | ||
| 556 | /* that byte a few times. */ | ||
| 557 | if (instances[minor].run_length && !instances[minor].run_flag) { | ||
| 558 | |||
| 559 | char buffer[128]; | ||
| 560 | unsigned idx; | ||
| 561 | unsigned repeat = remaining < instances[minor].run_length | ||
| 562 | ? remaining | ||
| 563 | : instances[minor].run_length; | ||
| 564 | |||
| 565 | for (idx = 0 ; idx < repeat ; idx += 1) | ||
| 566 | buffer[idx] = instances[minor].repeat_byte; | ||
| 567 | |||
| 568 | if (copy_to_user(c, buffer, repeat)) | ||
| 569 | return -EFAULT; | ||
| 570 | remaining -= repeat; | ||
| 571 | c += repeat; | ||
| 572 | instances[minor].run_length -= repeat; | ||
| 573 | } | ||
| 574 | |||
| 575 | if (remaining == 0) break; | ||
| 576 | |||
| 577 | |||
| 578 | /* Wait for Event 43: Data active on the bus. */ | ||
| 579 | rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); | ||
| 580 | if (rc == -1) break; | ||
| 581 | |||
| 582 | if (rc & BPP_GP_Busy) { | ||
| 583 | /* OK, this is data. read it in. */ | ||
| 584 | unsigned char byte = bpp_inb(base_addrs[minor]); | ||
| 585 | if (put_user(byte, c)) | ||
| 586 | return -EFAULT; | ||
| 587 | c += 1; | ||
| 588 | remaining -= 1; | ||
| 589 | |||
| 590 | if (instances[minor].run_flag) { | ||
| 591 | instances[minor].repeat_byte = byte; | ||
| 592 | instances[minor].run_flag = 0; | ||
| 593 | } | ||
| 594 | |||
| 595 | } else { | ||
| 596 | unsigned char byte = bpp_inb(base_addrs[minor]); | ||
| 597 | if (byte & 0x80) { | ||
| 598 | printk("bpp%d: " | ||
| 599 | "Ignoring ECP channel %u from device.\n", | ||
| 600 | minor, byte & 0x7f); | ||
| 601 | } else { | ||
| 602 | instances[minor].run_length = byte; | ||
| 603 | instances[minor].run_flag = 1; | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | /* Event 44: I got it. */ | ||
| 608 | set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor); | ||
| 609 | |||
| 610 | /* Wait for event 45: peripheral handshake */ | ||
| 611 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
| 612 | if (rc == -1) return -ETIMEDOUT; | ||
| 613 | |||
| 614 | /* Event 46: Finish handshake */ | ||
| 615 | set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); | ||
| 616 | |||
| 617 | } | ||
| 618 | |||
| 619 | |||
| 620 | return cnt - remaining; | ||
| 621 | } | ||
| 622 | |||
| 623 | static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos) | ||
| 624 | { | ||
| 625 | long rc; | ||
| 626 | unsigned minor = iminor(f->f_path.dentry->d_inode); | ||
| 627 | if (minor >= BPP_NO) return -ENODEV; | ||
| 628 | if (!instances[minor].present) return -ENODEV; | ||
| 629 | |||
| 630 | switch (instances[minor].mode) { | ||
| 631 | |||
| 632 | default: | ||
| 633 | if (instances[minor].mode != COMPATIBILITY) | ||
| 634 | terminate(minor); | ||
| 635 | |||
| 636 | if (instances[minor].enhanced) { | ||
| 637 | /* For now, do all reads with ECP-RLE mode */ | ||
| 638 | unsigned short pins; | ||
| 639 | |||
| 640 | rc = negotiate(DEFAULT_ECP, minor); | ||
| 641 | if (rc < 0) break; | ||
| 642 | |||
| 643 | instances[minor].mode = ECP_RLE; | ||
| 644 | |||
| 645 | /* Event 30: set nAutoFd low to setup for ECP mode */ | ||
| 646 | pins = get_pins(minor); | ||
| 647 | pins &= ~BPP_PP_nAutoFd; | ||
| 648 | set_pins(pins, minor); | ||
| 649 | |||
| 650 | /* Wait for Event 31: peripheral ready */ | ||
| 651 | rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); | ||
| 652 | if (rc == -1) return -ETIMEDOUT; | ||
| 653 | |||
| 654 | rc = read_ecp(minor, c, cnt); | ||
| 655 | |||
| 656 | } else { | ||
| 657 | rc = negotiate(DEFAULT_NIBBLE, minor); | ||
| 658 | if (rc < 0) break; | ||
| 659 | |||
| 660 | instances[minor].mode = NIBBLE; | ||
| 661 | |||
| 662 | rc = read_nibble(minor, c, cnt); | ||
| 663 | } | ||
| 664 | break; | ||
| 665 | |||
| 666 | case NIBBLE: | ||
| 667 | rc = read_nibble(minor, c, cnt); | ||
| 668 | break; | ||
| 669 | |||
| 670 | case ECP: | ||
| 671 | case ECP_RLE: | ||
| 672 | rc = read_ecp(minor, c, cnt); | ||
| 673 | break; | ||
| 674 | |||
| 675 | } | ||
| 676 | |||
| 677 | |||
| 678 | return rc; | ||
| 679 | } | ||
| 680 | |||
| 681 | /* | ||
| 682 | * Compatibility mode handshaking is a matter of writing data, | ||
| 683 | * strobing it, and waiting for the printer to stop being busy. | ||
| 684 | */ | ||
| 685 | static long write_compat(unsigned minor, const char __user *c, unsigned long cnt) | ||
| 686 | { | ||
| 687 | long rc; | ||
| 688 | unsigned short pins = get_pins(minor); | ||
| 689 | |||
| 690 | unsigned long remaining = cnt; | ||
| 691 | |||
| 692 | |||
| 693 | while (remaining > 0) { | ||
| 694 | unsigned char byte; | ||
| 695 | |||
| 696 | if (get_user(byte, c)) | ||
| 697 | return -EFAULT; | ||
| 698 | c += 1; | ||
| 699 | |||
| 700 | rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); | ||
| 701 | if (rc == -1) return -ETIMEDOUT; | ||
| 702 | |||
| 703 | bpp_outb_p(byte, base_addrs[minor]); | ||
| 704 | remaining -= 1; | ||
| 705 | /* snooze(1, minor); */ | ||
| 706 | |||
| 707 | pins &= ~BPP_PP_nStrobe; | ||
| 708 | set_pins(pins, minor); | ||
| 709 | |||
| 710 | rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); | ||
| 711 | |||
| 712 | pins |= BPP_PP_nStrobe; | ||
| 713 | set_pins(pins, minor); | ||
| 714 | } | ||
| 715 | |||
| 716 | return cnt - remaining; | ||
| 717 | } | ||
| 718 | |||
| 719 | /* | ||
| 720 | * Write data using ECP mode. Watch out that the port may be set up | ||
| 721 | * for reading. If so, turn the port around. | ||
| 722 | */ | ||
| 723 | static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) | ||
| 724 | { | ||
| 725 | unsigned short pins = get_pins(minor); | ||
| 726 | unsigned long remaining = cnt; | ||
| 727 | |||
| 728 | if (instances[minor].direction) { | ||
| 729 | int rc; | ||
| 730 | |||
| 731 | /* Event 47 Request bus be turned around */ | ||
| 732 | pins |= BPP_PP_nInit; | ||
| 733 | set_pins(pins, minor); | ||
| 734 | |||
| 735 | /* Wait for Event 49: Peripheral relinquished bus */ | ||
| 736 | rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); | ||
| 737 | |||
| 738 | pins |= BPP_PP_nAutoFd; | ||
| 739 | instances[minor].direction = 0; | ||
| 740 | set_pins(pins, minor); | ||
| 741 | } | ||
| 742 | |||
| 743 | while (remaining > 0) { | ||
| 744 | unsigned char byte; | ||
| 745 | int rc; | ||
| 746 | |||
| 747 | if (get_user(byte, c)) | ||
| 748 | return -EFAULT; | ||
| 749 | |||
| 750 | rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); | ||
| 751 | if (rc == -1) return -ETIMEDOUT; | ||
| 752 | |||
| 753 | c += 1; | ||
| 754 | |||
| 755 | bpp_outb_p(byte, base_addrs[minor]); | ||
| 756 | |||
| 757 | pins &= ~BPP_PP_nStrobe; | ||
| 758 | set_pins(pins, minor); | ||
| 759 | |||
| 760 | pins |= BPP_PP_nStrobe; | ||
| 761 | rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); | ||
| 762 | if (rc == -1) return -EIO; | ||
| 763 | |||
| 764 | set_pins(pins, minor); | ||
| 765 | } | ||
| 766 | |||
| 767 | return cnt - remaining; | ||
| 768 | } | ||
| 769 | |||
| 770 | /* | ||
| 771 | * Write to the peripheral. Be sensitive of the current mode. If I'm | ||
| 772 | * in a mode that can be turned around (ECP) then just do | ||
| 773 | * that. Otherwise, terminate and do my writing in compat mode. This | ||
| 774 | * is the safest course as any device can handle it. | ||
| 775 | */ | ||
| 776 | static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos) | ||
| 777 | { | ||
| 778 | long errno = 0; | ||
| 779 | unsigned minor = iminor(f->f_path.dentry->d_inode); | ||
| 780 | if (minor >= BPP_NO) return -ENODEV; | ||
| 781 | if (!instances[minor].present) return -ENODEV; | ||
| 782 | |||
| 783 | switch (instances[minor].mode) { | ||
| 784 | |||
| 785 | case ECP: | ||
| 786 | case ECP_RLE: | ||
| 787 | errno = write_ecp(minor, c, cnt); | ||
| 788 | break; | ||
| 789 | case COMPATIBILITY: | ||
| 790 | errno = write_compat(minor, c, cnt); | ||
| 791 | break; | ||
| 792 | default: | ||
| 793 | terminate(minor); | ||
| 794 | errno = write_compat(minor, c, cnt); | ||
| 795 | } | ||
| 796 | |||
| 797 | return errno; | ||
| 798 | } | ||
| 799 | |||
| 800 | static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, | ||
| 801 | unsigned long arg) | ||
| 802 | { | ||
| 803 | int errno = 0; | ||
| 804 | |||
| 805 | unsigned minor = iminor(inode); | ||
| 806 | if (minor >= BPP_NO) return -ENODEV; | ||
| 807 | if (!instances[minor].present) return -ENODEV; | ||
| 808 | |||
| 809 | |||
| 810 | switch (cmd) { | ||
| 811 | |||
| 812 | case BPP_PUT_PINS: | ||
| 813 | set_pins(arg, minor); | ||
| 814 | break; | ||
| 815 | |||
| 816 | case BPP_GET_PINS: | ||
| 817 | errno = get_pins(minor); | ||
| 818 | break; | ||
| 819 | |||
| 820 | case BPP_PUT_DATA: | ||
| 821 | bpp_outb_p(arg, base_addrs[minor]); | ||
| 822 | break; | ||
| 823 | |||
| 824 | case BPP_GET_DATA: | ||
| 825 | errno = bpp_inb_p(base_addrs[minor]); | ||
| 826 | break; | ||
| 827 | |||
| 828 | case BPP_SET_INPUT: | ||
| 829 | if (arg) | ||
| 830 | if (instances[minor].enhanced) { | ||
| 831 | unsigned short bits = get_pins(minor); | ||
| 832 | instances[minor].direction = 0x20; | ||
| 833 | set_pins(bits, minor); | ||
| 834 | } else { | ||
| 835 | errno = -ENOTTY; | ||
| 836 | } | ||
| 837 | else { | ||
| 838 | unsigned short bits = get_pins(minor); | ||
| 839 | instances[minor].direction = 0x00; | ||
| 840 | set_pins(bits, minor); | ||
| 841 | } | ||
| 842 | break; | ||
| 843 | |||
| 844 | default: | ||
| 845 | errno = -EINVAL; | ||
| 846 | } | ||
| 847 | |||
| 848 | return errno; | ||
| 849 | } | ||
| 850 | |||
| 851 | static const struct file_operations bpp_fops = { | ||
| 852 | .owner = THIS_MODULE, | ||
| 853 | .read = bpp_read, | ||
| 854 | .write = bpp_write, | ||
| 855 | .ioctl = bpp_ioctl, | ||
| 856 | .open = bpp_open, | ||
| 857 | .release = bpp_release, | ||
| 858 | }; | ||
| 859 | |||
| 860 | #if defined(__i386__) | ||
| 861 | |||
| 862 | #define collectLptPorts() {} | ||
| 863 | |||
| 864 | static void probeLptPort(unsigned idx) | ||
| 865 | { | ||
| 866 | unsigned int testvalue; | ||
| 867 | const unsigned short lpAddr = base_addrs[idx]; | ||
| 868 | |||
| 869 | instances[idx].present = 0; | ||
| 870 | instances[idx].enhanced = 0; | ||
| 871 | instances[idx].direction = 0; | ||
| 872 | instances[idx].mode = COMPATIBILITY; | ||
| 873 | instances[idx].run_length = 0; | ||
| 874 | instances[idx].run_flag = 0; | ||
| 875 | if (!request_region(lpAddr,3, bpp_dev_name)) return; | ||
| 876 | |||
| 877 | /* | ||
| 878 | * First, make sure the instance exists. Do this by writing to | ||
| 879 | * the data latch and reading the value back. If the port *is* | ||
| 880 | * present, test to see if it supports extended-mode | ||
| 881 | * operation. This will be required for IEEE1284 reverse | ||
| 882 | * transfers. | ||
| 883 | */ | ||
| 884 | |||
| 885 | outb_p(BPP_PROBE_CODE, lpAddr); | ||
| 886 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
| 887 | ; | ||
| 888 | testvalue = inb_p(lpAddr); | ||
| 889 | if (testvalue == BPP_PROBE_CODE) { | ||
| 890 | unsigned save; | ||
| 891 | instances[idx].present = 1; | ||
| 892 | |||
| 893 | save = inb_p(lpAddr+2); | ||
| 894 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
| 895 | ; | ||
| 896 | outb_p(save|0x20, lpAddr+2); | ||
| 897 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
| 898 | ; | ||
| 899 | outb_p(~BPP_PROBE_CODE, lpAddr); | ||
| 900 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
| 901 | ; | ||
| 902 | testvalue = inb_p(lpAddr); | ||
| 903 | if ((testvalue&0xff) == (0xff&~BPP_PROBE_CODE)) | ||
| 904 | instances[idx].enhanced = 0; | ||
| 905 | else | ||
| 906 | instances[idx].enhanced = 1; | ||
| 907 | outb_p(save, lpAddr+2); | ||
| 908 | } | ||
| 909 | else { | ||
| 910 | release_region(lpAddr,3); | ||
| 911 | } | ||
| 912 | /* | ||
| 913 | * Leave the port in compat idle mode. | ||
| 914 | */ | ||
| 915 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); | ||
| 916 | |||
| 917 | printk("bpp%d: Port at 0x%03x: Enhanced mode %s\n", idx, base_addrs[idx], | ||
| 918 | instances[idx].enhanced? "SUPPORTED" : "UNAVAILABLE"); | ||
| 919 | } | ||
| 920 | |||
| 921 | static inline void freeLptPort(int idx) | ||
| 922 | { | ||
| 923 | release_region(base_addrs[idx], 3); | ||
| 924 | } | ||
| 925 | |||
| 926 | #endif | ||
| 927 | |||
| 928 | #if defined(__sparc__) | ||
| 929 | |||
| 930 | static void __iomem *map_bpp(struct sbus_dev *dev, int idx) | ||
| 931 | { | ||
| 932 | return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp"); | ||
| 933 | } | ||
| 934 | |||
| 935 | static int collectLptPorts(void) | ||
| 936 | { | ||
| 937 | struct sbus_bus *bus; | ||
| 938 | struct sbus_dev *dev; | ||
| 939 | int count; | ||
| 940 | |||
| 941 | count = 0; | ||
| 942 | for_all_sbusdev(dev, bus) { | ||
| 943 | if (strcmp(dev->prom_name, "SUNW,bpp") == 0) { | ||
| 944 | if (count >= BPP_NO) { | ||
| 945 | printk(KERN_NOTICE | ||
| 946 | "bpp: More than %d bpp ports," | ||
| 947 | " rest is ignored\n", BPP_NO); | ||
| 948 | return count; | ||
| 949 | } | ||
| 950 | base_addrs[count] = map_bpp(dev, count); | ||
| 951 | count++; | ||
| 952 | } | ||
| 953 | } | ||
| 954 | return count; | ||
| 955 | } | ||
| 956 | |||
| 957 | static void probeLptPort(unsigned idx) | ||
| 958 | { | ||
| 959 | void __iomem *rp = base_addrs[idx]; | ||
| 960 | __u32 csr; | ||
| 961 | char *brand; | ||
| 962 | |||
| 963 | instances[idx].present = 0; | ||
| 964 | instances[idx].enhanced = 0; | ||
| 965 | instances[idx].direction = 0; | ||
| 966 | instances[idx].mode = COMPATIBILITY; | ||
| 967 | instances[idx].run_length = 0; | ||
| 968 | instances[idx].run_flag = 0; | ||
| 969 | |||
| 970 | if (!rp) return; | ||
| 971 | |||
| 972 | instances[idx].present = 1; | ||
| 973 | instances[idx].enhanced = 1; /* Sure */ | ||
| 974 | |||
| 975 | csr = sbus_readl(rp + BPP_CSR); | ||
| 976 | if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { | ||
| 977 | udelay(20); | ||
| 978 | csr = sbus_readl(rp + BPP_CSR); | ||
| 979 | if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { | ||
| 980 | printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); | ||
| 981 | } | ||
| 982 | } | ||
| 983 | printk("bpp%d: reset with 0x%08x ..", idx, csr); | ||
| 984 | sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR); | ||
| 985 | udelay(500); | ||
| 986 | sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR); | ||
| 987 | csr = sbus_readl(rp + BPP_CSR); | ||
| 988 | printk(" done with csr=0x%08x ocr=0x%04x\n", | ||
| 989 | csr, sbus_readw(rp + BPP_OCR)); | ||
| 990 | |||
| 991 | switch (csr & P_DEV_ID_MASK) { | ||
| 992 | case P_DEV_ID_ZEBRA: | ||
| 993 | brand = "Zebra"; | ||
| 994 | break; | ||
| 995 | case P_DEV_ID_L64854: | ||
| 996 | brand = "DMA2"; | ||
| 997 | break; | ||
| 998 | default: | ||
| 999 | brand = "Unknown"; | ||
| 1000 | } | ||
| 1001 | printk("bpp%d: %s at %p\n", idx, brand, rp); | ||
| 1002 | |||
| 1003 | /* | ||
| 1004 | * Leave the port in compat idle mode. | ||
| 1005 | */ | ||
| 1006 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); | ||
| 1007 | |||
| 1008 | return; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | static inline void freeLptPort(int idx) | ||
| 1012 | { | ||
| 1013 | sbus_iounmap(base_addrs[idx], BPP_SIZE); | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | #endif | ||
| 1017 | |||
| 1018 | static int __init bpp_init(void) | ||
| 1019 | { | ||
| 1020 | int rc; | ||
| 1021 | unsigned idx; | ||
| 1022 | |||
| 1023 | rc = collectLptPorts(); | ||
| 1024 | if (rc == 0) | ||
| 1025 | return -ENODEV; | ||
| 1026 | |||
| 1027 | rc = register_chrdev(BPP_MAJOR, bpp_dev_name, &bpp_fops); | ||
| 1028 | if (rc < 0) | ||
| 1029 | return rc; | ||
| 1030 | |||
| 1031 | for (idx = 0; idx < BPP_NO; idx++) { | ||
| 1032 | instances[idx].opened = 0; | ||
| 1033 | probeLptPort(idx); | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | return 0; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | static void __exit bpp_cleanup(void) | ||
| 1040 | { | ||
| 1041 | unsigned idx; | ||
| 1042 | |||
| 1043 | unregister_chrdev(BPP_MAJOR, bpp_dev_name); | ||
| 1044 | |||
| 1045 | for (idx = 0; idx < BPP_NO; idx++) { | ||
| 1046 | if (instances[idx].present) | ||
| 1047 | freeLptPort(idx); | ||
| 1048 | } | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | module_init(bpp_init); | ||
| 1052 | module_exit(bpp_cleanup); | ||
| 1053 | |||
| 1054 | MODULE_LICENSE("GPL"); | ||
| 1055 | |||
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c deleted file mode 100644 index 23abfdfb44f1..000000000000 --- a/drivers/sbus/char/cpwatchdog.c +++ /dev/null | |||
| @@ -1,858 +0,0 @@ | |||
| 1 | /* cpwatchdog.c - driver implementation for hardware watchdog | ||
| 2 | * timers found on Sun Microsystems CP1400 and CP1500 boards. | ||
| 3 | * | ||
| 4 | * This device supports both the generic Linux watchdog | ||
| 5 | * interface and Solaris-compatible ioctls as best it is | ||
| 6 | * able. | ||
| 7 | * | ||
| 8 | * NOTE: CP1400 systems appear to have a defective intr_mask | ||
| 9 | * register on the PLD, preventing the disabling of | ||
| 10 | * timer interrupts. We use a timer to periodically | ||
| 11 | * reset 'stopped' watchdogs on affected platforms. | ||
| 12 | * | ||
| 13 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/fs.h> | ||
| 19 | #include <linux/errno.h> | ||
| 20 | #include <linux/major.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | #include <linux/miscdevice.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/timer.h> | ||
| 26 | #include <linux/smp_lock.h> | ||
| 27 | #include <linux/io.h> | ||
| 28 | #include <asm/irq.h> | ||
| 29 | #include <asm/ebus.h> | ||
| 30 | #include <asm/oplib.h> | ||
| 31 | #include <asm/uaccess.h> | ||
| 32 | |||
| 33 | #include <asm/watchdog.h> | ||
| 34 | |||
| 35 | #define WD_OBPNAME "watchdog" | ||
| 36 | #define WD_BADMODEL "SUNW,501-5336" | ||
| 37 | #define WD_BTIMEOUT (jiffies + (HZ * 1000)) | ||
| 38 | #define WD_BLIMIT 0xFFFF | ||
| 39 | |||
| 40 | #define WD0_DEVNAME "watchdog0" | ||
| 41 | #define WD1_DEVNAME "watchdog1" | ||
| 42 | #define WD2_DEVNAME "watchdog2" | ||
| 43 | |||
| 44 | #define WD0_MINOR 212 | ||
| 45 | #define WD1_MINOR 213 | ||
| 46 | #define WD2_MINOR 214 | ||
| 47 | |||
| 48 | |||
| 49 | /* Internal driver definitions | ||
| 50 | */ | ||
| 51 | #define WD0_ID 0 /* Watchdog0 */ | ||
| 52 | #define WD1_ID 1 /* Watchdog1 */ | ||
| 53 | #define WD2_ID 2 /* Watchdog2 */ | ||
| 54 | #define WD_NUMDEVS 3 /* Device contains 3 timers */ | ||
| 55 | |||
| 56 | #define WD_INTR_OFF 0 /* Interrupt disable value */ | ||
| 57 | #define WD_INTR_ON 1 /* Interrupt enable value */ | ||
| 58 | |||
| 59 | #define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */ | ||
| 60 | #define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */ | ||
| 61 | #define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */ | ||
| 62 | |||
| 63 | /* Register value definitions | ||
| 64 | */ | ||
| 65 | #define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */ | ||
| 66 | #define WD1_INTR_MASK 0x02 | ||
| 67 | #define WD2_INTR_MASK 0x04 | ||
| 68 | |||
| 69 | #define WD_S_RUNNING 0x01 /* Watchdog device status running */ | ||
| 70 | #define WD_S_EXPIRED 0x02 /* Watchdog device status expired */ | ||
| 71 | |||
| 72 | /* Sun uses Altera PLD EPF8820ATC144-4 | ||
| 73 | * providing three hardware watchdogs: | ||
| 74 | * | ||
| 75 | * 1) RIC - sends an interrupt when triggered | ||
| 76 | * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU | ||
| 77 | * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board | ||
| 78 | * | ||
| 79 | *** Timer register block definition (struct wd_timer_regblk) | ||
| 80 | * | ||
| 81 | * dcntr and limit registers (halfword access): | ||
| 82 | * ------------------- | ||
| 83 | * | 15 | ...| 1 | 0 | | ||
| 84 | * ------------------- | ||
| 85 | * |- counter val -| | ||
| 86 | * ------------------- | ||
| 87 | * dcntr - Current 16-bit downcounter value. | ||
| 88 | * When downcounter reaches '0' watchdog expires. | ||
| 89 | * Reading this register resets downcounter with 'limit' value. | ||
| 90 | * limit - 16-bit countdown value in 1/10th second increments. | ||
| 91 | * Writing this register begins countdown with input value. | ||
| 92 | * Reading from this register does not affect counter. | ||
| 93 | * NOTES: After watchdog reset, dcntr and limit contain '1' | ||
| 94 | * | ||
| 95 | * status register (byte access): | ||
| 96 | * --------------------------- | ||
| 97 | * | 7 | ... | 2 | 1 | 0 | | ||
| 98 | * --------------+------------ | ||
| 99 | * |- UNUSED -| EXP | RUN | | ||
| 100 | * --------------------------- | ||
| 101 | * status- Bit 0 - Watchdog is running | ||
| 102 | * Bit 1 - Watchdog has expired | ||
| 103 | * | ||
| 104 | *** PLD register block definition (struct wd_pld_regblk) | ||
| 105 | * | ||
| 106 | * intr_mask register (byte access): | ||
| 107 | * --------------------------------- | ||
| 108 | * | 7 | ... | 3 | 2 | 1 | 0 | | ||
| 109 | * +-------------+------------------ | ||
| 110 | * |- UNUSED -| WD3 | WD2 | WD1 | | ||
| 111 | * --------------------------------- | ||
| 112 | * WD3 - 1 == Interrupt disabled for watchdog 3 | ||
| 113 | * WD2 - 1 == Interrupt disabled for watchdog 2 | ||
| 114 | * WD1 - 1 == Interrupt disabled for watchdog 1 | ||
| 115 | * | ||
| 116 | * pld_status register (byte access): | ||
| 117 | * UNKNOWN, MAGICAL MYSTERY REGISTER | ||
| 118 | * | ||
| 119 | */ | ||
| 120 | #define WD_TIMER_REGSZ 16 | ||
| 121 | #define WD0_OFF 0 | ||
| 122 | #define WD1_OFF (WD_TIMER_REGSZ * 1) | ||
| 123 | #define WD2_OFF (WD_TIMER_REGSZ * 2) | ||
| 124 | #define PLD_OFF (WD_TIMER_REGSZ * 3) | ||
| 125 | |||
| 126 | #define WD_DCNTR 0x00 | ||
| 127 | #define WD_LIMIT 0x04 | ||
| 128 | #define WD_STATUS 0x08 | ||
| 129 | |||
| 130 | #define PLD_IMASK (PLD_OFF + 0x00) | ||
| 131 | #define PLD_STATUS (PLD_OFF + 0x04) | ||
| 132 | |||
| 133 | /* Individual timer structure | ||
| 134 | */ | ||
| 135 | struct wd_timer { | ||
| 136 | __u16 timeout; | ||
| 137 | __u8 intr_mask; | ||
| 138 | unsigned char runstatus; | ||
| 139 | void __iomem *regs; | ||
| 140 | }; | ||
| 141 | |||
| 142 | /* Device structure | ||
| 143 | */ | ||
| 144 | struct wd_device { | ||
| 145 | int irq; | ||
| 146 | spinlock_t lock; | ||
| 147 | unsigned char isbaddoggie; /* defective PLD */ | ||
| 148 | unsigned char opt_enable; | ||
| 149 | unsigned char opt_reboot; | ||
| 150 | unsigned short opt_timeout; | ||
| 151 | unsigned char initialized; | ||
| 152 | struct wd_timer watchdog[WD_NUMDEVS]; | ||
| 153 | void __iomem *regs; | ||
| 154 | }; | ||
| 155 | |||
| 156 | static struct wd_device wd_dev = { | ||
| 157 | 0, __SPIN_LOCK_UNLOCKED(wd_dev.lock), 0, 0, 0, 0, | ||
| 158 | }; | ||
| 159 | |||
| 160 | static struct timer_list wd_timer; | ||
| 161 | |||
| 162 | static int wd0_timeout = 0; | ||
| 163 | static int wd1_timeout = 0; | ||
| 164 | static int wd2_timeout = 0; | ||
| 165 | |||
| 166 | #ifdef MODULE | ||
| 167 | module_param (wd0_timeout, int, 0); | ||
| 168 | MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); | ||
| 169 | module_param (wd1_timeout, int, 0); | ||
| 170 | MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); | ||
| 171 | module_param (wd2_timeout, int, 0); | ||
| 172 | MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); | ||
| 173 | |||
| 174 | MODULE_AUTHOR | ||
| 175 | ("Eric Brower <ebrower@usa.net>"); | ||
| 176 | MODULE_DESCRIPTION | ||
| 177 | ("Hardware watchdog driver for Sun Microsystems CP1400/1500"); | ||
| 178 | MODULE_LICENSE("GPL"); | ||
| 179 | MODULE_SUPPORTED_DEVICE | ||
| 180 | ("watchdog"); | ||
| 181 | #endif /* ifdef MODULE */ | ||
| 182 | |||
| 183 | /* Forward declarations of internal methods | ||
| 184 | */ | ||
| 185 | #ifdef WD_DEBUG | ||
| 186 | static void wd_dumpregs(void); | ||
| 187 | #endif | ||
| 188 | static irqreturn_t wd_interrupt(int irq, void *dev_id); | ||
| 189 | static void wd_toggleintr(struct wd_timer* pTimer, int enable); | ||
| 190 | static void wd_pingtimer(struct wd_timer* pTimer); | ||
| 191 | static void wd_starttimer(struct wd_timer* pTimer); | ||
| 192 | static void wd_resetbrokentimer(struct wd_timer* pTimer); | ||
| 193 | static void wd_stoptimer(struct wd_timer* pTimer); | ||
| 194 | static void wd_brokentimer(unsigned long data); | ||
| 195 | static int wd_getstatus(struct wd_timer* pTimer); | ||
| 196 | |||
| 197 | /* PLD expects words to be written in LSB format, | ||
| 198 | * so we must flip all words prior to writing them to regs | ||
| 199 | */ | ||
| 200 | static inline unsigned short flip_word(unsigned short word) | ||
| 201 | { | ||
| 202 | return ((word & 0xff) << 8) | ((word >> 8) & 0xff); | ||
| 203 | } | ||
| 204 | |||
| 205 | #define wd_writew(val, addr) (writew(flip_word(val), addr)) | ||
| 206 | #define wd_readw(addr) (flip_word(readw(addr))) | ||
| 207 | #define wd_writeb(val, addr) (writeb(val, addr)) | ||
| 208 | #define wd_readb(addr) (readb(addr)) | ||
| 209 | |||
| 210 | |||
| 211 | /* CP1400s seem to have broken PLD implementations-- | ||
| 212 | * the interrupt_mask register cannot be written, so | ||
| 213 | * no timer interrupts can be masked within the PLD. | ||
| 214 | */ | ||
| 215 | static inline int wd_isbroken(void) | ||
| 216 | { | ||
| 217 | /* we could test this by read/write/read/restore | ||
| 218 | * on the interrupt mask register only if OBP | ||
| 219 | * 'watchdog-enable?' == FALSE, but it seems | ||
| 220 | * ubiquitous on CP1400s | ||
| 221 | */ | ||
| 222 | char val[32]; | ||
| 223 | prom_getproperty(prom_root_node, "model", val, sizeof(val)); | ||
| 224 | return((!strcmp(val, WD_BADMODEL)) ? 1 : 0); | ||
| 225 | } | ||
| 226 | |||
| 227 | /* Retrieve watchdog-enable? option from OBP | ||
| 228 | * Returns 0 if false, 1 if true | ||
| 229 | */ | ||
| 230 | static inline int wd_opt_enable(void) | ||
| 231 | { | ||
| 232 | int opt_node; | ||
| 233 | |||
| 234 | opt_node = prom_getchild(prom_root_node); | ||
| 235 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
| 236 | return((-1 == prom_getint(opt_node, "watchdog-enable?")) ? 0 : 1); | ||
| 237 | } | ||
| 238 | |||
| 239 | /* Retrieve watchdog-reboot? option from OBP | ||
| 240 | * Returns 0 if false, 1 if true | ||
| 241 | */ | ||
| 242 | static inline int wd_opt_reboot(void) | ||
| 243 | { | ||
| 244 | int opt_node; | ||
| 245 | |||
| 246 | opt_node = prom_getchild(prom_root_node); | ||
| 247 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
| 248 | return((-1 == prom_getint(opt_node, "watchdog-reboot?")) ? 0 : 1); | ||
| 249 | } | ||
| 250 | |||
| 251 | /* Retrieve watchdog-timeout option from OBP | ||
| 252 | * Returns OBP value, or 0 if not located | ||
| 253 | */ | ||
| 254 | static inline int wd_opt_timeout(void) | ||
| 255 | { | ||
| 256 | int opt_node; | ||
| 257 | char value[32]; | ||
| 258 | char *p = value; | ||
| 259 | |||
| 260 | opt_node = prom_getchild(prom_root_node); | ||
| 261 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
| 262 | opt_node = prom_getproperty(opt_node, | ||
| 263 | "watchdog-timeout", | ||
| 264 | value, | ||
| 265 | sizeof(value)); | ||
| 266 | if(-1 != opt_node) { | ||
| 267 | /* atoi implementation */ | ||
| 268 | for(opt_node = 0; /* nop */; p++) { | ||
| 269 | if(*p >= '0' && *p <= '9') { | ||
| 270 | opt_node = (10*opt_node)+(*p-'0'); | ||
| 271 | } | ||
| 272 | else { | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | } | ||
| 277 | return((-1 == opt_node) ? (0) : (opt_node)); | ||
| 278 | } | ||
| 279 | |||
| 280 | static int wd_open(struct inode *inode, struct file *f) | ||
| 281 | { | ||
| 282 | lock_kernel(); | ||
| 283 | switch(iminor(inode)) | ||
| 284 | { | ||
| 285 | case WD0_MINOR: | ||
| 286 | f->private_data = &wd_dev.watchdog[WD0_ID]; | ||
| 287 | break; | ||
| 288 | case WD1_MINOR: | ||
| 289 | f->private_data = &wd_dev.watchdog[WD1_ID]; | ||
| 290 | break; | ||
| 291 | case WD2_MINOR: | ||
| 292 | f->private_data = &wd_dev.watchdog[WD2_ID]; | ||
| 293 | break; | ||
| 294 | default: | ||
| 295 | unlock_kernel(); | ||
| 296 | return(-ENODEV); | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Register IRQ on first open of device */ | ||
| 300 | if(0 == wd_dev.initialized) | ||
| 301 | { | ||
| 302 | if (request_irq(wd_dev.irq, | ||
| 303 | &wd_interrupt, | ||
| 304 | IRQF_SHARED, | ||
| 305 | WD_OBPNAME, | ||
| 306 | (void *)wd_dev.regs)) { | ||
| 307 | printk("%s: Cannot register IRQ %d\n", | ||
| 308 | WD_OBPNAME, wd_dev.irq); | ||
| 309 | unlock_kernel(); | ||
| 310 | return(-EBUSY); | ||
| 311 | } | ||
| 312 | wd_dev.initialized = 1; | ||
| 313 | } | ||
| 314 | |||
| 315 | unlock_kernel(); | ||
| 316 | return(nonseekable_open(inode, f)); | ||
| 317 | } | ||
| 318 | |||
| 319 | static int wd_release(struct inode *inode, struct file *file) | ||
| 320 | { | ||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static int wd_ioctl(struct inode *inode, struct file *file, | ||
| 325 | unsigned int cmd, unsigned long arg) | ||
| 326 | { | ||
| 327 | int setopt = 0; | ||
| 328 | struct wd_timer* pTimer = (struct wd_timer*)file->private_data; | ||
| 329 | void __user *argp = (void __user *)arg; | ||
| 330 | struct watchdog_info info = { | ||
| 331 | 0, | ||
| 332 | 0, | ||
| 333 | "Altera EPF8820ATC144-4" | ||
| 334 | }; | ||
| 335 | |||
| 336 | if(NULL == pTimer) { | ||
| 337 | return(-EINVAL); | ||
| 338 | } | ||
| 339 | |||
| 340 | switch(cmd) | ||
| 341 | { | ||
| 342 | /* Generic Linux IOCTLs */ | ||
| 343 | case WDIOC_GETSUPPORT: | ||
| 344 | if(copy_to_user(argp, &info, sizeof(struct watchdog_info))) { | ||
| 345 | return(-EFAULT); | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | case WDIOC_GETSTATUS: | ||
| 349 | case WDIOC_GETBOOTSTATUS: | ||
| 350 | if (put_user(0, (int __user *)argp)) | ||
| 351 | return -EFAULT; | ||
| 352 | break; | ||
| 353 | case WDIOC_KEEPALIVE: | ||
| 354 | wd_pingtimer(pTimer); | ||
| 355 | break; | ||
| 356 | case WDIOC_SETOPTIONS: | ||
| 357 | if(copy_from_user(&setopt, argp, sizeof(unsigned int))) { | ||
| 358 | return -EFAULT; | ||
| 359 | } | ||
| 360 | if(setopt & WDIOS_DISABLECARD) { | ||
| 361 | if(wd_dev.opt_enable) { | ||
| 362 | printk( | ||
| 363 | "%s: cannot disable watchdog in ENABLED mode\n", | ||
| 364 | WD_OBPNAME); | ||
| 365 | return(-EINVAL); | ||
| 366 | } | ||
| 367 | wd_stoptimer(pTimer); | ||
| 368 | } | ||
| 369 | else if(setopt & WDIOS_ENABLECARD) { | ||
| 370 | wd_starttimer(pTimer); | ||
| 371 | } | ||
| 372 | else { | ||
| 373 | return(-EINVAL); | ||
| 374 | } | ||
| 375 | break; | ||
| 376 | /* Solaris-compatible IOCTLs */ | ||
| 377 | case WIOCGSTAT: | ||
| 378 | setopt = wd_getstatus(pTimer); | ||
| 379 | if(copy_to_user(argp, &setopt, sizeof(unsigned int))) { | ||
| 380 | return(-EFAULT); | ||
| 381 | } | ||
| 382 | break; | ||
| 383 | case WIOCSTART: | ||
| 384 | wd_starttimer(pTimer); | ||
| 385 | break; | ||
| 386 | case WIOCSTOP: | ||
| 387 | if(wd_dev.opt_enable) { | ||
| 388 | printk("%s: cannot disable watchdog in ENABLED mode\n", | ||
| 389 | WD_OBPNAME); | ||
| 390 | return(-EINVAL); | ||
| 391 | } | ||
| 392 | wd_stoptimer(pTimer); | ||
| 393 | break; | ||
| 394 | default: | ||
| 395 | return(-EINVAL); | ||
| 396 | } | ||
| 397 | return(0); | ||
| 398 | } | ||
| 399 | |||
| 400 | static long wd_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 401 | unsigned long arg) | ||
| 402 | { | ||
| 403 | int rval = -ENOIOCTLCMD; | ||
| 404 | |||
| 405 | switch (cmd) { | ||
| 406 | /* solaris ioctls are specific to this driver */ | ||
| 407 | case WIOCSTART: | ||
| 408 | case WIOCSTOP: | ||
| 409 | case WIOCGSTAT: | ||
| 410 | lock_kernel(); | ||
| 411 | rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | ||
| 412 | unlock_kernel(); | ||
| 413 | break; | ||
| 414 | /* everything else is handled by the generic compat layer */ | ||
| 415 | default: | ||
| 416 | break; | ||
| 417 | } | ||
| 418 | |||
| 419 | return rval; | ||
| 420 | } | ||
| 421 | |||
| 422 | static ssize_t wd_write(struct file *file, | ||
| 423 | const char __user *buf, | ||
| 424 | size_t count, | ||
| 425 | loff_t *ppos) | ||
| 426 | { | ||
| 427 | struct wd_timer* pTimer = (struct wd_timer*)file->private_data; | ||
| 428 | |||
| 429 | if(NULL == pTimer) { | ||
| 430 | return(-EINVAL); | ||
| 431 | } | ||
| 432 | |||
| 433 | if (count) { | ||
| 434 | wd_pingtimer(pTimer); | ||
| 435 | return 1; | ||
| 436 | } | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | |||
| 440 | static ssize_t wd_read(struct file * file, char __user *buffer, | ||
| 441 | size_t count, loff_t *ppos) | ||
| 442 | { | ||
| 443 | #ifdef WD_DEBUG | ||
| 444 | wd_dumpregs(); | ||
| 445 | return(0); | ||
| 446 | #else | ||
| 447 | return(-EINVAL); | ||
| 448 | #endif /* ifdef WD_DEBUG */ | ||
| 449 | } | ||
| 450 | |||
| 451 | static irqreturn_t wd_interrupt(int irq, void *dev_id) | ||
| 452 | { | ||
| 453 | /* Only WD0 will interrupt-- others are NMI and we won't | ||
| 454 | * see them here.... | ||
| 455 | */ | ||
| 456 | spin_lock_irq(&wd_dev.lock); | ||
| 457 | if((unsigned long)wd_dev.regs == (unsigned long)dev_id) | ||
| 458 | { | ||
| 459 | wd_stoptimer(&wd_dev.watchdog[WD0_ID]); | ||
| 460 | wd_dev.watchdog[WD0_ID].runstatus |= WD_STAT_SVCD; | ||
| 461 | } | ||
| 462 | spin_unlock_irq(&wd_dev.lock); | ||
| 463 | return IRQ_HANDLED; | ||
| 464 | } | ||
| 465 | |||
| 466 | static const struct file_operations wd_fops = { | ||
| 467 | .owner = THIS_MODULE, | ||
| 468 | .ioctl = wd_ioctl, | ||
| 469 | .compat_ioctl = wd_compat_ioctl, | ||
| 470 | .open = wd_open, | ||
| 471 | .write = wd_write, | ||
| 472 | .read = wd_read, | ||
| 473 | .release = wd_release, | ||
| 474 | }; | ||
| 475 | |||
| 476 | static struct miscdevice wd0_miscdev = { WD0_MINOR, WD0_DEVNAME, &wd_fops }; | ||
| 477 | static struct miscdevice wd1_miscdev = { WD1_MINOR, WD1_DEVNAME, &wd_fops }; | ||
| 478 | static struct miscdevice wd2_miscdev = { WD2_MINOR, WD2_DEVNAME, &wd_fops }; | ||
| 479 | |||
| 480 | #ifdef WD_DEBUG | ||
| 481 | static void wd_dumpregs(void) | ||
| 482 | { | ||
| 483 | /* Reading from downcounters initiates watchdog countdown-- | ||
| 484 | * Example is included below for illustration purposes. | ||
| 485 | */ | ||
| 486 | int i; | ||
| 487 | printk("%s: dumping register values\n", WD_OBPNAME); | ||
| 488 | for(i = WD0_ID; i < WD_NUMDEVS; ++i) { | ||
| 489 | /* printk("\t%s%i: dcntr at 0x%lx: 0x%x\n", | ||
| 490 | * WD_OBPNAME, | ||
| 491 | * i, | ||
| 492 | * (unsigned long)(&wd_dev.watchdog[i].regs->dcntr), | ||
| 493 | * readw(&wd_dev.watchdog[i].regs->dcntr)); | ||
| 494 | */ | ||
| 495 | printk("\t%s%i: limit at 0x%lx: 0x%x\n", | ||
| 496 | WD_OBPNAME, | ||
| 497 | i, | ||
| 498 | (unsigned long)(&wd_dev.watchdog[i].regs->limit), | ||
| 499 | readw(&wd_dev.watchdog[i].regs->limit)); | ||
| 500 | printk("\t%s%i: status at 0x%lx: 0x%x\n", | ||
| 501 | WD_OBPNAME, | ||
| 502 | i, | ||
| 503 | (unsigned long)(&wd_dev.watchdog[i].regs->status), | ||
| 504 | readb(&wd_dev.watchdog[i].regs->status)); | ||
| 505 | printk("\t%s%i: driver status: 0x%x\n", | ||
| 506 | WD_OBPNAME, | ||
| 507 | i, | ||
| 508 | wd_getstatus(&wd_dev.watchdog[i])); | ||
| 509 | } | ||
| 510 | printk("\tintr_mask at %p: 0x%x\n", | ||
| 511 | wd_dev.regs + PLD_IMASK, | ||
| 512 | readb(wd_dev.regs + PLD_IMASK)); | ||
| 513 | printk("\tpld_status at %p: 0x%x\n", | ||
| 514 | wd_dev.regs + PLD_STATUS, | ||
| 515 | readb(wd_dev.regs + PLD_STATUS)); | ||
| 516 | } | ||
| 517 | #endif | ||
| 518 | |||
| 519 | /* Enable or disable watchdog interrupts | ||
| 520 | * Because of the CP1400 defect this should only be | ||
| 521 | * called during initialzation or by wd_[start|stop]timer() | ||
| 522 | * | ||
| 523 | * pTimer - pointer to timer device, or NULL to indicate all timers | ||
| 524 | * enable - non-zero to enable interrupts, zero to disable | ||
| 525 | */ | ||
| 526 | static void wd_toggleintr(struct wd_timer* pTimer, int enable) | ||
| 527 | { | ||
| 528 | unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK); | ||
| 529 | unsigned char setregs = | ||
| 530 | (NULL == pTimer) ? | ||
| 531 | (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : | ||
| 532 | (pTimer->intr_mask); | ||
| 533 | |||
| 534 | (WD_INTR_ON == enable) ? | ||
| 535 | (curregs &= ~setregs): | ||
| 536 | (curregs |= setregs); | ||
| 537 | |||
| 538 | wd_writeb(curregs, wd_dev.regs + PLD_IMASK); | ||
| 539 | return; | ||
| 540 | } | ||
| 541 | |||
| 542 | /* Reset countdown timer with 'limit' value and continue countdown. | ||
| 543 | * This will not start a stopped timer. | ||
| 544 | * | ||
| 545 | * pTimer - pointer to timer device | ||
| 546 | */ | ||
| 547 | static void wd_pingtimer(struct wd_timer* pTimer) | ||
| 548 | { | ||
| 549 | if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { | ||
| 550 | wd_readw(pTimer->regs + WD_DCNTR); | ||
| 551 | } | ||
| 552 | } | ||
| 553 | |||
| 554 | /* Stop a running watchdog timer-- the timer actually keeps | ||
| 555 | * running, but the interrupt is masked so that no action is | ||
| 556 | * taken upon expiration. | ||
| 557 | * | ||
| 558 | * pTimer - pointer to timer device | ||
| 559 | */ | ||
| 560 | static void wd_stoptimer(struct wd_timer* pTimer) | ||
| 561 | { | ||
| 562 | if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { | ||
| 563 | wd_toggleintr(pTimer, WD_INTR_OFF); | ||
| 564 | |||
| 565 | if(wd_dev.isbaddoggie) { | ||
| 566 | pTimer->runstatus |= WD_STAT_BSTOP; | ||
| 567 | wd_brokentimer((unsigned long)&wd_dev); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | /* Start a watchdog timer with the specified limit value | ||
| 573 | * If the watchdog is running, it will be restarted with | ||
| 574 | * the provided limit value. | ||
| 575 | * | ||
| 576 | * This function will enable interrupts on the specified | ||
| 577 | * watchdog. | ||
| 578 | * | ||
| 579 | * pTimer - pointer to timer device | ||
| 580 | * limit - limit (countdown) value in 1/10th seconds | ||
| 581 | */ | ||
| 582 | static void wd_starttimer(struct wd_timer* pTimer) | ||
| 583 | { | ||
| 584 | if(wd_dev.isbaddoggie) { | ||
| 585 | pTimer->runstatus &= ~WD_STAT_BSTOP; | ||
| 586 | } | ||
| 587 | pTimer->runstatus &= ~WD_STAT_SVCD; | ||
| 588 | |||
| 589 | wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT); | ||
| 590 | wd_toggleintr(pTimer, WD_INTR_ON); | ||
| 591 | } | ||
| 592 | |||
| 593 | /* Restarts timer with maximum limit value and | ||
| 594 | * does not unset 'brokenstop' value. | ||
| 595 | */ | ||
| 596 | static void wd_resetbrokentimer(struct wd_timer* pTimer) | ||
| 597 | { | ||
| 598 | wd_toggleintr(pTimer, WD_INTR_ON); | ||
| 599 | wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT); | ||
| 600 | } | ||
| 601 | |||
| 602 | /* Timer device initialization helper. | ||
| 603 | * Returns 0 on success, other on failure | ||
| 604 | */ | ||
| 605 | static int wd_inittimer(int whichdog) | ||
| 606 | { | ||
| 607 | struct miscdevice *whichmisc; | ||
| 608 | void __iomem *whichregs; | ||
| 609 | char whichident[8]; | ||
| 610 | int whichmask; | ||
| 611 | __u16 whichlimit; | ||
| 612 | |||
| 613 | switch(whichdog) | ||
| 614 | { | ||
| 615 | case WD0_ID: | ||
| 616 | whichmisc = &wd0_miscdev; | ||
| 617 | strcpy(whichident, "RIC"); | ||
| 618 | whichregs = wd_dev.regs + WD0_OFF; | ||
| 619 | whichmask = WD0_INTR_MASK; | ||
| 620 | whichlimit= (0 == wd0_timeout) ? | ||
| 621 | (wd_dev.opt_timeout): | ||
| 622 | (wd0_timeout); | ||
| 623 | break; | ||
| 624 | case WD1_ID: | ||
| 625 | whichmisc = &wd1_miscdev; | ||
| 626 | strcpy(whichident, "XIR"); | ||
| 627 | whichregs = wd_dev.regs + WD1_OFF; | ||
| 628 | whichmask = WD1_INTR_MASK; | ||
| 629 | whichlimit= (0 == wd1_timeout) ? | ||
| 630 | (wd_dev.opt_timeout): | ||
| 631 | (wd1_timeout); | ||
| 632 | break; | ||
| 633 | case WD2_ID: | ||
| 634 | whichmisc = &wd2_miscdev; | ||
| 635 | strcpy(whichident, "POR"); | ||
| 636 | whichregs = wd_dev.regs + WD2_OFF; | ||
| 637 | whichmask = WD2_INTR_MASK; | ||
| 638 | whichlimit= (0 == wd2_timeout) ? | ||
| 639 | (wd_dev.opt_timeout): | ||
| 640 | (wd2_timeout); | ||
| 641 | break; | ||
| 642 | default: | ||
| 643 | printk("%s: %s: invalid watchdog id: %i\n", | ||
| 644 | WD_OBPNAME, __func__, whichdog); | ||
| 645 | return(1); | ||
| 646 | } | ||
| 647 | if(0 != misc_register(whichmisc)) | ||
| 648 | { | ||
| 649 | return(1); | ||
| 650 | } | ||
| 651 | wd_dev.watchdog[whichdog].regs = whichregs; | ||
| 652 | wd_dev.watchdog[whichdog].timeout = whichlimit; | ||
| 653 | wd_dev.watchdog[whichdog].intr_mask = whichmask; | ||
| 654 | wd_dev.watchdog[whichdog].runstatus &= ~WD_STAT_BSTOP; | ||
| 655 | wd_dev.watchdog[whichdog].runstatus |= WD_STAT_INIT; | ||
| 656 | |||
| 657 | printk("%s%i: %s hardware watchdog [%01i.%i sec] %s\n", | ||
| 658 | WD_OBPNAME, | ||
| 659 | whichdog, | ||
| 660 | whichident, | ||
| 661 | wd_dev.watchdog[whichdog].timeout / 10, | ||
| 662 | wd_dev.watchdog[whichdog].timeout % 10, | ||
| 663 | (0 != wd_dev.opt_enable) ? "in ENABLED mode" : ""); | ||
| 664 | return(0); | ||
| 665 | } | ||
| 666 | |||
| 667 | /* Timer method called to reset stopped watchdogs-- | ||
| 668 | * because of the PLD bug on CP1400, we cannot mask | ||
| 669 | * interrupts within the PLD so me must continually | ||
| 670 | * reset the timers ad infinitum. | ||
| 671 | */ | ||
| 672 | static void wd_brokentimer(unsigned long data) | ||
| 673 | { | ||
| 674 | struct wd_device* pDev = (struct wd_device*)data; | ||
| 675 | int id, tripped = 0; | ||
| 676 | |||
| 677 | /* kill a running timer instance, in case we | ||
| 678 | * were called directly instead of by kernel timer | ||
| 679 | */ | ||
| 680 | if(timer_pending(&wd_timer)) { | ||
| 681 | del_timer(&wd_timer); | ||
| 682 | } | ||
| 683 | |||
| 684 | for(id = WD0_ID; id < WD_NUMDEVS; ++id) { | ||
| 685 | if(pDev->watchdog[id].runstatus & WD_STAT_BSTOP) { | ||
| 686 | ++tripped; | ||
| 687 | wd_resetbrokentimer(&pDev->watchdog[id]); | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | if(tripped) { | ||
| 692 | /* there is at least one timer brokenstopped-- reschedule */ | ||
| 693 | init_timer(&wd_timer); | ||
| 694 | wd_timer.expires = WD_BTIMEOUT; | ||
| 695 | add_timer(&wd_timer); | ||
| 696 | } | ||
| 697 | } | ||
| 698 | |||
| 699 | static int wd_getstatus(struct wd_timer* pTimer) | ||
| 700 | { | ||
| 701 | unsigned char stat = wd_readb(pTimer->regs + WD_STATUS); | ||
| 702 | unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK); | ||
| 703 | unsigned char ret = WD_STOPPED; | ||
| 704 | |||
| 705 | /* determine STOPPED */ | ||
| 706 | if(0 == stat ) { | ||
| 707 | return(ret); | ||
| 708 | } | ||
| 709 | /* determine EXPIRED vs FREERUN vs RUNNING */ | ||
| 710 | else if(WD_S_EXPIRED & stat) { | ||
| 711 | ret = WD_EXPIRED; | ||
| 712 | } | ||
| 713 | else if(WD_S_RUNNING & stat) { | ||
| 714 | if(intr & pTimer->intr_mask) { | ||
| 715 | ret = WD_FREERUN; | ||
| 716 | } | ||
| 717 | else { | ||
| 718 | /* Fudge WD_EXPIRED status for defective CP1400-- | ||
| 719 | * IF timer is running | ||
| 720 | * AND brokenstop is set | ||
| 721 | * AND an interrupt has been serviced | ||
| 722 | * we are WD_EXPIRED. | ||
| 723 | * | ||
| 724 | * IF timer is running | ||
| 725 | * AND brokenstop is set | ||
| 726 | * AND no interrupt has been serviced | ||
| 727 | * we are WD_FREERUN. | ||
| 728 | */ | ||
| 729 | if(wd_dev.isbaddoggie && (pTimer->runstatus & WD_STAT_BSTOP)) { | ||
| 730 | if(pTimer->runstatus & WD_STAT_SVCD) { | ||
| 731 | ret = WD_EXPIRED; | ||
| 732 | } | ||
| 733 | else { | ||
| 734 | /* we could as well pretend we are expired */ | ||
| 735 | ret = WD_FREERUN; | ||
| 736 | } | ||
| 737 | } | ||
| 738 | else { | ||
| 739 | ret = WD_RUNNING; | ||
| 740 | } | ||
| 741 | } | ||
| 742 | } | ||
| 743 | |||
| 744 | /* determine SERVICED */ | ||
| 745 | if(pTimer->runstatus & WD_STAT_SVCD) { | ||
| 746 | ret |= WD_SERVICED; | ||
| 747 | } | ||
| 748 | |||
| 749 | return(ret); | ||
| 750 | } | ||
| 751 | |||
| 752 | static int __init wd_init(void) | ||
| 753 | { | ||
| 754 | int id; | ||
| 755 | struct linux_ebus *ebus = NULL; | ||
| 756 | struct linux_ebus_device *edev = NULL; | ||
| 757 | |||
| 758 | for_each_ebus(ebus) { | ||
| 759 | for_each_ebusdev(edev, ebus) { | ||
| 760 | if (!strcmp(edev->ofdev.node->name, WD_OBPNAME)) | ||
| 761 | goto ebus_done; | ||
| 762 | } | ||
| 763 | } | ||
| 764 | |||
| 765 | ebus_done: | ||
| 766 | if(!edev) { | ||
| 767 | printk("%s: unable to locate device\n", WD_OBPNAME); | ||
| 768 | return -ENODEV; | ||
| 769 | } | ||
| 770 | |||
| 771 | wd_dev.regs = | ||
| 772 | ioremap(edev->resource[0].start, 4 * WD_TIMER_REGSZ); /* ? */ | ||
| 773 | |||
| 774 | if(NULL == wd_dev.regs) { | ||
| 775 | printk("%s: unable to map registers\n", WD_OBPNAME); | ||
| 776 | return(-ENODEV); | ||
| 777 | } | ||
| 778 | |||
| 779 | /* initialize device structure from OBP parameters */ | ||
| 780 | wd_dev.irq = edev->irqs[0]; | ||
| 781 | wd_dev.opt_enable = wd_opt_enable(); | ||
| 782 | wd_dev.opt_reboot = wd_opt_reboot(); | ||
| 783 | wd_dev.opt_timeout = wd_opt_timeout(); | ||
| 784 | wd_dev.isbaddoggie = wd_isbroken(); | ||
| 785 | |||
| 786 | /* disable all interrupts unless watchdog-enabled? == true */ | ||
| 787 | if(! wd_dev.opt_enable) { | ||
| 788 | wd_toggleintr(NULL, WD_INTR_OFF); | ||
| 789 | } | ||
| 790 | |||
| 791 | /* register miscellaneous devices */ | ||
| 792 | for(id = WD0_ID; id < WD_NUMDEVS; ++id) { | ||
| 793 | if(0 != wd_inittimer(id)) { | ||
| 794 | printk("%s%i: unable to initialize\n", WD_OBPNAME, id); | ||
| 795 | } | ||
| 796 | } | ||
| 797 | |||
| 798 | /* warn about possible defective PLD */ | ||
| 799 | if(wd_dev.isbaddoggie) { | ||
| 800 | init_timer(&wd_timer); | ||
| 801 | wd_timer.function = wd_brokentimer; | ||
| 802 | wd_timer.data = (unsigned long)&wd_dev; | ||
| 803 | wd_timer.expires = WD_BTIMEOUT; | ||
| 804 | |||
| 805 | printk("%s: PLD defect workaround enabled for model %s\n", | ||
| 806 | WD_OBPNAME, WD_BADMODEL); | ||
| 807 | } | ||
| 808 | return(0); | ||
| 809 | } | ||
| 810 | |||
| 811 | static void __exit wd_cleanup(void) | ||
| 812 | { | ||
| 813 | int id; | ||
| 814 | |||
| 815 | /* if 'watchdog-enable?' == TRUE, timers are not stopped | ||
| 816 | * when module is unloaded. All brokenstopped timers will | ||
| 817 | * also now eventually trip. | ||
| 818 | */ | ||
| 819 | for(id = WD0_ID; id < WD_NUMDEVS; ++id) { | ||
| 820 | if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) { | ||
| 821 | if(wd_dev.opt_enable) { | ||
| 822 | printk(KERN_WARNING "%s%i: timer not stopped at release\n", | ||
| 823 | WD_OBPNAME, id); | ||
| 824 | } | ||
| 825 | else { | ||
| 826 | wd_stoptimer(&wd_dev.watchdog[id]); | ||
| 827 | if(wd_dev.watchdog[id].runstatus & WD_STAT_BSTOP) { | ||
| 828 | wd_resetbrokentimer(&wd_dev.watchdog[id]); | ||
| 829 | printk(KERN_WARNING | ||
| 830 | "%s%i: defect workaround disabled at release, "\ | ||
| 831 | "timer expires in ~%01i sec\n", | ||
| 832 | WD_OBPNAME, id, | ||
| 833 | wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10); | ||
| 834 | } | ||
| 835 | } | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | if(wd_dev.isbaddoggie && timer_pending(&wd_timer)) { | ||
| 840 | del_timer(&wd_timer); | ||
| 841 | } | ||
| 842 | if(0 != (wd_dev.watchdog[WD0_ID].runstatus & WD_STAT_INIT)) { | ||
| 843 | misc_deregister(&wd0_miscdev); | ||
| 844 | } | ||
| 845 | if(0 != (wd_dev.watchdog[WD1_ID].runstatus & WD_STAT_INIT)) { | ||
| 846 | misc_deregister(&wd1_miscdev); | ||
| 847 | } | ||
| 848 | if(0 != (wd_dev.watchdog[WD2_ID].runstatus & WD_STAT_INIT)) { | ||
| 849 | misc_deregister(&wd2_miscdev); | ||
| 850 | } | ||
| 851 | if(0 != wd_dev.initialized) { | ||
| 852 | free_irq(wd_dev.irq, (void *)wd_dev.regs); | ||
| 853 | } | ||
| 854 | iounmap(wd_dev.regs); | ||
| 855 | } | ||
| 856 | |||
| 857 | module_init(wd_init); | ||
| 858 | module_exit(wd_cleanup); | ||
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index d8f5c0ca236d..2550af4ae432 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c | |||
| @@ -1,10 +1,7 @@ | |||
| 1 | /* $Id: display7seg.c,v 1.6 2002/01/08 16:00:16 davem Exp $ | 1 | /* display7seg.c - Driver implementation for the 7-segment display |
| 2 | * | 2 | * present on Sun Microsystems CP1400 and CP1500 |
| 3 | * display7seg - Driver implementation for the 7-segment display | ||
| 4 | * present on Sun Microsystems CP1400 and CP1500 | ||
| 5 | * | 3 | * |
| 6 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | 4 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) |
| 7 | * | ||
| 8 | */ | 5 | */ |
| 9 | 6 | ||
| 10 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
| @@ -16,22 +13,20 @@ | |||
| 16 | #include <linux/miscdevice.h> | 13 | #include <linux/miscdevice.h> |
| 17 | #include <linux/ioport.h> /* request_region */ | 14 | #include <linux/ioport.h> /* request_region */ |
| 18 | #include <linux/smp_lock.h> | 15 | #include <linux/smp_lock.h> |
| 16 | #include <linux/of.h> | ||
| 17 | #include <linux/of_device.h> | ||
| 19 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
| 20 | #include <asm/ebus.h> /* EBus device */ | ||
| 21 | #include <asm/oplib.h> /* OpenProm Library */ | ||
| 22 | #include <asm/uaccess.h> /* put_/get_user */ | 19 | #include <asm/uaccess.h> /* put_/get_user */ |
| 23 | #include <asm/io.h> | 20 | #include <asm/io.h> |
| 24 | 21 | ||
| 25 | #include <asm/display7seg.h> | 22 | #include <asm/display7seg.h> |
| 26 | 23 | ||
| 27 | #define D7S_MINOR 193 | 24 | #define D7S_MINOR 193 |
| 28 | #define D7S_OBPNAME "display7seg" | 25 | #define DRIVER_NAME "d7s" |
| 29 | #define D7S_DEVNAME "d7s" | 26 | #define PFX DRIVER_NAME ": " |
| 30 | 27 | ||
| 31 | static int sol_compat = 0; /* Solaris compatibility mode */ | 28 | static int sol_compat = 0; /* Solaris compatibility mode */ |
| 32 | 29 | ||
| 33 | #ifdef MODULE | ||
| 34 | |||
| 35 | /* Solaris compatibility flag - | 30 | /* Solaris compatibility flag - |
| 36 | * The Solaris implementation omits support for several | 31 | * The Solaris implementation omits support for several |
| 37 | * documented driver features (ref Sun doc 806-0180-03). | 32 | * documented driver features (ref Sun doc 806-0180-03). |
| @@ -46,20 +41,20 @@ static int sol_compat = 0; /* Solaris compatibility mode */ | |||
| 46 | * If you wish the device to operate as under Solaris, | 41 | * If you wish the device to operate as under Solaris, |
| 47 | * omitting above features, set this parameter to non-zero. | 42 | * omitting above features, set this parameter to non-zero. |
| 48 | */ | 43 | */ |
| 49 | module_param | 44 | module_param(sol_compat, int, 0); |
| 50 | (sol_compat, int, 0); | 45 | MODULE_PARM_DESC(sol_compat, |
| 51 | MODULE_PARM_DESC | 46 | "Disables documented functionality omitted from Solaris driver"); |
| 52 | (sol_compat, | 47 | |
| 53 | "Disables documented functionality omitted from Solaris driver"); | 48 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); |
| 54 | 49 | MODULE_DESCRIPTION("7-Segment Display driver for Sun Microsystems CP1400/1500"); | |
| 55 | MODULE_AUTHOR | ||
| 56 | ("Eric Brower <ebrower@usa.net>"); | ||
| 57 | MODULE_DESCRIPTION | ||
| 58 | ("7-Segment Display driver for Sun Microsystems CP1400/1500"); | ||
| 59 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
| 60 | MODULE_SUPPORTED_DEVICE | 51 | MODULE_SUPPORTED_DEVICE("d7s"); |
| 61 | ("d7s"); | 52 | |
| 62 | #endif /* ifdef MODULE */ | 53 | struct d7s { |
| 54 | void __iomem *regs; | ||
| 55 | bool flipped; | ||
| 56 | }; | ||
| 57 | struct d7s *d7s_device; | ||
| 63 | 58 | ||
| 64 | /* | 59 | /* |
| 65 | * Register block address- see header for details | 60 | * Register block address- see header for details |
| @@ -72,22 +67,6 @@ MODULE_SUPPORTED_DEVICE | |||
| 72 | * FLIP - Inverts display for upside-down mounted board | 67 | * FLIP - Inverts display for upside-down mounted board |
| 73 | * bits 0-4 - 7-segment display contents | 68 | * bits 0-4 - 7-segment display contents |
| 74 | */ | 69 | */ |
| 75 | static void __iomem* d7s_regs; | ||
| 76 | |||
| 77 | static inline void d7s_free(void) | ||
| 78 | { | ||
| 79 | iounmap(d7s_regs); | ||
| 80 | } | ||
| 81 | |||
| 82 | static inline int d7s_obpflipped(void) | ||
| 83 | { | ||
| 84 | int opt_node; | ||
| 85 | |||
| 86 | opt_node = prom_getchild(prom_root_node); | ||
| 87 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
| 88 | return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1); | ||
| 89 | } | ||
| 90 | |||
| 91 | static atomic_t d7s_users = ATOMIC_INIT(0); | 70 | static atomic_t d7s_users = ATOMIC_INIT(0); |
| 92 | 71 | ||
| 93 | static int d7s_open(struct inode *inode, struct file *f) | 72 | static int d7s_open(struct inode *inode, struct file *f) |
| @@ -106,12 +85,15 @@ static int d7s_release(struct inode *inode, struct file *f) | |||
| 106 | * are not operating in solaris-compat mode | 85 | * are not operating in solaris-compat mode |
| 107 | */ | 86 | */ |
| 108 | if (atomic_dec_and_test(&d7s_users) && !sol_compat) { | 87 | if (atomic_dec_and_test(&d7s_users) && !sol_compat) { |
| 109 | int regval = 0; | 88 | struct d7s *p = d7s_device; |
| 110 | 89 | u8 regval = 0; | |
| 111 | regval = readb(d7s_regs); | 90 | |
| 112 | (0 == d7s_obpflipped()) ? | 91 | regval = readb(p->regs); |
| 113 | writeb(regval |= D7S_FLIP, d7s_regs): | 92 | if (p->flipped) |
| 114 | writeb(regval &= ~D7S_FLIP, d7s_regs); | 93 | regval |= D7S_FLIP; |
| 94 | else | ||
| 95 | regval &= ~D7S_FLIP; | ||
| 96 | writeb(regval, p->regs); | ||
| 115 | } | 97 | } |
| 116 | 98 | ||
| 117 | return 0; | 99 | return 0; |
| @@ -119,9 +101,10 @@ static int d7s_release(struct inode *inode, struct file *f) | |||
| 119 | 101 | ||
| 120 | static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 102 | static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 121 | { | 103 | { |
| 122 | __u8 regs = readb(d7s_regs); | 104 | struct d7s *p = d7s_device; |
| 123 | __u8 ireg = 0; | 105 | u8 regs = readb(p->regs); |
| 124 | int error = 0; | 106 | int error = 0; |
| 107 | u8 ireg = 0; | ||
| 125 | 108 | ||
| 126 | if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) | 109 | if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) |
| 127 | return -ENODEV; | 110 | return -ENODEV; |
| @@ -129,18 +112,20 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 129 | lock_kernel(); | 112 | lock_kernel(); |
| 130 | switch (cmd) { | 113 | switch (cmd) { |
| 131 | case D7SIOCWR: | 114 | case D7SIOCWR: |
| 132 | /* assign device register values | 115 | /* assign device register values we mask-out D7S_FLIP |
| 133 | * we mask-out D7S_FLIP if in sol_compat mode | 116 | * if in sol_compat mode |
| 134 | */ | 117 | */ |
| 135 | if (get_user(ireg, (int __user *) arg)) { | 118 | if (get_user(ireg, (int __user *) arg)) { |
| 136 | error = -EFAULT; | 119 | error = -EFAULT; |
| 137 | break; | 120 | break; |
| 138 | } | 121 | } |
| 139 | if (0 != sol_compat) { | 122 | if (sol_compat) { |
| 140 | (regs & D7S_FLIP) ? | 123 | if (regs & D7S_FLIP) |
| 141 | (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); | 124 | ireg |= D7S_FLIP; |
| 125 | else | ||
| 126 | ireg &= ~D7S_FLIP; | ||
| 142 | } | 127 | } |
| 143 | writeb(ireg, d7s_regs); | 128 | writeb(ireg, p->regs); |
| 144 | break; | 129 | break; |
| 145 | 130 | ||
| 146 | case D7SIOCRD: | 131 | case D7SIOCRD: |
| @@ -158,9 +143,11 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 158 | 143 | ||
| 159 | case D7SIOCTM: | 144 | case D7SIOCTM: |
| 160 | /* toggle device mode-- flip display orientation */ | 145 | /* toggle device mode-- flip display orientation */ |
| 161 | (regs & D7S_FLIP) ? | 146 | if (regs & D7S_FLIP) |
| 162 | (regs &= ~D7S_FLIP) : (regs |= D7S_FLIP); | 147 | regs &= ~D7S_FLIP; |
| 163 | writeb(regs, d7s_regs); | 148 | else |
| 149 | regs |= D7S_FLIP; | ||
| 150 | writeb(regs, p->regs); | ||
| 164 | break; | 151 | break; |
| 165 | }; | 152 | }; |
| 166 | unlock_kernel(); | 153 | unlock_kernel(); |
| @@ -176,69 +163,123 @@ static const struct file_operations d7s_fops = { | |||
| 176 | .release = d7s_release, | 163 | .release = d7s_release, |
| 177 | }; | 164 | }; |
| 178 | 165 | ||
| 179 | static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; | 166 | static struct miscdevice d7s_miscdev = { |
| 167 | .minor = D7S_MINOR, | ||
| 168 | .name = DRIVER_NAME, | ||
| 169 | .fops = &d7s_fops | ||
| 170 | }; | ||
| 180 | 171 | ||
| 181 | static int __init d7s_init(void) | 172 | static int __devinit d7s_probe(struct of_device *op, |
| 173 | const struct of_device_id *match) | ||
| 182 | { | 174 | { |
| 183 | struct linux_ebus *ebus = NULL; | 175 | struct device_node *opts; |
| 184 | struct linux_ebus_device *edev = NULL; | 176 | int err = -EINVAL; |
| 185 | int iTmp = 0, regs = 0; | 177 | struct d7s *p; |
| 186 | 178 | u8 regs; | |
| 187 | for_each_ebus(ebus) { | 179 | |
| 188 | for_each_ebusdev(edev, ebus) { | 180 | if (d7s_device) |
| 189 | if (!strcmp(edev->prom_node->name, D7S_OBPNAME)) | 181 | goto out; |
| 190 | goto ebus_done; | 182 | |
| 191 | } | 183 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 184 | err = -ENOMEM; | ||
| 185 | if (!p) | ||
| 186 | goto out; | ||
| 187 | |||
| 188 | p->regs = of_ioremap(&op->resource[0], 0, sizeof(u8), "d7s"); | ||
| 189 | if (!p->regs) { | ||
| 190 | printk(KERN_ERR PFX "Cannot map chip registers\n"); | ||
| 191 | goto out_free; | ||
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | ebus_done: | 194 | err = misc_register(&d7s_miscdev); |
| 195 | if(!edev) { | 195 | if (err) { |
| 196 | printk("%s: unable to locate device\n", D7S_DEVNAME); | 196 | printk(KERN_ERR PFX "Unable to acquire miscdevice minor %i\n", |
| 197 | return -ENODEV; | 197 | D7S_MINOR); |
| 198 | goto out_iounmap; | ||
| 198 | } | 199 | } |
| 199 | 200 | ||
| 200 | d7s_regs = ioremap(edev->resource[0].start, sizeof(__u8)); | 201 | /* OBP option "d7s-flipped?" is honored as default for the |
| 201 | 202 | * device, and reset default when detached | |
| 202 | iTmp = misc_register(&d7s_miscdev); | ||
| 203 | if (0 != iTmp) { | ||
| 204 | printk("%s: unable to acquire miscdevice minor %i\n", | ||
| 205 | D7S_DEVNAME, D7S_MINOR); | ||
| 206 | iounmap(d7s_regs); | ||
| 207 | return iTmp; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* OBP option "d7s-flipped?" is honored as default | ||
| 211 | * for the device, and reset default when detached | ||
| 212 | */ | 203 | */ |
| 213 | regs = readb(d7s_regs); | 204 | regs = readb(p->regs); |
| 214 | iTmp = d7s_obpflipped(); | 205 | opts = of_find_node_by_path("/options"); |
| 215 | (0 == iTmp) ? | 206 | if (opts && |
| 216 | writeb(regs |= D7S_FLIP, d7s_regs): | 207 | of_get_property(opts, "d7s-flipped?", NULL)) |
| 217 | writeb(regs &= ~D7S_FLIP, d7s_regs); | 208 | p->flipped = true; |
| 218 | 209 | ||
| 219 | printk("%s: 7-Segment Display%s at 0x%lx %s\n", | 210 | if (p->flipped) |
| 220 | D7S_DEVNAME, | 211 | regs |= D7S_FLIP; |
| 221 | (0 == iTmp) ? (" (FLIPPED)") : (""), | 212 | else |
| 222 | edev->resource[0].start, | 213 | regs &= ~D7S_FLIP; |
| 223 | (0 != sol_compat) ? ("in sol_compat mode") : ("")); | 214 | |
| 224 | 215 | writeb(regs, p->regs); | |
| 225 | return 0; | 216 | |
| 217 | printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%lx] %s\n", | ||
| 218 | op->node->full_name, | ||
| 219 | (regs & D7S_FLIP) ? " (FLIPPED)" : "", | ||
| 220 | op->resource[0].start, | ||
| 221 | sol_compat ? "in sol_compat mode" : ""); | ||
| 222 | |||
| 223 | dev_set_drvdata(&op->dev, p); | ||
| 224 | d7s_device = p; | ||
| 225 | err = 0; | ||
| 226 | |||
| 227 | out: | ||
| 228 | return err; | ||
| 229 | |||
| 230 | out_iounmap: | ||
| 231 | of_iounmap(&op->resource[0], p->regs, sizeof(u8)); | ||
| 232 | |||
| 233 | out_free: | ||
| 234 | kfree(p); | ||
| 235 | goto out; | ||
| 226 | } | 236 | } |
| 227 | 237 | ||
| 228 | static void __exit d7s_cleanup(void) | 238 | static int __devexit d7s_remove(struct of_device *op) |
| 229 | { | 239 | { |
| 230 | int regs = readb(d7s_regs); | 240 | struct d7s *p = dev_get_drvdata(&op->dev); |
| 241 | u8 regs = readb(p->regs); | ||
| 231 | 242 | ||
| 232 | /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ | 243 | /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ |
| 233 | if (0 == sol_compat) { | 244 | if (sol_compat) { |
| 234 | (0 == d7s_obpflipped()) ? | 245 | if (p->flipped) |
| 235 | writeb(regs |= D7S_FLIP, d7s_regs): | 246 | regs |= D7S_FLIP; |
| 236 | writeb(regs &= ~D7S_FLIP, d7s_regs); | 247 | else |
| 248 | regs &= ~D7S_FLIP; | ||
| 249 | writeb(regs, p->regs); | ||
| 237 | } | 250 | } |
| 238 | 251 | ||
| 239 | misc_deregister(&d7s_miscdev); | 252 | misc_deregister(&d7s_miscdev); |
| 240 | d7s_free(); | 253 | of_iounmap(&op->resource[0], p->regs, sizeof(u8)); |
| 254 | kfree(p); | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static const struct of_device_id d7s_match[] = { | ||
| 260 | { | ||
| 261 | .name = "display7seg", | ||
| 262 | }, | ||
| 263 | {}, | ||
| 264 | }; | ||
| 265 | MODULE_DEVICE_TABLE(of, d7s_match); | ||
| 266 | |||
| 267 | static struct of_platform_driver d7s_driver = { | ||
| 268 | .name = DRIVER_NAME, | ||
| 269 | .match_table = d7s_match, | ||
| 270 | .probe = d7s_probe, | ||
| 271 | .remove = __devexit_p(d7s_remove), | ||
| 272 | }; | ||
| 273 | |||
| 274 | static int __init d7s_init(void) | ||
| 275 | { | ||
| 276 | return of_register_driver(&d7s_driver, &of_bus_type); | ||
| 277 | } | ||
| 278 | |||
| 279 | static void __exit d7s_exit(void) | ||
| 280 | { | ||
| 281 | of_unregister_driver(&d7s_driver); | ||
| 241 | } | 282 | } |
| 242 | 283 | ||
| 243 | module_init(d7s_init); | 284 | module_init(d7s_init); |
| 244 | module_exit(d7s_cleanup); | 285 | module_exit(d7s_exit); |
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index a408402426f8..58e583b61e60 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* $Id: envctrl.c,v 1.25 2002/01/15 09:01:26 davem Exp $ | 1 | /* envctrl.c: Temperature and Fan monitoring on Machines providing it. |
| 2 | * envctrl.c: Temperature and Fan monitoring on Machines providing it. | ||
| 3 | * | 2 | * |
| 4 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) |
| 5 | * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) | 4 | * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) |
| @@ -28,12 +27,16 @@ | |||
| 28 | #include <linux/kmod.h> | 27 | #include <linux/kmod.h> |
| 29 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
| 30 | #include <linux/smp_lock.h> | 29 | #include <linux/smp_lock.h> |
| 30 | #include <linux/of.h> | ||
| 31 | #include <linux/of_device.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/ebus.h> | ||
| 33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
| 34 | #include <asm/envctrl.h> | 34 | #include <asm/envctrl.h> |
| 35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
| 36 | 36 | ||
| 37 | #define DRIVER_NAME "envctrl" | ||
| 38 | #define PFX DRIVER_NAME ": " | ||
| 39 | |||
| 37 | #define ENVCTRL_MINOR 162 | 40 | #define ENVCTRL_MINOR 162 |
| 38 | 41 | ||
| 39 | #define PCF8584_ADDRESS 0x55 | 42 | #define PCF8584_ADDRESS 0x55 |
| @@ -193,7 +196,7 @@ static void envtrl_i2c_test_pin(void) | |||
| 193 | } | 196 | } |
| 194 | 197 | ||
| 195 | if (limit <= 0) | 198 | if (limit <= 0) |
| 196 | printk(KERN_INFO "envctrl: Pin status will not clear.\n"); | 199 | printk(KERN_INFO PFX "Pin status will not clear.\n"); |
| 197 | } | 200 | } |
| 198 | 201 | ||
| 199 | /* Function Description: Test busy bit. | 202 | /* Function Description: Test busy bit. |
| @@ -211,7 +214,7 @@ static void envctrl_i2c_test_bb(void) | |||
| 211 | } | 214 | } |
| 212 | 215 | ||
| 213 | if (limit <= 0) | 216 | if (limit <= 0) |
| 214 | printk(KERN_INFO "envctrl: Busy bit will not clear.\n"); | 217 | printk(KERN_INFO PFX "Busy bit will not clear.\n"); |
| 215 | } | 218 | } |
| 216 | 219 | ||
| 217 | /* Function Description: Send the address for a read access. | 220 | /* Function Description: Send the address for a read access. |
| @@ -858,11 +861,10 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) | |||
| 858 | /* Function Description: Initialize i2c child device. | 861 | /* Function Description: Initialize i2c child device. |
| 859 | * Return: None. | 862 | * Return: None. |
| 860 | */ | 863 | */ |
| 861 | static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, | 864 | static void envctrl_init_i2c_child(struct device_node *dp, |
| 862 | struct i2c_child_t *pchild) | 865 | struct i2c_child_t *pchild) |
| 863 | { | 866 | { |
| 864 | int len, i, tbls_size = 0; | 867 | int len, i, tbls_size = 0; |
| 865 | struct device_node *dp = edev_child->prom_node; | ||
| 866 | const void *pval; | 868 | const void *pval; |
| 867 | 869 | ||
| 868 | /* Get device address. */ | 870 | /* Get device address. */ |
| @@ -882,12 +884,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, | |||
| 882 | 884 | ||
| 883 | pchild->tables = kmalloc(tbls_size, GFP_KERNEL); | 885 | pchild->tables = kmalloc(tbls_size, GFP_KERNEL); |
| 884 | if (pchild->tables == NULL){ | 886 | if (pchild->tables == NULL){ |
| 885 | printk("envctrl: Failed to allocate table.\n"); | 887 | printk(KERN_ERR PFX "Failed to allocate table.\n"); |
| 886 | return; | 888 | return; |
| 887 | } | 889 | } |
| 888 | pval = of_get_property(dp, "tables", &len); | 890 | pval = of_get_property(dp, "tables", &len); |
| 889 | if (!pval || len <= 0) { | 891 | if (!pval || len <= 0) { |
| 890 | printk("envctrl: Failed to get table.\n"); | 892 | printk(KERN_ERR PFX "Failed to get table.\n"); |
| 891 | return; | 893 | return; |
| 892 | } | 894 | } |
| 893 | memcpy(pchild->tables, pval, len); | 895 | memcpy(pchild->tables, pval, len); |
| @@ -993,14 +995,14 @@ static int kenvctrld(void *__unused) | |||
| 993 | struct i2c_child_t *cputemp; | 995 | struct i2c_child_t *cputemp; |
| 994 | 996 | ||
| 995 | if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { | 997 | if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { |
| 996 | printk(KERN_ERR | 998 | printk(KERN_ERR PFX |
| 997 | "envctrl: kenvctrld unable to monitor CPU temp-- exiting\n"); | 999 | "kenvctrld unable to monitor CPU temp-- exiting\n"); |
| 998 | return -ENODEV; | 1000 | return -ENODEV; |
| 999 | } | 1001 | } |
| 1000 | 1002 | ||
| 1001 | poll_interval = 5000; /* TODO env_mon_interval */ | 1003 | poll_interval = 5000; /* TODO env_mon_interval */ |
| 1002 | 1004 | ||
| 1003 | printk(KERN_INFO "envctrl: %s starting...\n", current->comm); | 1005 | printk(KERN_INFO PFX "%s starting...\n", current->comm); |
| 1004 | for (;;) { | 1006 | for (;;) { |
| 1005 | msleep_interruptible(poll_interval); | 1007 | msleep_interruptible(poll_interval); |
| 1006 | 1008 | ||
| @@ -1022,54 +1024,35 @@ static int kenvctrld(void *__unused) | |||
| 1022 | } | 1024 | } |
| 1023 | } | 1025 | } |
| 1024 | } | 1026 | } |
| 1025 | printk(KERN_INFO "envctrl: %s exiting...\n", current->comm); | 1027 | printk(KERN_INFO PFX "%s exiting...\n", current->comm); |
| 1026 | return 0; | 1028 | return 0; |
| 1027 | } | 1029 | } |
| 1028 | 1030 | ||
| 1029 | static int __init envctrl_init(void) | 1031 | static int __devinit envctrl_probe(struct of_device *op, |
| 1032 | const struct of_device_id *match) | ||
| 1030 | { | 1033 | { |
| 1031 | struct linux_ebus *ebus = NULL; | 1034 | struct device_node *dp; |
| 1032 | struct linux_ebus_device *edev = NULL; | 1035 | int index, err; |
| 1033 | struct linux_ebus_child *edev_child = NULL; | ||
| 1034 | int err, i = 0; | ||
| 1035 | |||
| 1036 | for_each_ebus(ebus) { | ||
| 1037 | for_each_ebusdev(edev, ebus) { | ||
| 1038 | if (!strcmp(edev->prom_node->name, "bbc")) { | ||
| 1039 | /* If we find a boot-bus controller node, | ||
| 1040 | * then this envctrl driver is not for us. | ||
| 1041 | */ | ||
| 1042 | return -ENODEV; | ||
| 1043 | } | ||
| 1044 | } | ||
| 1045 | } | ||
| 1046 | 1036 | ||
| 1047 | /* Traverse through ebus and ebus device list for i2c device and | 1037 | if (i2c) |
| 1048 | * adc and gpio nodes. | 1038 | return -EINVAL; |
| 1049 | */ | 1039 | |
| 1050 | for_each_ebus(ebus) { | 1040 | i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME); |
| 1051 | for_each_ebusdev(edev, ebus) { | 1041 | if (!i2c) |
| 1052 | if (!strcmp(edev->prom_node->name, "i2c")) { | 1042 | return -ENOMEM; |
| 1053 | i2c = ioremap(edev->resource[0].start, 0x2); | 1043 | |
| 1054 | for_each_edevchild(edev, edev_child) { | 1044 | index = 0; |
| 1055 | if (!strcmp("gpio", edev_child->prom_node->name)) { | 1045 | dp = op->node->child; |
| 1056 | i2c_childlist[i].i2ctype = I2C_GPIO; | 1046 | while (dp) { |
| 1057 | envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); | 1047 | if (!strcmp(dp->name, "gpio")) { |
| 1058 | } | 1048 | i2c_childlist[index].i2ctype = I2C_GPIO; |
| 1059 | if (!strcmp("adc", edev_child->prom_node->name)) { | 1049 | envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); |
| 1060 | i2c_childlist[i].i2ctype = I2C_ADC; | 1050 | } else if (!strcmp(dp->name, "adc")) { |
| 1061 | envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); | 1051 | i2c_childlist[index].i2ctype = I2C_ADC; |
| 1062 | } | 1052 | envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); |
| 1063 | } | ||
| 1064 | goto done; | ||
| 1065 | } | ||
| 1066 | } | 1053 | } |
| 1067 | } | ||
| 1068 | 1054 | ||
| 1069 | done: | 1055 | dp = dp->sibling; |
| 1070 | if (!edev) { | ||
| 1071 | printk("envctrl: I2C device not found.\n"); | ||
| 1072 | return -ENODEV; | ||
| 1073 | } | 1056 | } |
| 1074 | 1057 | ||
| 1075 | /* Set device address. */ | 1058 | /* Set device address. */ |
| @@ -1087,7 +1070,7 @@ done: | |||
| 1087 | /* Register the device as a minor miscellaneous device. */ | 1070 | /* Register the device as a minor miscellaneous device. */ |
| 1088 | err = misc_register(&envctrl_dev); | 1071 | err = misc_register(&envctrl_dev); |
| 1089 | if (err) { | 1072 | if (err) { |
| 1090 | printk("envctrl: Unable to get misc minor %d\n", | 1073 | printk(KERN_ERR PFX "Unable to get misc minor %d\n", |
| 1091 | envctrl_dev.minor); | 1074 | envctrl_dev.minor); |
| 1092 | goto out_iounmap; | 1075 | goto out_iounmap; |
| 1093 | } | 1076 | } |
| @@ -1096,12 +1079,12 @@ done: | |||
| 1096 | * a next child device, so we decrement before reverse-traversal of | 1079 | * a next child device, so we decrement before reverse-traversal of |
| 1097 | * child devices. | 1080 | * child devices. |
| 1098 | */ | 1081 | */ |
| 1099 | printk("envctrl: initialized "); | 1082 | printk(KERN_INFO PFX "Initialized "); |
| 1100 | for (--i; i >= 0; --i) { | 1083 | for (--index; index >= 0; --index) { |
| 1101 | printk("[%s 0x%lx]%s", | 1084 | printk("[%s 0x%lx]%s", |
| 1102 | (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") : | 1085 | (I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" : |
| 1103 | ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")), | 1086 | ((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"), |
| 1104 | i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); | 1087 | i2c_childlist[index].addr, (0 == index) ? "\n" : " "); |
| 1105 | } | 1088 | } |
| 1106 | 1089 | ||
| 1107 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); | 1090 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
| @@ -1115,26 +1098,54 @@ done: | |||
| 1115 | out_deregister: | 1098 | out_deregister: |
| 1116 | misc_deregister(&envctrl_dev); | 1099 | misc_deregister(&envctrl_dev); |
| 1117 | out_iounmap: | 1100 | out_iounmap: |
| 1118 | iounmap(i2c); | 1101 | of_iounmap(&op->resource[0], i2c, 0x2); |
| 1119 | for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) | 1102 | for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) |
| 1120 | kfree(i2c_childlist[i].tables); | 1103 | kfree(i2c_childlist[index].tables); |
| 1121 | 1104 | ||
| 1122 | return err; | 1105 | return err; |
| 1123 | } | 1106 | } |
| 1124 | 1107 | ||
| 1125 | static void __exit envctrl_cleanup(void) | 1108 | static int __devexit envctrl_remove(struct of_device *op) |
| 1126 | { | 1109 | { |
| 1127 | int i; | 1110 | int index; |
| 1128 | 1111 | ||
| 1129 | kthread_stop(kenvctrld_task); | 1112 | kthread_stop(kenvctrld_task); |
| 1130 | 1113 | ||
| 1131 | iounmap(i2c); | 1114 | of_iounmap(&op->resource[0], i2c, 0x2); |
| 1132 | misc_deregister(&envctrl_dev); | 1115 | misc_deregister(&envctrl_dev); |
| 1133 | 1116 | ||
| 1134 | for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) | 1117 | for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) |
| 1135 | kfree(i2c_childlist[i].tables); | 1118 | kfree(i2c_childlist[index].tables); |
| 1119 | |||
| 1120 | return 0; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | static const struct of_device_id envctrl_match[] = { | ||
| 1124 | { | ||
| 1125 | .name = "i2c", | ||
| 1126 | .compatible = "i2cpcf,8584", | ||
| 1127 | }, | ||
| 1128 | {}, | ||
| 1129 | }; | ||
| 1130 | MODULE_DEVICE_TABLE(of, envctrl_match); | ||
| 1131 | |||
| 1132 | static struct of_platform_driver envctrl_driver = { | ||
| 1133 | .name = DRIVER_NAME, | ||
| 1134 | .match_table = envctrl_match, | ||
| 1135 | .probe = envctrl_probe, | ||
| 1136 | .remove = __devexit_p(envctrl_remove), | ||
| 1137 | }; | ||
| 1138 | |||
| 1139 | static int __init envctrl_init(void) | ||
| 1140 | { | ||
| 1141 | return of_register_driver(&envctrl_driver, &of_bus_type); | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | static void __exit envctrl_exit(void) | ||
| 1145 | { | ||
| 1146 | of_unregister_driver(&envctrl_driver); | ||
| 1136 | } | 1147 | } |
| 1137 | 1148 | ||
| 1138 | module_init(envctrl_init); | 1149 | module_init(envctrl_init); |
| 1139 | module_exit(envctrl_cleanup); | 1150 | module_exit(envctrl_exit); |
| 1140 | MODULE_LICENSE("GPL"); | 1151 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 7d95e151513a..41083472ff4f 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* $Id: flash.c,v 1.25 2001/12/21 04:56:16 davem Exp $ | 1 | /* flash.c: Allow mmap access to the OBP Flash, for OBP updates. |
| 2 | * flash.c: Allow mmap access to the OBP Flash, for OBP updates. | ||
| 3 | * | 2 | * |
| 4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
| 5 | */ | 4 | */ |
| @@ -15,13 +14,13 @@ | |||
| 15 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
| 16 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
| 17 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_device.h> | ||
| 18 | 19 | ||
| 19 | #include <asm/system.h> | 20 | #include <asm/system.h> |
| 20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
| 21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
| 22 | #include <asm/io.h> | 23 | #include <asm/io.h> |
| 23 | #include <asm/sbus.h> | ||
| 24 | #include <asm/ebus.h> | ||
| 25 | #include <asm/upa.h> | 24 | #include <asm/upa.h> |
| 26 | 25 | ||
| 27 | static DEFINE_SPINLOCK(flash_lock); | 26 | static DEFINE_SPINLOCK(flash_lock); |
| @@ -161,97 +160,68 @@ static const struct file_operations flash_fops = { | |||
| 161 | 160 | ||
| 162 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; | 161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; |
| 163 | 162 | ||
| 164 | static int __init flash_init(void) | 163 | static int __devinit flash_probe(struct of_device *op, |
| 164 | const struct of_device_id *match) | ||
| 165 | { | 165 | { |
| 166 | struct sbus_bus *sbus; | 166 | struct device_node *dp = op->node; |
| 167 | struct sbus_dev *sdev = NULL; | 167 | struct device_node *parent; |
| 168 | #ifdef CONFIG_PCI | ||
| 169 | struct linux_ebus *ebus; | ||
| 170 | struct linux_ebus_device *edev = NULL; | ||
| 171 | struct linux_prom_registers regs[2]; | ||
| 172 | int len, nregs; | ||
| 173 | #endif | ||
| 174 | int err; | ||
| 175 | |||
| 176 | for_all_sbusdev(sdev, sbus) { | ||
| 177 | if (!strcmp(sdev->prom_name, "flashprom")) { | ||
| 178 | if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) { | ||
| 179 | flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | | ||
| 180 | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); | ||
| 181 | flash.read_size = sdev->reg_addrs[0].reg_size; | ||
| 182 | flash.write_base = flash.read_base; | ||
| 183 | flash.write_size = flash.read_size; | ||
| 184 | } else { | ||
| 185 | flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | | ||
| 186 | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); | ||
| 187 | flash.read_size = sdev->reg_addrs[0].reg_size; | ||
| 188 | flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) | | ||
| 189 | (((unsigned long)sdev->reg_addrs[1].which_io)<<32UL); | ||
| 190 | flash.write_size = sdev->reg_addrs[1].reg_size; | ||
| 191 | } | ||
| 192 | flash.busy = 0; | ||
| 193 | break; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | if (!sdev) { | ||
| 197 | #ifdef CONFIG_PCI | ||
| 198 | const struct linux_prom_registers *ebus_regs; | ||
| 199 | |||
| 200 | for_each_ebus(ebus) { | ||
| 201 | for_each_ebusdev(edev, ebus) { | ||
| 202 | if (!strcmp(edev->prom_node->name, "flashprom")) | ||
| 203 | goto ebus_done; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | ebus_done: | ||
| 207 | if (!edev) | ||
| 208 | return -ENODEV; | ||
| 209 | |||
| 210 | ebus_regs = of_get_property(edev->prom_node, "reg", &len); | ||
| 211 | if (!ebus_regs || (len % sizeof(regs[0])) != 0) { | ||
| 212 | printk("flash: Strange reg property size %d\n", len); | ||
| 213 | return -ENODEV; | ||
| 214 | } | ||
| 215 | |||
| 216 | nregs = len / sizeof(ebus_regs[0]); | ||
| 217 | 168 | ||
| 218 | flash.read_base = edev->resource[0].start; | 169 | parent = dp->parent; |
| 219 | flash.read_size = ebus_regs[0].reg_size; | ||
| 220 | 170 | ||
| 221 | if (nregs == 1) { | 171 | if (strcmp(parent->name, "sbus") && |
| 222 | flash.write_base = edev->resource[0].start; | 172 | strcmp(parent->name, "sbi") && |
| 223 | flash.write_size = ebus_regs[0].reg_size; | 173 | strcmp(parent->name, "ebus")) |
| 224 | } else if (nregs == 2) { | ||
| 225 | flash.write_base = edev->resource[1].start; | ||
| 226 | flash.write_size = ebus_regs[1].reg_size; | ||
| 227 | } else { | ||
| 228 | printk("flash: Strange number of regs %d\n", nregs); | ||
| 229 | return -ENODEV; | ||
| 230 | } | ||
| 231 | |||
| 232 | flash.busy = 0; | ||
| 233 | |||
| 234 | #else | ||
| 235 | return -ENODEV; | 174 | return -ENODEV; |
| 236 | #endif | 175 | |
| 176 | flash.read_base = op->resource[0].start; | ||
| 177 | flash.read_size = resource_size(&op->resource[0]); | ||
| 178 | if (op->resource[1].flags) { | ||
| 179 | flash.write_base = op->resource[1].start; | ||
| 180 | flash.write_size = resource_size(&op->resource[1]); | ||
| 181 | } else { | ||
| 182 | flash.write_base = op->resource[0].start; | ||
| 183 | flash.write_size = resource_size(&op->resource[0]); | ||
| 237 | } | 184 | } |
| 185 | flash.busy = 0; | ||
| 238 | 186 | ||
| 239 | printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n", | 187 | printk(KERN_INFO "%s: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n", |
| 188 | op->node->full_name, | ||
| 240 | flash.read_base, flash.read_size, | 189 | flash.read_base, flash.read_size, |
| 241 | flash.write_base, flash.write_size); | 190 | flash.write_base, flash.write_size); |
| 242 | 191 | ||
| 243 | err = misc_register(&flash_dev); | 192 | return misc_register(&flash_dev); |
| 244 | if (err) { | 193 | } |
| 245 | printk(KERN_ERR "flash: unable to get misc minor\n"); | 194 | |
| 246 | return err; | 195 | static int __devexit flash_remove(struct of_device *op) |
| 247 | } | 196 | { |
| 197 | misc_deregister(&flash_dev); | ||
| 248 | 198 | ||
| 249 | return 0; | 199 | return 0; |
| 250 | } | 200 | } |
| 251 | 201 | ||
| 202 | static const struct of_device_id flash_match[] = { | ||
| 203 | { | ||
| 204 | .name = "flashprom", | ||
| 205 | }, | ||
| 206 | {}, | ||
| 207 | }; | ||
| 208 | MODULE_DEVICE_TABLE(of, flash_match); | ||
| 209 | |||
| 210 | static struct of_platform_driver flash_driver = { | ||
| 211 | .name = "flash", | ||
| 212 | .match_table = flash_match, | ||
| 213 | .probe = flash_probe, | ||
| 214 | .remove = __devexit_p(flash_remove), | ||
| 215 | }; | ||
| 216 | |||
| 217 | static int __init flash_init(void) | ||
| 218 | { | ||
| 219 | return of_register_driver(&flash_driver, &of_bus_type); | ||
| 220 | } | ||
| 221 | |||
| 252 | static void __exit flash_cleanup(void) | 222 | static void __exit flash_cleanup(void) |
| 253 | { | 223 | { |
| 254 | misc_deregister(&flash_dev); | 224 | of_unregister_driver(&flash_driver); |
| 255 | } | 225 | } |
| 256 | 226 | ||
| 257 | module_init(flash_init); | 227 | module_init(flash_init); |
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c deleted file mode 100644 index b0429917154d..000000000000 --- a/drivers/sbus/char/rtc.c +++ /dev/null | |||
| @@ -1,275 +0,0 @@ | |||
| 1 | /* $Id: rtc.c,v 1.28 2001/10/08 22:19:51 davem Exp $ | ||
| 2 | * | ||
| 3 | * Linux/SPARC Real Time Clock Driver | ||
| 4 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
| 5 | * | ||
| 6 | * This is a little driver that lets a user-level program access | ||
| 7 | * the SPARC Mostek real time clock chip. It is no use unless you | ||
| 8 | * use the modified clock utility. | ||
| 9 | * | ||
| 10 | * Get the modified clock utility from: | ||
| 11 | * ftp://vger.kernel.org/pub/linux/Sparc/userland/clock.c | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/smp_lock.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <linux/miscdevice.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/fcntl.h> | ||
| 21 | #include <linux/poll.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <asm/io.h> | ||
| 24 | #include <asm/mostek.h> | ||
| 25 | #include <asm/system.h> | ||
| 26 | #include <asm/uaccess.h> | ||
| 27 | #include <asm/rtc.h> | ||
| 28 | |||
| 29 | static int rtc_busy = 0; | ||
| 30 | |||
| 31 | /* This is the structure layout used by drivers/char/rtc.c, we | ||
| 32 | * support that driver's ioctls so that things are less messy in | ||
| 33 | * userspace. | ||
| 34 | */ | ||
| 35 | struct rtc_time_generic { | ||
| 36 | int tm_sec; | ||
| 37 | int tm_min; | ||
| 38 | int tm_hour; | ||
| 39 | int tm_mday; | ||
| 40 | int tm_mon; | ||
| 41 | int tm_year; | ||
| 42 | int tm_wday; | ||
| 43 | int tm_yday; | ||
| 44 | int tm_isdst; | ||
| 45 | }; | ||
| 46 | #define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */ | ||
| 47 | #define RTC_AIE_OFF _IO('p', 0x02) /* ... off */ | ||
| 48 | #define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ | ||
| 49 | #define RTC_UIE_OFF _IO('p', 0x04) /* ... off */ | ||
| 50 | #define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */ | ||
| 51 | #define RTC_PIE_OFF _IO('p', 0x06) /* ... off */ | ||
| 52 | #define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */ | ||
| 53 | #define RTC_WIE_OFF _IO('p', 0x10) /* ... off */ | ||
| 54 | #define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */ | ||
| 55 | #define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */ | ||
| 56 | #define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */ | ||
| 57 | #define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */ | ||
| 58 | #define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */ | ||
| 59 | #define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ | ||
| 60 | #define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ | ||
| 61 | #define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ | ||
| 62 | #define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ | ||
| 63 | #define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ | ||
| 64 | #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ | ||
| 65 | #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ | ||
| 66 | |||
| 67 | /* Retrieve the current date and time from the real time clock. */ | ||
| 68 | static void get_rtc_time(struct rtc_time *t) | ||
| 69 | { | ||
| 70 | void __iomem *regs = mstk48t02_regs; | ||
| 71 | u8 tmp; | ||
| 72 | |||
| 73 | spin_lock_irq(&mostek_lock); | ||
| 74 | |||
| 75 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 76 | tmp |= MSTK_CREG_READ; | ||
| 77 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 78 | |||
| 79 | t->sec = MSTK_REG_SEC(regs); | ||
| 80 | t->min = MSTK_REG_MIN(regs); | ||
| 81 | t->hour = MSTK_REG_HOUR(regs); | ||
| 82 | t->dow = MSTK_REG_DOW(regs); | ||
| 83 | t->dom = MSTK_REG_DOM(regs); | ||
| 84 | t->month = MSTK_REG_MONTH(regs); | ||
| 85 | t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); | ||
| 86 | |||
| 87 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 88 | tmp &= ~MSTK_CREG_READ; | ||
| 89 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 90 | |||
| 91 | spin_unlock_irq(&mostek_lock); | ||
| 92 | } | ||
| 93 | |||
| 94 | /* Set the current date and time inthe real time clock. */ | ||
| 95 | void set_rtc_time(struct rtc_time *t) | ||
| 96 | { | ||
| 97 | void __iomem *regs = mstk48t02_regs; | ||
| 98 | u8 tmp; | ||
| 99 | |||
| 100 | spin_lock_irq(&mostek_lock); | ||
| 101 | |||
| 102 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 103 | tmp |= MSTK_CREG_WRITE; | ||
| 104 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 105 | |||
| 106 | MSTK_SET_REG_SEC(regs,t->sec); | ||
| 107 | MSTK_SET_REG_MIN(regs,t->min); | ||
| 108 | MSTK_SET_REG_HOUR(regs,t->hour); | ||
| 109 | MSTK_SET_REG_DOW(regs,t->dow); | ||
| 110 | MSTK_SET_REG_DOM(regs,t->dom); | ||
| 111 | MSTK_SET_REG_MONTH(regs,t->month); | ||
| 112 | MSTK_SET_REG_YEAR(regs,t->year - MSTK_YEAR_ZERO); | ||
| 113 | |||
| 114 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
| 115 | tmp &= ~MSTK_CREG_WRITE; | ||
| 116 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
| 117 | |||
| 118 | spin_unlock_irq(&mostek_lock); | ||
| 119 | } | ||
| 120 | |||
| 121 | static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm) | ||
| 122 | { | ||
| 123 | struct rtc_time_generic __user *utm = argp; | ||
| 124 | |||
| 125 | if (__put_user(tm->sec, &utm->tm_sec) || | ||
| 126 | __put_user(tm->min, &utm->tm_min) || | ||
| 127 | __put_user(tm->hour, &utm->tm_hour) || | ||
| 128 | __put_user(tm->dom, &utm->tm_mday) || | ||
| 129 | __put_user(tm->month, &utm->tm_mon) || | ||
| 130 | __put_user(tm->year, &utm->tm_year) || | ||
| 131 | __put_user(tm->dow, &utm->tm_wday) || | ||
| 132 | __put_user(0, &utm->tm_yday) || | ||
| 133 | __put_user(0, &utm->tm_isdst)) | ||
| 134 | return -EFAULT; | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp) | ||
| 140 | { | ||
| 141 | struct rtc_time_generic __user *utm = argp; | ||
| 142 | |||
| 143 | if (__get_user(tm->sec, &utm->tm_sec) || | ||
| 144 | __get_user(tm->min, &utm->tm_min) || | ||
| 145 | __get_user(tm->hour, &utm->tm_hour) || | ||
| 146 | __get_user(tm->dom, &utm->tm_mday) || | ||
| 147 | __get_user(tm->month, &utm->tm_mon) || | ||
| 148 | __get_user(tm->year, &utm->tm_year) || | ||
| 149 | __get_user(tm->dow, &utm->tm_wday)) | ||
| 150 | return -EFAULT; | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
| 156 | unsigned long arg) | ||
| 157 | { | ||
| 158 | struct rtc_time rtc_tm; | ||
| 159 | void __user *argp = (void __user *)arg; | ||
| 160 | |||
| 161 | switch (cmd) { | ||
| 162 | /* No interrupt support, return an error | ||
| 163 | * compatible with drivers/char/rtc.c | ||
| 164 | */ | ||
| 165 | case RTC_AIE_OFF: | ||
| 166 | case RTC_AIE_ON: | ||
| 167 | case RTC_PIE_OFF: | ||
| 168 | case RTC_PIE_ON: | ||
| 169 | case RTC_UIE_OFF: | ||
| 170 | case RTC_UIE_ON: | ||
| 171 | case RTC_IRQP_READ: | ||
| 172 | case RTC_IRQP_SET: | ||
| 173 | case RTC_EPOCH_SET: | ||
| 174 | case RTC_EPOCH_READ: | ||
| 175 | return -EINVAL; | ||
| 176 | |||
| 177 | case RTCGET: | ||
| 178 | case RTC_RD_TIME: | ||
| 179 | memset(&rtc_tm, 0, sizeof(struct rtc_time)); | ||
| 180 | get_rtc_time(&rtc_tm); | ||
| 181 | |||
| 182 | if (cmd == RTCGET) { | ||
| 183 | if (copy_to_user(argp, &rtc_tm, | ||
| 184 | sizeof(struct rtc_time))) | ||
| 185 | return -EFAULT; | ||
| 186 | } else if (put_rtc_time_generic(argp, &rtc_tm)) | ||
| 187 | return -EFAULT; | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | |||
| 191 | |||
| 192 | case RTCSET: | ||
| 193 | case RTC_SET_TIME: | ||
| 194 | if (!capable(CAP_SYS_TIME)) | ||
| 195 | return -EPERM; | ||
| 196 | |||
| 197 | if (cmd == RTCSET) { | ||
| 198 | if (copy_from_user(&rtc_tm, argp, | ||
| 199 | sizeof(struct rtc_time))) | ||
| 200 | return -EFAULT; | ||
| 201 | } else if (get_rtc_time_generic(&rtc_tm, argp)) | ||
| 202 | return -EFAULT; | ||
| 203 | |||
| 204 | set_rtc_time(&rtc_tm); | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | |||
| 208 | default: | ||
| 209 | return -EINVAL; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | |||
| 213 | static int rtc_open(struct inode *inode, struct file *file) | ||
| 214 | { | ||
| 215 | int ret; | ||
| 216 | |||
| 217 | lock_kernel(); | ||
| 218 | spin_lock_irq(&mostek_lock); | ||
| 219 | if (rtc_busy) { | ||
| 220 | ret = -EBUSY; | ||
| 221 | } else { | ||
| 222 | rtc_busy = 1; | ||
| 223 | ret = 0; | ||
| 224 | } | ||
| 225 | spin_unlock_irq(&mostek_lock); | ||
| 226 | unlock_kernel(); | ||
| 227 | |||
| 228 | return ret; | ||
| 229 | } | ||
| 230 | |||
| 231 | static int rtc_release(struct inode *inode, struct file *file) | ||
| 232 | { | ||
| 233 | rtc_busy = 0; | ||
| 234 | |||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static const struct file_operations rtc_fops = { | ||
| 239 | .owner = THIS_MODULE, | ||
| 240 | .llseek = no_llseek, | ||
| 241 | .ioctl = rtc_ioctl, | ||
| 242 | .open = rtc_open, | ||
| 243 | .release = rtc_release, | ||
| 244 | }; | ||
| 245 | |||
| 246 | static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops }; | ||
| 247 | |||
| 248 | static int __init rtc_sun_init(void) | ||
| 249 | { | ||
| 250 | int error; | ||
| 251 | |||
| 252 | /* It is possible we are being driven by some other RTC chip | ||
| 253 | * and thus another RTC driver is handling things. | ||
| 254 | */ | ||
| 255 | if (!mstk48t02_regs) | ||
| 256 | return -ENODEV; | ||
| 257 | |||
| 258 | error = misc_register(&rtc_dev); | ||
| 259 | if (error) { | ||
| 260 | printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n"); | ||
| 261 | return error; | ||
| 262 | } | ||
| 263 | printk("rtc_sun_init: Registered Mostek RTC driver.\n"); | ||
| 264 | |||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | static void __exit rtc_sun_cleanup(void) | ||
| 269 | { | ||
| 270 | misc_deregister(&rtc_dev); | ||
| 271 | } | ||
| 272 | |||
| 273 | module_init(rtc_sun_init); | ||
| 274 | module_exit(rtc_sun_cleanup); | ||
| 275 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 777637594acd..27993c37775d 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* $Id: uctrl.c,v 1.12 2001/10/08 22:19:51 davem Exp $ | 1 | /* uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 |
| 2 | * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 | ||
| 3 | * | 2 | * |
| 4 | * Copyright 1999 Derrick J Brashear (shadow@dementia.org) | 3 | * Copyright 1999 Derrick J Brashear (shadow@dementia.org) |
| 4 | * Copyright 2008 David S. Miller (davem@davemloft.net) | ||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/miscdevice.h> | 15 | #include <linux/miscdevice.h> |
| 16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_device.h> | ||
| 17 | 19 | ||
| 18 | #include <asm/openprom.h> | 20 | #include <asm/openprom.h> |
| 19 | #include <asm/oplib.h> | 21 | #include <asm/oplib.h> |
| @@ -21,7 +23,6 @@ | |||
| 21 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
| 22 | #include <asm/io.h> | 24 | #include <asm/io.h> |
| 23 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
| 24 | #include <asm/sbus.h> | ||
| 25 | 26 | ||
| 26 | #define UCTRL_MINOR 174 | 27 | #define UCTRL_MINOR 174 |
| 27 | 28 | ||
| @@ -33,26 +34,26 @@ | |||
| 33 | #endif | 34 | #endif |
| 34 | 35 | ||
| 35 | struct uctrl_regs { | 36 | struct uctrl_regs { |
| 36 | volatile u32 uctrl_intr; | 37 | u32 uctrl_intr; |
| 37 | volatile u32 uctrl_data; | 38 | u32 uctrl_data; |
| 38 | volatile u32 uctrl_stat; | 39 | u32 uctrl_stat; |
| 39 | volatile u32 uctrl_xxx[5]; | 40 | u32 uctrl_xxx[5]; |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | struct ts102_regs { | 43 | struct ts102_regs { |
| 43 | volatile u32 card_a_intr; | 44 | u32 card_a_intr; |
| 44 | volatile u32 card_a_stat; | 45 | u32 card_a_stat; |
| 45 | volatile u32 card_a_ctrl; | 46 | u32 card_a_ctrl; |
| 46 | volatile u32 card_a_xxx; | 47 | u32 card_a_xxx; |
| 47 | volatile u32 card_b_intr; | 48 | u32 card_b_intr; |
| 48 | volatile u32 card_b_stat; | 49 | u32 card_b_stat; |
| 49 | volatile u32 card_b_ctrl; | 50 | u32 card_b_ctrl; |
| 50 | volatile u32 card_b_xxx; | 51 | u32 card_b_xxx; |
| 51 | volatile u32 uctrl_intr; | 52 | u32 uctrl_intr; |
| 52 | volatile u32 uctrl_data; | 53 | u32 uctrl_data; |
| 53 | volatile u32 uctrl_stat; | 54 | u32 uctrl_stat; |
| 54 | volatile u32 uctrl_xxx; | 55 | u32 uctrl_xxx; |
| 55 | volatile u32 ts102_xxx[4]; | 56 | u32 ts102_xxx[4]; |
| 56 | }; | 57 | }; |
| 57 | 58 | ||
| 58 | /* Bits for uctrl_intr register */ | 59 | /* Bits for uctrl_intr register */ |
| @@ -186,17 +187,15 @@ enum uctrl_opcode { | |||
| 186 | POWER_RESTART=0x83, | 187 | POWER_RESTART=0x83, |
| 187 | }; | 188 | }; |
| 188 | 189 | ||
| 189 | struct uctrl_driver { | 190 | static struct uctrl_driver { |
| 190 | struct uctrl_regs *regs; | 191 | struct uctrl_regs __iomem *regs; |
| 191 | int irq; | 192 | int irq; |
| 192 | int pending; | 193 | int pending; |
| 193 | struct uctrl_status status; | 194 | struct uctrl_status status; |
| 194 | }; | 195 | } *global_driver; |
| 195 | |||
| 196 | static struct uctrl_driver drv; | ||
| 197 | 196 | ||
| 198 | static void uctrl_get_event_status(void); | 197 | static void uctrl_get_event_status(struct uctrl_driver *); |
| 199 | static void uctrl_get_external_status(void); | 198 | static void uctrl_get_external_status(struct uctrl_driver *); |
| 200 | 199 | ||
| 201 | static int | 200 | static int |
| 202 | uctrl_ioctl(struct inode *inode, struct file *file, | 201 | uctrl_ioctl(struct inode *inode, struct file *file, |
| @@ -213,16 +212,14 @@ static int | |||
| 213 | uctrl_open(struct inode *inode, struct file *file) | 212 | uctrl_open(struct inode *inode, struct file *file) |
| 214 | { | 213 | { |
| 215 | lock_kernel(); | 214 | lock_kernel(); |
| 216 | uctrl_get_event_status(); | 215 | uctrl_get_event_status(global_driver); |
| 217 | uctrl_get_external_status(); | 216 | uctrl_get_external_status(global_driver); |
| 218 | unlock_kernel(); | 217 | unlock_kernel(); |
| 219 | return 0; | 218 | return 0; |
| 220 | } | 219 | } |
| 221 | 220 | ||
| 222 | static irqreturn_t uctrl_interrupt(int irq, void *dev_id) | 221 | static irqreturn_t uctrl_interrupt(int irq, void *dev_id) |
| 223 | { | 222 | { |
| 224 | struct uctrl_driver *driver = (struct uctrl_driver *)dev_id; | ||
| 225 | printk("in uctrl_interrupt\n"); | ||
| 226 | return IRQ_HANDLED; | 223 | return IRQ_HANDLED; |
| 227 | } | 224 | } |
| 228 | 225 | ||
| @@ -244,11 +241,11 @@ static struct miscdevice uctrl_dev = { | |||
| 244 | { \ | 241 | { \ |
| 245 | unsigned int i; \ | 242 | unsigned int i; \ |
| 246 | for (i = 0; i < 10000; i++) { \ | 243 | for (i = 0; i < 10000; i++) { \ |
| 247 | if (UCTRL_STAT_TXNF_STA & driver->regs->uctrl_stat) \ | 244 | if (UCTRL_STAT_TXNF_STA & sbus_readl(&driver->regs->uctrl_stat)) \ |
| 248 | break; \ | 245 | break; \ |
| 249 | } \ | 246 | } \ |
| 250 | dprintk(("write data 0x%02x\n", value)); \ | 247 | dprintk(("write data 0x%02x\n", value)); \ |
| 251 | driver->regs->uctrl_data = value; \ | 248 | sbus_writel(value, &driver->regs->uctrl_data); \ |
| 252 | } | 249 | } |
| 253 | 250 | ||
| 254 | /* Wait for something to read, read it, then clear the bit */ | 251 | /* Wait for something to read, read it, then clear the bit */ |
| @@ -257,24 +254,23 @@ static struct miscdevice uctrl_dev = { | |||
| 257 | unsigned int i; \ | 254 | unsigned int i; \ |
| 258 | value = 0; \ | 255 | value = 0; \ |
| 259 | for (i = 0; i < 10000; i++) { \ | 256 | for (i = 0; i < 10000; i++) { \ |
| 260 | if ((UCTRL_STAT_RXNE_STA & driver->regs->uctrl_stat) == 0) \ | 257 | if ((UCTRL_STAT_RXNE_STA & sbus_readl(&driver->regs->uctrl_stat)) == 0) \ |
| 261 | break; \ | 258 | break; \ |
| 262 | udelay(1); \ | 259 | udelay(1); \ |
| 263 | } \ | 260 | } \ |
| 264 | value = driver->regs->uctrl_data; \ | 261 | value = sbus_readl(&driver->regs->uctrl_data); \ |
| 265 | dprintk(("read data 0x%02x\n", value)); \ | 262 | dprintk(("read data 0x%02x\n", value)); \ |
| 266 | driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \ | 263 | sbus_writel(UCTRL_STAT_RXNE_STA, &driver->regs->uctrl_stat); \ |
| 267 | } | 264 | } |
| 268 | 265 | ||
| 269 | static void uctrl_do_txn(struct uctrl_txn *txn) | 266 | static void uctrl_do_txn(struct uctrl_driver *driver, struct uctrl_txn *txn) |
| 270 | { | 267 | { |
| 271 | struct uctrl_driver *driver = &drv; | ||
| 272 | int stat, incnt, outcnt, bytecnt, intr; | 268 | int stat, incnt, outcnt, bytecnt, intr; |
| 273 | u32 byte; | 269 | u32 byte; |
| 274 | 270 | ||
| 275 | stat = driver->regs->uctrl_stat; | 271 | stat = sbus_readl(&driver->regs->uctrl_stat); |
| 276 | intr = driver->regs->uctrl_intr; | 272 | intr = sbus_readl(&driver->regs->uctrl_intr); |
| 277 | driver->regs->uctrl_stat = stat; | 273 | sbus_writel(stat, &driver->regs->uctrl_stat); |
| 278 | 274 | ||
| 279 | dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr)); | 275 | dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr)); |
| 280 | 276 | ||
| @@ -305,9 +301,8 @@ static void uctrl_do_txn(struct uctrl_txn *txn) | |||
| 305 | } | 301 | } |
| 306 | } | 302 | } |
| 307 | 303 | ||
| 308 | static void uctrl_get_event_status(void) | 304 | static void uctrl_get_event_status(struct uctrl_driver *driver) |
| 309 | { | 305 | { |
| 310 | struct uctrl_driver *driver = &drv; | ||
| 311 | struct uctrl_txn txn; | 306 | struct uctrl_txn txn; |
| 312 | u8 outbits[2]; | 307 | u8 outbits[2]; |
| 313 | 308 | ||
| @@ -317,7 +312,7 @@ static void uctrl_get_event_status(void) | |||
| 317 | txn.inbuf = NULL; | 312 | txn.inbuf = NULL; |
| 318 | txn.outbuf = outbits; | 313 | txn.outbuf = outbits; |
| 319 | 314 | ||
| 320 | uctrl_do_txn(&txn); | 315 | uctrl_do_txn(driver, &txn); |
| 321 | 316 | ||
| 322 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); | 317 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); |
| 323 | driver->status.event_status = | 318 | driver->status.event_status = |
| @@ -325,9 +320,8 @@ static void uctrl_get_event_status(void) | |||
| 325 | dprintk(("ev is %x\n", driver->status.event_status)); | 320 | dprintk(("ev is %x\n", driver->status.event_status)); |
| 326 | } | 321 | } |
| 327 | 322 | ||
| 328 | static void uctrl_get_external_status(void) | 323 | static void uctrl_get_external_status(struct uctrl_driver *driver) |
| 329 | { | 324 | { |
| 330 | struct uctrl_driver *driver = &drv; | ||
| 331 | struct uctrl_txn txn; | 325 | struct uctrl_txn txn; |
| 332 | u8 outbits[2]; | 326 | u8 outbits[2]; |
| 333 | int i, v; | 327 | int i, v; |
| @@ -338,7 +332,7 @@ static void uctrl_get_external_status(void) | |||
| 338 | txn.inbuf = NULL; | 332 | txn.inbuf = NULL; |
| 339 | txn.outbuf = outbits; | 333 | txn.outbuf = outbits; |
| 340 | 334 | ||
| 341 | uctrl_do_txn(&txn); | 335 | uctrl_do_txn(driver, &txn); |
| 342 | 336 | ||
| 343 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); | 337 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); |
| 344 | driver->status.external_status = | 338 | driver->status.external_status = |
| @@ -354,71 +348,101 @@ static void uctrl_get_external_status(void) | |||
| 354 | 348 | ||
| 355 | } | 349 | } |
| 356 | 350 | ||
| 357 | static int __init ts102_uctrl_init(void) | 351 | static int __devinit uctrl_probe(struct of_device *op, |
| 352 | const struct of_device_id *match) | ||
| 358 | { | 353 | { |
| 359 | struct uctrl_driver *driver = &drv; | 354 | struct uctrl_driver *p; |
| 360 | int len; | 355 | int err = -ENOMEM; |
| 361 | struct linux_prom_irqs tmp_irq[2]; | ||
| 362 | unsigned int vaddr[2] = { 0, 0 }; | ||
| 363 | int tmpnode, uctrlnode = prom_getchild(prom_root_node); | ||
| 364 | int err; | ||
| 365 | 356 | ||
| 366 | tmpnode = prom_searchsiblings(uctrlnode, "obio"); | 357 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 358 | if (!p) { | ||
| 359 | printk(KERN_ERR "uctrl: Unable to allocate device struct.\n"); | ||
| 360 | goto out; | ||
| 361 | } | ||
| 367 | 362 | ||
| 368 | if (tmpnode) | 363 | p->regs = of_ioremap(&op->resource[0], 0, |
| 369 | uctrlnode = prom_getchild(tmpnode); | 364 | resource_size(&op->resource[0]), |
| 365 | "uctrl"); | ||
| 366 | if (!p->regs) { | ||
| 367 | printk(KERN_ERR "uctrl: Unable to map registers.\n"); | ||
| 368 | goto out_free; | ||
| 369 | } | ||
| 370 | 370 | ||
| 371 | uctrlnode = prom_searchsiblings(uctrlnode, "uctrl"); | 371 | p->irq = op->irqs[0]; |
| 372 | err = request_irq(p->irq, uctrl_interrupt, 0, "uctrl", p); | ||
| 373 | if (err) { | ||
| 374 | printk(KERN_ERR "uctrl: Unable to register irq.\n"); | ||
| 375 | goto out_iounmap; | ||
| 376 | } | ||
| 372 | 377 | ||
| 373 | if (!uctrlnode) | 378 | err = misc_register(&uctrl_dev); |
| 374 | return -ENODEV; | 379 | if (err) { |
| 380 | printk(KERN_ERR "uctrl: Unable to register misc device.\n"); | ||
| 381 | goto out_free_irq; | ||
| 382 | } | ||
| 375 | 383 | ||
| 376 | /* the prom mapped it for us */ | 384 | sbus_writel(UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK, &p->regs->uctrl_intr); |
| 377 | len = prom_getproperty(uctrlnode, "address", (void *) vaddr, | 385 | printk(KERN_INFO "%s: uctrl regs[0x%p] (irq %d)\n", |
| 378 | sizeof(vaddr)); | 386 | op->node->full_name, p->regs, p->irq); |
| 379 | driver->regs = (struct uctrl_regs *)vaddr[0]; | 387 | uctrl_get_event_status(p); |
| 388 | uctrl_get_external_status(p); | ||
| 380 | 389 | ||
| 381 | len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq, | 390 | dev_set_drvdata(&op->dev, p); |
| 382 | sizeof(tmp_irq)); | 391 | global_driver = p; |
| 383 | 392 | ||
| 384 | /* Flush device */ | 393 | out: |
| 385 | READUCTLDATA(len); | 394 | return err; |
| 386 | 395 | ||
| 387 | if(!driver->irq) | 396 | out_free_irq: |
| 388 | driver->irq = tmp_irq[0].pri; | 397 | free_irq(p->irq, p); |
| 389 | 398 | ||
| 390 | err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver); | 399 | out_iounmap: |
| 391 | if (err) { | 400 | of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); |
| 392 | printk("%s: unable to register irq %d\n", | ||
| 393 | __func__, driver->irq); | ||
| 394 | return err; | ||
| 395 | } | ||
| 396 | 401 | ||
| 397 | if (misc_register(&uctrl_dev)) { | 402 | out_free: |
| 398 | printk("%s: unable to get misc minor %d\n", | 403 | kfree(p); |
| 399 | __func__, uctrl_dev.minor); | 404 | goto out; |
| 400 | free_irq(driver->irq, driver); | 405 | } |
| 401 | return -ENODEV; | ||
| 402 | } | ||
| 403 | 406 | ||
| 404 | driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK; | 407 | static int __devexit uctrl_remove(struct of_device *op) |
| 405 | printk("uctrl: 0x%p (irq %d)\n", driver->regs, driver->irq); | 408 | { |
| 406 | uctrl_get_event_status(); | 409 | struct uctrl_driver *p = dev_get_drvdata(&op->dev); |
| 407 | uctrl_get_external_status(); | 410 | |
| 408 | return 0; | 411 | if (p) { |
| 412 | misc_deregister(&uctrl_dev); | ||
| 413 | free_irq(p->irq, p); | ||
| 414 | of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); | ||
| 415 | kfree(p); | ||
| 416 | } | ||
| 417 | return 0; | ||
| 409 | } | 418 | } |
| 410 | 419 | ||
| 411 | static void __exit ts102_uctrl_cleanup(void) | 420 | static const struct of_device_id uctrl_match[] = { |
| 421 | { | ||
| 422 | .name = "uctrl", | ||
| 423 | }, | ||
| 424 | {}, | ||
| 425 | }; | ||
| 426 | MODULE_DEVICE_TABLE(of, uctrl_match); | ||
| 427 | |||
| 428 | static struct of_platform_driver uctrl_driver = { | ||
| 429 | .name = "uctrl", | ||
| 430 | .match_table = uctrl_match, | ||
| 431 | .probe = uctrl_probe, | ||
| 432 | .remove = __devexit_p(uctrl_remove), | ||
| 433 | }; | ||
| 434 | |||
| 435 | |||
| 436 | static int __init uctrl_init(void) | ||
| 412 | { | 437 | { |
| 413 | struct uctrl_driver *driver = &drv; | 438 | return of_register_driver(&uctrl_driver, &of_bus_type); |
| 439 | } | ||
| 414 | 440 | ||
| 415 | misc_deregister(&uctrl_dev); | 441 | static void __exit uctrl_exit(void) |
| 416 | if (driver->irq) | 442 | { |
| 417 | free_irq(driver->irq, driver); | 443 | of_unregister_driver(&uctrl_driver); |
| 418 | if (driver->regs) | ||
| 419 | driver->regs = NULL; | ||
| 420 | } | 444 | } |
| 421 | 445 | ||
| 422 | module_init(ts102_uctrl_init); | 446 | module_init(uctrl_init); |
| 423 | module_exit(ts102_uctrl_cleanup); | 447 | module_exit(uctrl_exit); |
| 424 | MODULE_LICENSE("GPL"); | 448 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h deleted file mode 100644 index a5240c52aa0b..000000000000 --- a/drivers/sbus/char/vfc.h +++ /dev/null | |||
| @@ -1,171 +0,0 @@ | |||
| 1 | #ifndef _LINUX_VFC_H_ | ||
| 2 | #define _LINUX_VFC_H_ | ||
| 3 | |||
| 4 | /* | ||
| 5 | * The control register for the vfc is at offset 0x4000 | ||
| 6 | * The first field ram bank is located at offset 0x5000 | ||
| 7 | * The second field ram bank is at offset 0x7000 | ||
| 8 | * i2c_reg address the Phillips PCF8584(see notes in vfc_i2c.c) | ||
| 9 | * data and transmit register. | ||
| 10 | * i2c_s1 controls register s1 of the PCF8584 | ||
| 11 | * i2c_write seems to be similar to i2c_write but I am not | ||
| 12 | * quite sure why sun uses it | ||
| 13 | * | ||
| 14 | * I am also not sure whether or not you can read the fram bank as a | ||
| 15 | * whole or whether you must read each word individually from offset | ||
| 16 | * 0x5000 as soon as I figure it out I will update this file */ | ||
| 17 | |||
| 18 | struct vfc_regs { | ||
| 19 | char pad1[0x4000]; | ||
| 20 | unsigned int control; /* Offset 0x4000 */ | ||
| 21 | char pad2[0xffb]; /* from offset 0x4004 to 0x5000 */ | ||
| 22 | unsigned int fram_bank1; /* Offset 0x5000 */ | ||
| 23 | char pad3[0xffb]; /* from offset 0x5004 to 0x6000 */ | ||
| 24 | unsigned int i2c_reg; /* Offset 0x6000 */ | ||
| 25 | unsigned int i2c_magic2; /* Offset 0x6004 */ | ||
| 26 | unsigned int i2c_s1; /* Offset 0x6008 */ | ||
| 27 | unsigned int i2c_write; /* Offset 0x600c */ | ||
| 28 | char pad4[0xff0]; /* from offset 0x6010 to 0x7000 */ | ||
| 29 | unsigned int fram_bank2; /* Offset 0x7000 */ | ||
| 30 | char pad5[0x1000]; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #define VFC_SAA9051_NR (13) | ||
| 34 | #define VFC_SAA9051_ADDR (0x8a) | ||
| 35 | /* The saa9051 returns the following for its status | ||
| 36 | * bit 0 - 0 | ||
| 37 | * bit 1 - SECAM color detected (1=found,0=not found) | ||
| 38 | * bit 2 - COLOR detected (1=found,0=not found) | ||
| 39 | * bit 3 - 0 | ||
| 40 | * bit 4 - Field frequency bit (1=60Hz (NTSC), 0=50Hz (PAL)) | ||
| 41 | * bit 5 - 1 | ||
| 42 | * bit 6 - horizontal frequency lock (1=transmitter found, | ||
| 43 | * 0=no transmitter) | ||
| 44 | * bit 7 - Power on reset bit (1=reset,0=at least one successful | ||
| 45 | * read of the status byte) | ||
| 46 | */ | ||
| 47 | |||
| 48 | #define VFC_SAA9051_PONRES (0x80) | ||
| 49 | #define VFC_SAA9051_HLOCK (0x40) | ||
| 50 | #define VFC_SAA9051_FD (0x10) | ||
| 51 | #define VFC_SAA9051_CD (0x04) | ||
| 52 | #define VFC_SAA9051_CS (0x02) | ||
| 53 | |||
| 54 | |||
| 55 | /* The various saa9051 sub addresses */ | ||
| 56 | |||
| 57 | #define VFC_SAA9051_IDEL (0) | ||
| 58 | #define VFC_SAA9051_HSY_START (1) | ||
| 59 | #define VFC_SAA9051_HSY_STOP (2) | ||
| 60 | #define VFC_SAA9051_HC_START (3) | ||
| 61 | #define VFC_SAA9051_HC_STOP (4) | ||
| 62 | #define VFC_SAA9051_HS_START (5) | ||
| 63 | #define VFC_SAA9051_HORIZ_PEAK (6) | ||
| 64 | #define VFC_SAA9051_HUE (7) | ||
| 65 | #define VFC_SAA9051_C1 (8) | ||
| 66 | #define VFC_SAA9051_C2 (9) | ||
| 67 | #define VFC_SAA9051_C3 (0xa) | ||
| 68 | #define VFC_SAA9051_SECAM_DELAY (0xb) | ||
| 69 | |||
| 70 | |||
| 71 | /* Bit settings for saa9051 sub address 0x06 */ | ||
| 72 | |||
| 73 | #define VFC_SAA9051_AP1 (0x01) | ||
| 74 | #define VFC_SAA9051_AP2 (0x02) | ||
| 75 | #define VFC_SAA9051_COR1 (0x04) | ||
| 76 | #define VFC_SAA9051_COR2 (0x08) | ||
| 77 | #define VFC_SAA9051_BP1 (0x10) | ||
| 78 | #define VFC_SAA9051_BP2 (0x20) | ||
| 79 | #define VFC_SAA9051_PF (0x40) | ||
| 80 | #define VFC_SAA9051_BY (0x80) | ||
| 81 | |||
| 82 | |||
| 83 | /* Bit settings for saa9051 sub address 0x08 */ | ||
| 84 | |||
| 85 | #define VFC_SAA9051_CCFR0 (0x01) | ||
| 86 | #define VFC_SAA9051_CCFR1 (0x02) | ||
| 87 | #define VFC_SAA9051_YPN (0x04) | ||
| 88 | #define VFC_SAA9051_ALT (0x08) | ||
| 89 | #define VFC_SAA9051_CO (0x10) | ||
| 90 | #define VFC_SAA9051_VTR (0x20) | ||
| 91 | #define VFC_SAA9051_FS (0x40) | ||
| 92 | #define VFC_SAA9051_HPLL (0x80) | ||
| 93 | |||
| 94 | |||
| 95 | /* Bit settings for saa9051 sub address 9 */ | ||
| 96 | |||
| 97 | #define VFC_SAA9051_SS0 (0x01) | ||
| 98 | #define VFC_SAA9051_SS1 (0x02) | ||
| 99 | #define VFC_SAA9051_AFCC (0x04) | ||
| 100 | #define VFC_SAA9051_CI (0x08) | ||
| 101 | #define VFC_SAA9051_SA9D4 (0x10) /* Don't care bit */ | ||
| 102 | #define VFC_SAA9051_OEC (0x20) | ||
| 103 | #define VFC_SAA9051_OEY (0x40) | ||
| 104 | #define VFC_SAA9051_VNL (0x80) | ||
| 105 | |||
| 106 | |||
| 107 | /* Bit settings for saa9051 sub address 0x0A */ | ||
| 108 | |||
| 109 | #define VFC_SAA9051_YDL0 (0x01) | ||
| 110 | #define VFC_SAA9051_YDL1 (0x02) | ||
| 111 | #define VFC_SAA9051_YDL2 (0x04) | ||
| 112 | #define VFC_SAA9051_SS2 (0x08) | ||
| 113 | #define VFC_SAA9051_SS3 (0x10) | ||
| 114 | #define VFC_SAA9051_YC (0x20) | ||
| 115 | #define VFC_SAA9051_CT (0x40) | ||
| 116 | #define VFC_SAA9051_SYC (0x80) | ||
| 117 | |||
| 118 | |||
| 119 | #define VFC_SAA9051_SA(a,b) ((a)->saa9051_state_array[(b)+1]) | ||
| 120 | #define vfc_update_saa9051(a) (vfc_i2c_sendbuf((a),VFC_SAA9051_ADDR,\ | ||
| 121 | (a)->saa9051_state_array,\ | ||
| 122 | VFC_SAA9051_NR)) | ||
| 123 | |||
| 124 | |||
| 125 | struct vfc_dev { | ||
| 126 | volatile struct vfc_regs __iomem *regs; | ||
| 127 | struct vfc_regs *phys_regs; | ||
| 128 | unsigned int control_reg; | ||
| 129 | struct mutex device_lock_mtx; | ||
| 130 | int instance; | ||
| 131 | int busy; | ||
| 132 | unsigned long which_io; | ||
| 133 | unsigned char saa9051_state_array[VFC_SAA9051_NR]; | ||
| 134 | }; | ||
| 135 | |||
| 136 | void captstat_reset(struct vfc_dev *); | ||
| 137 | void memptr_reset(struct vfc_dev *); | ||
| 138 | |||
| 139 | int vfc_pcf8584_init(struct vfc_dev *); | ||
| 140 | void vfc_i2c_delay_no_busy(struct vfc_dev *, unsigned long); | ||
| 141 | void vfc_i2c_delay(struct vfc_dev *); | ||
| 142 | int vfc_i2c_sendbuf(struct vfc_dev *, unsigned char, char *, int) ; | ||
| 143 | int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ; | ||
| 144 | int vfc_i2c_reset_bus(struct vfc_dev *); | ||
| 145 | int vfc_init_i2c_bus(struct vfc_dev *); | ||
| 146 | |||
| 147 | #define VFC_CONTROL_DIAGMODE 0x10000000 | ||
| 148 | #define VFC_CONTROL_MEMPTR 0x20000000 | ||
| 149 | #define VFC_CONTROL_CAPTURE 0x02000000 | ||
| 150 | #define VFC_CONTROL_CAPTRESET 0x04000000 | ||
| 151 | |||
| 152 | #define VFC_STATUS_CAPTURE 0x08000000 | ||
| 153 | |||
| 154 | #ifdef VFC_IOCTL_DEBUG | ||
| 155 | #define VFC_IOCTL_DEBUG_PRINTK(a) printk a | ||
| 156 | #else | ||
| 157 | #define VFC_IOCTL_DEBUG_PRINTK(a) | ||
| 158 | #endif | ||
| 159 | |||
| 160 | #ifdef VFC_I2C_DEBUG | ||
| 161 | #define VFC_I2C_DEBUG_PRINTK(a) printk a | ||
| 162 | #else | ||
| 163 | #define VFC_I2C_DEBUG_PRINTK(a) | ||
| 164 | #endif | ||
| 165 | |||
| 166 | #endif /* _LINUX_VFC_H_ */ | ||
| 167 | |||
| 168 | |||
| 169 | |||
| 170 | |||
| 171 | |||
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c deleted file mode 100644 index 25181bb7d627..000000000000 --- a/drivers/sbus/char/vfc_dev.c +++ /dev/null | |||
| @@ -1,736 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * drivers/sbus/char/vfc_dev.c | ||
| 3 | * | ||
| 4 | * Driver for the Videopix Frame Grabber. | ||
| 5 | * | ||
| 6 | * In order to use the VFC you need to program the video controller | ||
| 7 | * chip. This chip is the Phillips SAA9051. You need to call their | ||
| 8 | * documentation ordering line to get the docs. | ||
| 9 | * | ||
| 10 | * There is very little documentation on the VFC itself. There is | ||
| 11 | * some useful info that can be found in the manuals that come with | ||
| 12 | * the card. I will hopefully write some better docs at a later date. | ||
| 13 | * | ||
| 14 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
| 15 | * */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/string.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/errno.h> | ||
| 22 | #include <linux/fs.h> | ||
| 23 | #include <linux/delay.h> | ||
| 24 | #include <linux/spinlock.h> | ||
| 25 | #include <linux/mutex.h> | ||
| 26 | #include <linux/mm.h> | ||
| 27 | #include <linux/smp_lock.h> | ||
| 28 | |||
| 29 | #include <asm/openprom.h> | ||
| 30 | #include <asm/oplib.h> | ||
| 31 | #include <asm/io.h> | ||
| 32 | #include <asm/system.h> | ||
| 33 | #include <asm/sbus.h> | ||
| 34 | #include <asm/page.h> | ||
| 35 | #include <asm/pgtable.h> | ||
| 36 | #include <asm/uaccess.h> | ||
| 37 | |||
| 38 | #define VFC_MAJOR (60) | ||
| 39 | |||
| 40 | #if 0 | ||
| 41 | #define VFC_IOCTL_DEBUG | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #include "vfc.h" | ||
| 45 | #include <asm/vfc_ioctls.h> | ||
| 46 | |||
| 47 | static const struct file_operations vfc_fops; | ||
| 48 | static struct vfc_dev **vfc_dev_lst; | ||
| 49 | static char vfcstr[]="vfc"; | ||
| 50 | static unsigned char saa9051_init_array[VFC_SAA9051_NR] = { | ||
| 51 | 0x00, 0x64, 0x72, 0x52, | ||
| 52 | 0x36, 0x18, 0xff, 0x20, | ||
| 53 | 0xfc, 0x77, 0xe3, 0x50, | ||
| 54 | 0x3e | ||
| 55 | }; | ||
| 56 | |||
| 57 | static void vfc_lock_device(struct vfc_dev *dev) | ||
| 58 | { | ||
| 59 | mutex_lock(&dev->device_lock_mtx); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void vfc_unlock_device(struct vfc_dev *dev) | ||
| 63 | { | ||
| 64 | mutex_unlock(&dev->device_lock_mtx); | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | static void vfc_captstat_reset(struct vfc_dev *dev) | ||
| 69 | { | ||
| 70 | dev->control_reg |= VFC_CONTROL_CAPTRESET; | ||
| 71 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 72 | dev->control_reg &= ~VFC_CONTROL_CAPTRESET; | ||
| 73 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 74 | dev->control_reg |= VFC_CONTROL_CAPTRESET; | ||
| 75 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 76 | } | ||
| 77 | |||
| 78 | static void vfc_memptr_reset(struct vfc_dev *dev) | ||
| 79 | { | ||
| 80 | dev->control_reg |= VFC_CONTROL_MEMPTR; | ||
| 81 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 82 | dev->control_reg &= ~VFC_CONTROL_MEMPTR; | ||
| 83 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 84 | dev->control_reg |= VFC_CONTROL_MEMPTR; | ||
| 85 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 86 | } | ||
| 87 | |||
| 88 | static int vfc_csr_init(struct vfc_dev *dev) | ||
| 89 | { | ||
| 90 | dev->control_reg = 0x80000000; | ||
| 91 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 92 | udelay(200); | ||
| 93 | dev->control_reg &= ~0x80000000; | ||
| 94 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 95 | udelay(100); | ||
| 96 | sbus_writel(0x0f000000, &dev->regs->i2c_magic2); | ||
| 97 | |||
| 98 | vfc_memptr_reset(dev); | ||
| 99 | |||
| 100 | dev->control_reg &= ~VFC_CONTROL_DIAGMODE; | ||
| 101 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
| 102 | dev->control_reg |= 0x40000000; | ||
| 103 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 104 | |||
| 105 | vfc_captstat_reset(dev); | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static int vfc_saa9051_init(struct vfc_dev *dev) | ||
| 111 | { | ||
| 112 | int i; | ||
| 113 | |||
| 114 | for (i = 0; i < VFC_SAA9051_NR; i++) | ||
| 115 | dev->saa9051_state_array[i] = saa9051_init_array[i]; | ||
| 116 | |||
| 117 | vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR, | ||
| 118 | dev->saa9051_state_array, VFC_SAA9051_NR); | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int init_vfc_hw(struct vfc_dev *dev) | ||
| 123 | { | ||
| 124 | vfc_lock_device(dev); | ||
| 125 | vfc_csr_init(dev); | ||
| 126 | |||
| 127 | vfc_pcf8584_init(dev); | ||
| 128 | vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic | ||
| 129 | sun code above*/ | ||
| 130 | vfc_saa9051_init(dev); | ||
| 131 | vfc_unlock_device(dev); | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int init_vfc_devstruct(struct vfc_dev *dev, int instance) | ||
| 136 | { | ||
| 137 | dev->instance=instance; | ||
| 138 | mutex_init(&dev->device_lock_mtx); | ||
| 139 | dev->control_reg=0; | ||
| 140 | dev->busy=0; | ||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, | ||
| 145 | int instance) | ||
| 146 | { | ||
| 147 | if(dev == NULL) { | ||
| 148 | printk(KERN_ERR "VFC: Bogus pointer passed\n"); | ||
| 149 | return -ENOMEM; | ||
| 150 | } | ||
| 151 | printk("Initializing vfc%d\n",instance); | ||
| 152 | dev->regs = NULL; | ||
| 153 | dev->regs = (volatile struct vfc_regs __iomem *) | ||
| 154 | sbus_ioremap(&sdev->resource[0], 0, | ||
| 155 | sizeof(struct vfc_regs), vfcstr); | ||
| 156 | dev->which_io = sdev->reg_addrs[0].which_io; | ||
| 157 | dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr; | ||
| 158 | if (dev->regs == NULL) | ||
| 159 | return -EIO; | ||
| 160 | |||
| 161 | printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", | ||
| 162 | instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); | ||
| 163 | |||
| 164 | if (init_vfc_devstruct(dev, instance)) | ||
| 165 | return -EINVAL; | ||
| 166 | if (init_vfc_hw(dev)) | ||
| 167 | return -EIO; | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | |||
| 172 | static struct vfc_dev *vfc_get_dev_ptr(int instance) | ||
| 173 | { | ||
| 174 | return vfc_dev_lst[instance]; | ||
| 175 | } | ||
| 176 | |||
| 177 | static DEFINE_SPINLOCK(vfc_dev_lock); | ||
| 178 | |||
| 179 | static int vfc_open(struct inode *inode, struct file *file) | ||
| 180 | { | ||
| 181 | struct vfc_dev *dev; | ||
| 182 | |||
| 183 | lock_kernel(); | ||
| 184 | spin_lock(&vfc_dev_lock); | ||
| 185 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
| 186 | if (dev == NULL) { | ||
| 187 | spin_unlock(&vfc_dev_lock); | ||
| 188 | unlock_kernel(); | ||
| 189 | return -ENODEV; | ||
| 190 | } | ||
| 191 | if (dev->busy) { | ||
| 192 | spin_unlock(&vfc_dev_lock); | ||
| 193 | unlock_kernel(); | ||
| 194 | return -EBUSY; | ||
| 195 | } | ||
| 196 | |||
| 197 | dev->busy = 1; | ||
| 198 | spin_unlock(&vfc_dev_lock); | ||
| 199 | |||
| 200 | vfc_lock_device(dev); | ||
| 201 | |||
| 202 | vfc_csr_init(dev); | ||
| 203 | vfc_pcf8584_init(dev); | ||
| 204 | vfc_init_i2c_bus(dev); | ||
| 205 | vfc_saa9051_init(dev); | ||
| 206 | vfc_memptr_reset(dev); | ||
| 207 | vfc_captstat_reset(dev); | ||
| 208 | |||
| 209 | vfc_unlock_device(dev); | ||
| 210 | unlock_kernel(); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int vfc_release(struct inode *inode,struct file *file) | ||
| 215 | { | ||
| 216 | struct vfc_dev *dev; | ||
| 217 | |||
| 218 | spin_lock(&vfc_dev_lock); | ||
| 219 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
| 220 | if (!dev || !dev->busy) { | ||
| 221 | spin_unlock(&vfc_dev_lock); | ||
| 222 | return -EINVAL; | ||
| 223 | } | ||
| 224 | dev->busy = 0; | ||
| 225 | spin_unlock(&vfc_dev_lock); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp) | ||
| 230 | { | ||
| 231 | struct vfc_debug_inout inout; | ||
| 232 | unsigned char *buffer; | ||
| 233 | |||
| 234 | if (!capable(CAP_SYS_ADMIN)) | ||
| 235 | return -EPERM; | ||
| 236 | |||
| 237 | switch(cmd) { | ||
| 238 | case VFC_I2C_SEND: | ||
| 239 | if(copy_from_user(&inout, argp, sizeof(inout))) | ||
| 240 | return -EFAULT; | ||
| 241 | |||
| 242 | buffer = kmalloc(inout.len, GFP_KERNEL); | ||
| 243 | if (buffer == NULL) | ||
| 244 | return -ENOMEM; | ||
| 245 | |||
| 246 | if(copy_from_user(buffer, inout.buffer, inout.len)) { | ||
| 247 | kfree(buffer); | ||
| 248 | return -EFAULT; | ||
| 249 | } | ||
| 250 | |||
| 251 | |||
| 252 | vfc_lock_device(dev); | ||
| 253 | inout.ret= | ||
| 254 | vfc_i2c_sendbuf(dev,inout.addr & 0xff, | ||
| 255 | buffer,inout.len); | ||
| 256 | |||
| 257 | if (copy_to_user(argp,&inout,sizeof(inout))) { | ||
| 258 | vfc_unlock_device(dev); | ||
| 259 | kfree(buffer); | ||
| 260 | return -EFAULT; | ||
| 261 | } | ||
| 262 | vfc_unlock_device(dev); | ||
| 263 | |||
| 264 | break; | ||
| 265 | case VFC_I2C_RECV: | ||
| 266 | if (copy_from_user(&inout, argp, sizeof(inout))) | ||
| 267 | return -EFAULT; | ||
| 268 | |||
| 269 | buffer = kzalloc(inout.len, GFP_KERNEL); | ||
| 270 | if (buffer == NULL) | ||
| 271 | return -ENOMEM; | ||
| 272 | |||
| 273 | vfc_lock_device(dev); | ||
| 274 | inout.ret= | ||
| 275 | vfc_i2c_recvbuf(dev,inout.addr & 0xff | ||
| 276 | ,buffer,inout.len); | ||
| 277 | vfc_unlock_device(dev); | ||
| 278 | |||
| 279 | if (copy_to_user(inout.buffer, buffer, inout.len)) { | ||
| 280 | kfree(buffer); | ||
| 281 | return -EFAULT; | ||
| 282 | } | ||
| 283 | if (copy_to_user(argp,&inout,sizeof(inout))) { | ||
| 284 | kfree(buffer); | ||
| 285 | return -EFAULT; | ||
| 286 | } | ||
| 287 | kfree(buffer); | ||
| 288 | break; | ||
| 289 | default: | ||
| 290 | return -EINVAL; | ||
| 291 | }; | ||
| 292 | |||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int vfc_capture_start(struct vfc_dev *dev) | ||
| 297 | { | ||
| 298 | vfc_captstat_reset(dev); | ||
| 299 | dev->control_reg = sbus_readl(&dev->regs->control); | ||
| 300 | if((dev->control_reg & VFC_STATUS_CAPTURE)) { | ||
| 301 | printk(KERN_ERR "vfc%d: vfc capture status not reset\n", | ||
| 302 | dev->instance); | ||
| 303 | return -EIO; | ||
| 304 | } | ||
| 305 | |||
| 306 | vfc_lock_device(dev); | ||
| 307 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
| 308 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 309 | dev->control_reg |= VFC_CONTROL_CAPTURE; | ||
| 310 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 311 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
| 312 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 313 | vfc_unlock_device(dev); | ||
| 314 | |||
| 315 | return 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | static int vfc_capture_poll(struct vfc_dev *dev) | ||
| 319 | { | ||
| 320 | int timeout = 1000; | ||
| 321 | |||
| 322 | while (!timeout--) { | ||
| 323 | if (sbus_readl(&dev->regs->control) & VFC_STATUS_CAPTURE) | ||
| 324 | break; | ||
| 325 | vfc_i2c_delay_no_busy(dev, 100); | ||
| 326 | } | ||
| 327 | if(!timeout) { | ||
| 328 | printk(KERN_WARNING "vfc%d: capture timed out\n", | ||
| 329 | dev->instance); | ||
| 330 | return -ETIMEDOUT; | ||
| 331 | } | ||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | |||
| 336 | |||
| 337 | static int vfc_set_control_ioctl(struct inode *inode, struct file *file, | ||
| 338 | struct vfc_dev *dev, unsigned long arg) | ||
| 339 | { | ||
| 340 | int setcmd, ret = 0; | ||
| 341 | |||
| 342 | if (copy_from_user(&setcmd,(void __user *)arg,sizeof(unsigned int))) | ||
| 343 | return -EFAULT; | ||
| 344 | |||
| 345 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", | ||
| 346 | dev->instance,setcmd)); | ||
| 347 | |||
| 348 | switch(setcmd) { | ||
| 349 | case MEMPRST: | ||
| 350 | vfc_lock_device(dev); | ||
| 351 | vfc_memptr_reset(dev); | ||
| 352 | vfc_unlock_device(dev); | ||
| 353 | ret=0; | ||
| 354 | break; | ||
| 355 | case CAPTRCMD: | ||
| 356 | vfc_capture_start(dev); | ||
| 357 | vfc_capture_poll(dev); | ||
| 358 | break; | ||
| 359 | case DIAGMODE: | ||
| 360 | if(capable(CAP_SYS_ADMIN)) { | ||
| 361 | vfc_lock_device(dev); | ||
| 362 | dev->control_reg |= VFC_CONTROL_DIAGMODE; | ||
| 363 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 364 | vfc_unlock_device(dev); | ||
| 365 | ret = 0; | ||
| 366 | } else { | ||
| 367 | ret = -EPERM; | ||
| 368 | } | ||
| 369 | break; | ||
| 370 | case NORMMODE: | ||
| 371 | vfc_lock_device(dev); | ||
| 372 | dev->control_reg &= ~VFC_CONTROL_DIAGMODE; | ||
| 373 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
| 374 | vfc_unlock_device(dev); | ||
| 375 | ret = 0; | ||
| 376 | break; | ||
| 377 | case CAPTRSTR: | ||
| 378 | vfc_capture_start(dev); | ||
| 379 | ret = 0; | ||
| 380 | break; | ||
| 381 | case CAPTRWAIT: | ||
| 382 | vfc_capture_poll(dev); | ||
| 383 | ret = 0; | ||
| 384 | break; | ||
| 385 | default: | ||
| 386 | ret = -EINVAL; | ||
| 387 | break; | ||
| 388 | }; | ||
| 389 | |||
| 390 | return ret; | ||
| 391 | } | ||
| 392 | |||
| 393 | |||
| 394 | static int vfc_port_change_ioctl(struct inode *inode, struct file *file, | ||
| 395 | struct vfc_dev *dev, unsigned long arg) | ||
| 396 | { | ||
| 397 | int ret = 0; | ||
| 398 | int cmd; | ||
| 399 | |||
| 400 | if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { | ||
| 401 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
| 402 | "vfc_port_change_ioctl\n", | ||
| 403 | dev->instance)); | ||
| 404 | return -EFAULT; | ||
| 405 | } | ||
| 406 | |||
| 407 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", | ||
| 408 | dev->instance, cmd)); | ||
| 409 | |||
| 410 | switch(cmd) { | ||
| 411 | case 1: | ||
| 412 | case 2: | ||
| 413 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72; | ||
| 414 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52; | ||
| 415 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36; | ||
| 416 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18; | ||
| 417 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2; | ||
| 418 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3; | ||
| 419 | VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e; | ||
| 420 | break; | ||
| 421 | case 3: | ||
| 422 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a; | ||
| 423 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17; | ||
| 424 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa; | ||
| 425 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde; | ||
| 426 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = | ||
| 427 | VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2; | ||
| 428 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC; | ||
| 429 | VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0; | ||
| 430 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= | ||
| 431 | ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
| 432 | break; | ||
| 433 | default: | ||
| 434 | ret = -EINVAL; | ||
| 435 | return ret; | ||
| 436 | break; | ||
| 437 | } | ||
| 438 | |||
| 439 | switch(cmd) { | ||
| 440 | case 1: | ||
| 441 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= | ||
| 442 | (VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
| 443 | break; | ||
| 444 | case 2: | ||
| 445 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= | ||
| 446 | ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
| 447 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; | ||
| 448 | break; | ||
| 449 | case 3: | ||
| 450 | break; | ||
| 451 | default: | ||
| 452 | ret = -EINVAL; | ||
| 453 | return ret; | ||
| 454 | break; | ||
| 455 | } | ||
| 456 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2); | ||
| 457 | ret=vfc_update_saa9051(dev); | ||
| 458 | udelay(500); | ||
| 459 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2); | ||
| 460 | ret=vfc_update_saa9051(dev); | ||
| 461 | return ret; | ||
| 462 | } | ||
| 463 | |||
| 464 | static int vfc_set_video_ioctl(struct inode *inode, struct file *file, | ||
| 465 | struct vfc_dev *dev, unsigned long arg) | ||
| 466 | { | ||
| 467 | int ret = 0; | ||
| 468 | int cmd; | ||
| 469 | |||
| 470 | if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { | ||
| 471 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
| 472 | "vfc_set_video_ioctl\n", | ||
| 473 | dev->instance)); | ||
| 474 | return ret; | ||
| 475 | } | ||
| 476 | |||
| 477 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", | ||
| 478 | dev->instance, cmd)); | ||
| 479 | switch(cmd) { | ||
| 480 | case STD_NTSC: | ||
| 481 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT; | ||
| 482 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | | ||
| 483 | VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS; | ||
| 484 | ret = vfc_update_saa9051(dev); | ||
| 485 | break; | ||
| 486 | case STD_PAL: | ||
| 487 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | | ||
| 488 | VFC_SAA9051_CCFR1 | | ||
| 489 | VFC_SAA9051_CCFR0 | | ||
| 490 | VFC_SAA9051_FS); | ||
| 491 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT; | ||
| 492 | ret = vfc_update_saa9051(dev); | ||
| 493 | break; | ||
| 494 | |||
| 495 | case COLOR_ON: | ||
| 496 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO; | ||
| 497 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= | ||
| 498 | ~(VFC_SAA9051_BY | VFC_SAA9051_PF); | ||
| 499 | ret = vfc_update_saa9051(dev); | ||
| 500 | break; | ||
| 501 | case MONO: | ||
| 502 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO); | ||
| 503 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= | ||
| 504 | (VFC_SAA9051_BY | VFC_SAA9051_PF); | ||
| 505 | ret = vfc_update_saa9051(dev); | ||
| 506 | break; | ||
| 507 | default: | ||
| 508 | ret = -EINVAL; | ||
| 509 | break; | ||
| 510 | }; | ||
| 511 | |||
| 512 | return ret; | ||
| 513 | } | ||
| 514 | |||
| 515 | static int vfc_get_video_ioctl(struct inode *inode, struct file *file, | ||
| 516 | struct vfc_dev *dev, unsigned long arg) | ||
| 517 | { | ||
| 518 | int ret = 0; | ||
| 519 | unsigned int status = NO_LOCK; | ||
| 520 | unsigned char buf[1]; | ||
| 521 | |||
| 522 | if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) { | ||
| 523 | printk(KERN_ERR "vfc%d: Unable to get status\n", | ||
| 524 | dev->instance); | ||
| 525 | return -EIO; | ||
| 526 | } | ||
| 527 | |||
| 528 | if(buf[0] & VFC_SAA9051_HLOCK) { | ||
| 529 | status = NO_LOCK; | ||
| 530 | } else if(buf[0] & VFC_SAA9051_FD) { | ||
| 531 | if(buf[0] & VFC_SAA9051_CD) | ||
| 532 | status = NTSC_COLOR; | ||
| 533 | else | ||
| 534 | status = NTSC_NOCOLOR; | ||
| 535 | } else { | ||
| 536 | if(buf[0] & VFC_SAA9051_CD) | ||
| 537 | status = PAL_COLOR; | ||
| 538 | else | ||
| 539 | status = PAL_NOCOLOR; | ||
| 540 | } | ||
| 541 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; " | ||
| 542 | "buf[0]=%x\n", dev->instance, status, buf[0])); | ||
| 543 | |||
| 544 | if (copy_to_user((void __user *)arg,&status,sizeof(unsigned int))) { | ||
| 545 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
| 546 | "vfc_get_video_ioctl\n", | ||
| 547 | dev->instance)); | ||
| 548 | return ret; | ||
| 549 | } | ||
| 550 | return ret; | ||
| 551 | } | ||
| 552 | |||
| 553 | static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
| 554 | unsigned long arg) | ||
| 555 | { | ||
| 556 | int ret = 0; | ||
| 557 | unsigned int tmp; | ||
| 558 | struct vfc_dev *dev; | ||
| 559 | void __user *argp = (void __user *)arg; | ||
| 560 | |||
| 561 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
| 562 | if(dev == NULL) | ||
| 563 | return -ENODEV; | ||
| 564 | |||
| 565 | switch(cmd & 0x0000ffff) { | ||
| 566 | case VFCGCTRL: | ||
| 567 | #if 0 | ||
| 568 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance)); | ||
| 569 | #endif | ||
| 570 | tmp = sbus_readl(&dev->regs->control); | ||
| 571 | if(copy_to_user(argp, &tmp, sizeof(unsigned int))) { | ||
| 572 | ret = -EFAULT; | ||
| 573 | break; | ||
| 574 | } | ||
| 575 | ret = 0; | ||
| 576 | break; | ||
| 577 | case VFCSCTRL: | ||
| 578 | ret = vfc_set_control_ioctl(inode, file, dev, arg); | ||
| 579 | break; | ||
| 580 | case VFCGVID: | ||
| 581 | ret = vfc_get_video_ioctl(inode, file, dev, arg); | ||
| 582 | break; | ||
| 583 | case VFCSVID: | ||
| 584 | ret = vfc_set_video_ioctl(inode, file, dev, arg); | ||
| 585 | break; | ||
| 586 | case VFCHUE: | ||
| 587 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance)); | ||
| 588 | if(copy_from_user(&tmp,argp,sizeof(unsigned int))) { | ||
| 589 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " | ||
| 590 | "to IOCTL(VFCHUE)", dev->instance)); | ||
| 591 | ret = -EFAULT; | ||
| 592 | } else { | ||
| 593 | VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp; | ||
| 594 | vfc_update_saa9051(dev); | ||
| 595 | ret = 0; | ||
| 596 | } | ||
| 597 | break; | ||
| 598 | case VFCPORTCHG: | ||
| 599 | ret = vfc_port_change_ioctl(inode, file, dev, arg); | ||
| 600 | break; | ||
| 601 | case VFCRDINFO: | ||
| 602 | ret = -EINVAL; | ||
| 603 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance)); | ||
| 604 | break; | ||
| 605 | default: | ||
| 606 | ret = vfc_debug(vfc_get_dev_ptr(iminor(inode)), cmd, argp); | ||
| 607 | break; | ||
| 608 | }; | ||
| 609 | |||
| 610 | return ret; | ||
| 611 | } | ||
| 612 | |||
| 613 | static int vfc_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 614 | { | ||
| 615 | unsigned int map_size, ret, map_offset; | ||
| 616 | struct vfc_dev *dev; | ||
| 617 | |||
| 618 | dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode)); | ||
| 619 | if(dev == NULL) | ||
| 620 | return -ENODEV; | ||
| 621 | |||
| 622 | map_size = vma->vm_end - vma->vm_start; | ||
| 623 | if(map_size > sizeof(struct vfc_regs)) | ||
| 624 | map_size = sizeof(struct vfc_regs); | ||
| 625 | |||
| 626 | vma->vm_flags |= | ||
| 627 | (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); | ||
| 628 | map_offset = (unsigned int) (long)dev->phys_regs; | ||
| 629 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
| 630 | MK_IOSPACE_PFN(dev->which_io, | ||
| 631 | map_offset >> PAGE_SHIFT), | ||
| 632 | map_size, vma->vm_page_prot); | ||
| 633 | |||
| 634 | if(ret) | ||
| 635 | return -EAGAIN; | ||
| 636 | |||
| 637 | return 0; | ||
| 638 | } | ||
| 639 | |||
| 640 | |||
| 641 | static const struct file_operations vfc_fops = { | ||
| 642 | .owner = THIS_MODULE, | ||
| 643 | .llseek = no_llseek, | ||
| 644 | .ioctl = vfc_ioctl, | ||
| 645 | .mmap = vfc_mmap, | ||
| 646 | .open = vfc_open, | ||
| 647 | .release = vfc_release, | ||
| 648 | }; | ||
| 649 | |||
| 650 | static int vfc_probe(void) | ||
| 651 | { | ||
| 652 | struct sbus_bus *sbus; | ||
| 653 | struct sbus_dev *sdev = NULL; | ||
| 654 | int ret; | ||
| 655 | int instance = 0, cards = 0; | ||
| 656 | |||
| 657 | for_all_sbusdev(sdev, sbus) { | ||
| 658 | if (strcmp(sdev->prom_name, "vfc") == 0) { | ||
| 659 | cards++; | ||
| 660 | continue; | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | if (!cards) | ||
| 665 | return -ENODEV; | ||
| 666 | |||
| 667 | vfc_dev_lst = kcalloc(cards + 1, sizeof(struct vfc_dev*), GFP_KERNEL); | ||
| 668 | if (vfc_dev_lst == NULL) | ||
| 669 | return -ENOMEM; | ||
| 670 | vfc_dev_lst[cards] = NULL; | ||
| 671 | |||
| 672 | ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); | ||
| 673 | if(ret) { | ||
| 674 | printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR); | ||
| 675 | kfree(vfc_dev_lst); | ||
| 676 | return -EIO; | ||
| 677 | } | ||
| 678 | instance = 0; | ||
| 679 | for_all_sbusdev(sdev, sbus) { | ||
| 680 | if (strcmp(sdev->prom_name, "vfc") == 0) { | ||
| 681 | vfc_dev_lst[instance]=(struct vfc_dev *) | ||
| 682 | kmalloc(sizeof(struct vfc_dev), GFP_KERNEL); | ||
| 683 | if (vfc_dev_lst[instance] == NULL) | ||
| 684 | return -ENOMEM; | ||
| 685 | ret = init_vfc_device(sdev, | ||
| 686 | vfc_dev_lst[instance], | ||
| 687 | instance); | ||
| 688 | if(ret) { | ||
| 689 | printk(KERN_ERR "Unable to initialize" | ||
| 690 | " vfc%d device\n", | ||
| 691 | instance); | ||
| 692 | } else { | ||
| 693 | } | ||
| 694 | |||
| 695 | instance++; | ||
| 696 | continue; | ||
| 697 | } | ||
| 698 | } | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | #ifdef MODULE | ||
| 704 | int init_module(void) | ||
| 705 | #else | ||
| 706 | int vfc_init(void) | ||
| 707 | #endif | ||
| 708 | { | ||
| 709 | return vfc_probe(); | ||
| 710 | } | ||
| 711 | |||
| 712 | #ifdef MODULE | ||
| 713 | static void deinit_vfc_device(struct vfc_dev *dev) | ||
| 714 | { | ||
| 715 | if(dev == NULL) | ||
| 716 | return; | ||
| 717 | sbus_iounmap(dev->regs, sizeof(struct vfc_regs)); | ||
| 718 | kfree(dev); | ||
| 719 | } | ||
| 720 | |||
| 721 | void cleanup_module(void) | ||
| 722 | { | ||
| 723 | struct vfc_dev **devp; | ||
| 724 | |||
| 725 | unregister_chrdev(VFC_MAJOR,vfcstr); | ||
| 726 | |||
| 727 | for (devp = vfc_dev_lst; *devp; devp++) | ||
| 728 | deinit_vfc_device(*devp); | ||
| 729 | |||
| 730 | kfree(vfc_dev_lst); | ||
| 731 | return; | ||
| 732 | } | ||
| 733 | #endif | ||
| 734 | |||
| 735 | MODULE_LICENSE("GPL"); | ||
| 736 | |||
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c deleted file mode 100644 index 32b986e0ed78..000000000000 --- a/drivers/sbus/char/vfc_i2c.c +++ /dev/null | |||
| @@ -1,335 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * drivers/sbus/char/vfc_i2c.c | ||
| 3 | * | ||
| 4 | * Driver for the Videopix Frame Grabber. | ||
| 5 | * | ||
| 6 | * Functions that support the Phillips i2c(I squared C) bus on the vfc | ||
| 7 | * Documentation for the Phillips I2C bus can be found on the | ||
| 8 | * phillips home page | ||
| 9 | * | ||
| 10 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* NOTE: It seems to me that the documentation regarding the | ||
| 15 | pcd8584t/pcf8584 does not show the correct way to address the i2c bus. | ||
| 16 | Based on the information on the I2C bus itself and the remainder of | ||
| 17 | the Phillips docs the following algorithms appear to be correct. I am | ||
| 18 | fairly certain that the flowcharts in the phillips docs are wrong. */ | ||
| 19 | |||
| 20 | |||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/string.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | #include <linux/sched.h> | ||
| 26 | #include <linux/wait.h> | ||
| 27 | #include <linux/delay.h> | ||
| 28 | #include <asm/openprom.h> | ||
| 29 | #include <asm/oplib.h> | ||
| 30 | #include <asm/io.h> | ||
| 31 | #include <asm/system.h> | ||
| 32 | #include <asm/sbus.h> | ||
| 33 | |||
| 34 | #if 0 | ||
| 35 | #define VFC_I2C_DEBUG | ||
| 36 | #endif | ||
| 37 | |||
| 38 | #include "vfc.h" | ||
| 39 | #include "vfc_i2c.h" | ||
| 40 | |||
| 41 | #define WRITE_S1(__val) \ | ||
| 42 | sbus_writel(__val, &dev->regs->i2c_s1) | ||
| 43 | #define WRITE_REG(__val) \ | ||
| 44 | sbus_writel(__val, &dev->regs->i2c_reg) | ||
| 45 | |||
| 46 | #define VFC_I2C_READ (0x1) | ||
| 47 | #define VFC_I2C_WRITE (0x0) | ||
| 48 | |||
| 49 | /****** | ||
| 50 | The i2c bus controller chip on the VFC is a pcd8584t, but | ||
| 51 | phillips claims it doesn't exist. As far as I can tell it is | ||
| 52 | identical to the PCF8584 so I treat it like it is the pcf8584. | ||
| 53 | |||
| 54 | NOTE: The pcf8584 only cares | ||
| 55 | about the msb of the word you feed it | ||
| 56 | *****/ | ||
| 57 | |||
| 58 | int vfc_pcf8584_init(struct vfc_dev *dev) | ||
| 59 | { | ||
| 60 | /* This will also choose register S0_OWN so we can set it. */ | ||
| 61 | WRITE_S1(RESET); | ||
| 62 | |||
| 63 | /* The pcf8584 shifts this value left one bit and uses | ||
| 64 | * it as its i2c bus address. | ||
| 65 | */ | ||
| 66 | WRITE_REG(0x55000000); | ||
| 67 | |||
| 68 | /* This will set the i2c bus at the same speed sun uses, | ||
| 69 | * and set another magic bit. | ||
| 70 | */ | ||
| 71 | WRITE_S1(SELECT(S2)); | ||
| 72 | WRITE_REG(0x14000000); | ||
| 73 | |||
| 74 | /* Enable the serial port, idle the i2c bus and set | ||
| 75 | * the data reg to s0. | ||
| 76 | */ | ||
| 77 | WRITE_S1(CLEAR_I2C_BUS); | ||
| 78 | udelay(100); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) | ||
| 83 | { | ||
| 84 | schedule_timeout_uninterruptible(usecs_to_jiffies(usecs)); | ||
| 85 | } | ||
| 86 | |||
| 87 | void inline vfc_i2c_delay(struct vfc_dev *dev) | ||
| 88 | { | ||
| 89 | vfc_i2c_delay_no_busy(dev, 100); | ||
| 90 | } | ||
| 91 | |||
| 92 | int vfc_init_i2c_bus(struct vfc_dev *dev) | ||
| 93 | { | ||
| 94 | WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK); | ||
| 95 | vfc_i2c_reset_bus(dev); | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | int vfc_i2c_reset_bus(struct vfc_dev *dev) | ||
| 100 | { | ||
| 101 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", | ||
| 102 | dev->instance)); | ||
| 103 | if(dev == NULL) | ||
| 104 | return -EINVAL; | ||
| 105 | if(dev->regs == NULL) | ||
| 106 | return -EINVAL; | ||
| 107 | WRITE_S1(SEND_I2C_STOP); | ||
| 108 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
| 109 | vfc_i2c_delay(dev); | ||
| 110 | WRITE_S1(CLEAR_I2C_BUS); | ||
| 111 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", | ||
| 112 | dev->instance, | ||
| 113 | sbus_readl(&dev->regs->i2c_s1))); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int vfc_i2c_wait_for_bus(struct vfc_dev *dev) | ||
| 118 | { | ||
| 119 | int timeout = 1000; | ||
| 120 | |||
| 121 | while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) { | ||
| 122 | if(!(timeout--)) | ||
| 123 | return -ETIMEDOUT; | ||
| 124 | vfc_i2c_delay(dev); | ||
| 125 | } | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack) | ||
| 130 | { | ||
| 131 | int timeout = 1000; | ||
| 132 | int s1; | ||
| 133 | |||
| 134 | while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) { | ||
| 135 | if (!(timeout--)) | ||
| 136 | return -ETIMEDOUT; | ||
| 137 | vfc_i2c_delay(dev); | ||
| 138 | } | ||
| 139 | if (ack == VFC_I2C_ACK_CHECK) { | ||
| 140 | if(s1 & LRB) | ||
| 141 | return -EIO; | ||
| 142 | } | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | #define SHIFT(a) ((a) << 24) | ||
| 147 | static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, | ||
| 148 | char mode) | ||
| 149 | { | ||
| 150 | int ret, raddr; | ||
| 151 | #if 1 | ||
| 152 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
| 153 | WRITE_S1(SELECT(S0) | ENABLE_SERIAL); | ||
| 154 | vfc_i2c_delay(dev); | ||
| 155 | #endif | ||
| 156 | |||
| 157 | switch(mode) { | ||
| 158 | case VFC_I2C_READ: | ||
| 159 | raddr = SHIFT(((unsigned int)addr | 0x1)); | ||
| 160 | WRITE_REG(raddr); | ||
| 161 | VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", | ||
| 162 | dev->instance, addr | 0x1)); | ||
| 163 | break; | ||
| 164 | case VFC_I2C_WRITE: | ||
| 165 | raddr = SHIFT((unsigned int)addr & ~0x1); | ||
| 166 | WRITE_REG(raddr); | ||
| 167 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", | ||
| 168 | dev->instance, addr & ~0x1)); | ||
| 169 | break; | ||
| 170 | default: | ||
| 171 | return -EINVAL; | ||
| 172 | }; | ||
| 173 | |||
| 174 | WRITE_S1(SEND_I2C_START); | ||
| 175 | vfc_i2c_delay(dev); | ||
| 176 | ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait | ||
| 177 | for the | ||
| 178 | i2c send | ||
| 179 | to finish | ||
| 180 | here but | ||
| 181 | Sun | ||
| 182 | doesn't, | ||
| 183 | hmm */ | ||
| 184 | if (ret) { | ||
| 185 | printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", | ||
| 186 | dev->instance); | ||
| 187 | return ret; | ||
| 188 | } else if (mode == VFC_I2C_READ) { | ||
| 189 | if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { | ||
| 190 | printk(KERN_WARNING | ||
| 191 | "vfc%d: returned slave address " | ||
| 192 | "mismatch(%x,%x)\n", | ||
| 193 | dev->instance, raddr, ret); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) | ||
| 200 | { | ||
| 201 | int ret; | ||
| 202 | u32 val = SHIFT((unsigned int)*byte); | ||
| 203 | |||
| 204 | WRITE_REG(val); | ||
| 205 | |||
| 206 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); | ||
| 207 | switch(ret) { | ||
| 208 | case -ETIMEDOUT: | ||
| 209 | printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", | ||
| 210 | dev->instance); | ||
| 211 | break; | ||
| 212 | case -EIO: | ||
| 213 | ret = XMIT_LAST_BYTE; | ||
| 214 | break; | ||
| 215 | default: | ||
| 216 | break; | ||
| 217 | }; | ||
| 218 | |||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, | ||
| 223 | int last) | ||
| 224 | { | ||
| 225 | int ret; | ||
| 226 | |||
| 227 | if (last) { | ||
| 228 | WRITE_REG(NEGATIVE_ACK); | ||
| 229 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", | ||
| 230 | dev->instance)); | ||
| 231 | } else { | ||
| 232 | WRITE_S1(ACK); | ||
| 233 | } | ||
| 234 | |||
| 235 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); | ||
| 236 | if(ret) { | ||
| 237 | printk(KERN_ERR "vfc%d: " | ||
| 238 | "VFC recv byte timed out\n", | ||
| 239 | dev->instance); | ||
| 240 | } | ||
| 241 | *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; | ||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | |||
| 245 | int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, | ||
| 246 | char *buf, int count) | ||
| 247 | { | ||
| 248 | int ret, last; | ||
| 249 | |||
| 250 | if(!(count && buf && dev && dev->regs) ) | ||
| 251 | return -EINVAL; | ||
| 252 | |||
| 253 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
| 254 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
| 255 | return ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { | ||
| 259 | WRITE_S1(SEND_I2C_STOP); | ||
| 260 | vfc_i2c_delay(dev); | ||
| 261 | return ret; | ||
| 262 | } | ||
| 263 | |||
| 264 | last = 0; | ||
| 265 | while (count--) { | ||
| 266 | if (!count) | ||
| 267 | last = 1; | ||
| 268 | if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { | ||
| 269 | printk(KERN_ERR "vfc%d: " | ||
| 270 | "VFC error while receiving byte\n", | ||
| 271 | dev->instance); | ||
| 272 | WRITE_S1(SEND_I2C_STOP); | ||
| 273 | ret = -EINVAL; | ||
| 274 | } | ||
| 275 | buf++; | ||
| 276 | } | ||
| 277 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
| 278 | vfc_i2c_delay(dev); | ||
| 279 | return ret; | ||
| 280 | } | ||
| 281 | |||
| 282 | int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, | ||
| 283 | char *buf, int count) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | |||
| 287 | if (!(buf && dev && dev->regs)) | ||
| 288 | return -EINVAL; | ||
| 289 | |||
| 290 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
| 291 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
| 292 | return ret; | ||
| 293 | } | ||
| 294 | |||
| 295 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { | ||
| 296 | WRITE_S1(SEND_I2C_STOP); | ||
| 297 | vfc_i2c_delay(dev); | ||
| 298 | return ret; | ||
| 299 | } | ||
| 300 | |||
| 301 | while(count--) { | ||
| 302 | ret = vfc_i2c_xmit_byte(dev, buf); | ||
| 303 | switch(ret) { | ||
| 304 | case XMIT_LAST_BYTE: | ||
| 305 | VFC_I2C_DEBUG_PRINTK(("vfc%d: " | ||
| 306 | "Receiver ended transmission with " | ||
| 307 | " %d bytes remaining\n", | ||
| 308 | dev->instance, count)); | ||
| 309 | ret = 0; | ||
| 310 | goto done; | ||
| 311 | break; | ||
| 312 | case 0: | ||
| 313 | break; | ||
| 314 | default: | ||
| 315 | printk(KERN_ERR "vfc%d: " | ||
| 316 | "VFC error while sending byte\n", dev->instance); | ||
| 317 | break; | ||
| 318 | }; | ||
| 319 | |||
| 320 | buf++; | ||
| 321 | } | ||
| 322 | done: | ||
| 323 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
| 324 | vfc_i2c_delay(dev); | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | |||
| 329 | |||
| 330 | |||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | |||
diff --git a/drivers/sbus/char/vfc_i2c.h b/drivers/sbus/char/vfc_i2c.h deleted file mode 100644 index a2e6973209d5..000000000000 --- a/drivers/sbus/char/vfc_i2c.h +++ /dev/null | |||
| @@ -1,44 +0,0 @@ | |||
| 1 | #ifndef _LINUX_VFC_I2C_H_ | ||
| 2 | #define _LINUX_VFC_I2C_H_ | ||
| 3 | |||
| 4 | /* control bits */ | ||
| 5 | #define PIN (0x80000000) | ||
| 6 | #define ESO (0x40000000) | ||
| 7 | #define ES1 (0x20000000) | ||
| 8 | #define ES2 (0x10000000) | ||
| 9 | #define ENI (0x08000000) | ||
| 10 | #define STA (0x04000000) | ||
| 11 | #define STO (0x02000000) | ||
| 12 | #define ACK (0x01000000) | ||
| 13 | |||
| 14 | /* status bits */ | ||
| 15 | #define STS (0x20000000) | ||
| 16 | #define BER (0x10000000) | ||
| 17 | #define LRB (0x08000000) | ||
| 18 | #define AAS (0x04000000) | ||
| 19 | #define LAB (0x02000000) | ||
| 20 | #define BB (0x01000000) | ||
| 21 | |||
| 22 | #define SEND_I2C_START (PIN | ESO | STA) | ||
| 23 | #define SEND_I2C_STOP (PIN | ESO | STO) | ||
| 24 | #define CLEAR_I2C_BUS (PIN | ESO | ACK) | ||
| 25 | #define NEGATIVE_ACK ((ESO) & ~ACK) | ||
| 26 | |||
| 27 | #define SELECT(a) (a) | ||
| 28 | #define S0 (PIN | ESO | ES1) | ||
| 29 | #define S0_OWN (PIN) | ||
| 30 | #define S2 (PIN | ES1) | ||
| 31 | #define S3 (PIN | ES2) | ||
| 32 | |||
| 33 | #define ENABLE_SERIAL (PIN | ESO) | ||
| 34 | #define DISABLE_SERIAL (PIN) | ||
| 35 | #define RESET (PIN) | ||
| 36 | |||
| 37 | #define XMIT_LAST_BYTE (1) | ||
| 38 | #define VFC_I2C_ACK_CHECK (1) | ||
| 39 | #define VFC_I2C_NO_ACK_CHECK (0) | ||
| 40 | |||
| 41 | #endif /* _LINUX_VFC_I2C_H_ */ | ||
| 42 | |||
| 43 | |||
| 44 | |||
diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c deleted file mode 100644 index ab0d2de3324c..000000000000 --- a/drivers/sbus/dvma.c +++ /dev/null | |||
| @@ -1,136 +0,0 @@ | |||
| 1 | /* dvma.c: Routines that are used to access DMA on the Sparc SBus. | ||
| 2 | * | ||
| 3 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/string.h> | ||
| 7 | #include <linux/kernel.h> | ||
| 8 | #include <linux/slab.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/delay.h> | ||
| 11 | |||
| 12 | #include <asm/oplib.h> | ||
| 13 | #include <asm/io.h> | ||
| 14 | #include <asm/dma.h> | ||
| 15 | #include <asm/sbus.h> | ||
| 16 | |||
| 17 | struct sbus_dma *dma_chain; | ||
| 18 | |||
| 19 | static void __init init_one_dvma(struct sbus_dma *dma, int num_dma) | ||
| 20 | { | ||
| 21 | printk("dma%d: ", num_dma); | ||
| 22 | |||
| 23 | dma->next = NULL; | ||
| 24 | dma->running = 0; /* No transfers going on as of yet */ | ||
| 25 | dma->allocated = 0; /* No one has allocated us yet */ | ||
| 26 | switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) { | ||
| 27 | case DMA_VERS0: | ||
| 28 | dma->revision = dvmarev0; | ||
| 29 | printk("Revision 0 "); | ||
| 30 | break; | ||
| 31 | case DMA_ESCV1: | ||
| 32 | dma->revision = dvmaesc1; | ||
| 33 | printk("ESC Revision 1 "); | ||
| 34 | break; | ||
| 35 | case DMA_VERS1: | ||
| 36 | dma->revision = dvmarev1; | ||
| 37 | printk("Revision 1 "); | ||
| 38 | break; | ||
| 39 | case DMA_VERS2: | ||
| 40 | dma->revision = dvmarev2; | ||
| 41 | printk("Revision 2 "); | ||
| 42 | break; | ||
| 43 | case DMA_VERHME: | ||
| 44 | dma->revision = dvmahme; | ||
| 45 | printk("HME DVMA gate array "); | ||
| 46 | break; | ||
| 47 | case DMA_VERSPLUS: | ||
| 48 | dma->revision = dvmarevplus; | ||
| 49 | printk("Revision 1 PLUS "); | ||
| 50 | break; | ||
| 51 | default: | ||
| 52 | printk("unknown dma version %08x", | ||
| 53 | sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID); | ||
| 54 | dma->allocated = 1; | ||
| 55 | break; | ||
| 56 | } | ||
| 57 | printk("\n"); | ||
| 58 | } | ||
| 59 | |||
| 60 | /* Probe this SBus DMA module(s) */ | ||
| 61 | void __init dvma_init(struct sbus_bus *sbus) | ||
| 62 | { | ||
| 63 | struct sbus_dev *this_dev; | ||
| 64 | struct sbus_dma *dma; | ||
| 65 | struct sbus_dma *dchain; | ||
| 66 | static int num_dma = 0; | ||
| 67 | |||
| 68 | for_each_sbusdev(this_dev, sbus) { | ||
| 69 | char *name = this_dev->prom_name; | ||
| 70 | int hme = 0; | ||
| 71 | |||
| 72 | if(!strcmp(name, "SUNW,fas")) | ||
| 73 | hme = 1; | ||
| 74 | else if(strcmp(name, "dma") && | ||
| 75 | strcmp(name, "ledma") && | ||
| 76 | strcmp(name, "espdma")) | ||
| 77 | continue; | ||
| 78 | |||
| 79 | /* Found one... */ | ||
| 80 | dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); | ||
| 81 | |||
| 82 | dma->sdev = this_dev; | ||
| 83 | |||
| 84 | /* Put at end of dma chain */ | ||
| 85 | dchain = dma_chain; | ||
| 86 | if(dchain) { | ||
| 87 | while(dchain->next) | ||
| 88 | dchain = dchain->next; | ||
| 89 | dchain->next = dma; | ||
| 90 | } else { | ||
| 91 | /* We're the first in line */ | ||
| 92 | dma_chain = dma; | ||
| 93 | } | ||
| 94 | |||
| 95 | dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0, | ||
| 96 | dma->sdev->resource[0].end - dma->sdev->resource[0].start + 1, | ||
| 97 | "dma"); | ||
| 98 | |||
| 99 | dma->node = dma->sdev->prom_node; | ||
| 100 | |||
| 101 | init_one_dvma(dma, num_dma++); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | #ifdef CONFIG_SUN4 | ||
| 106 | |||
| 107 | #include <asm/sun4paddr.h> | ||
| 108 | |||
| 109 | void __init sun4_dvma_init(void) | ||
| 110 | { | ||
| 111 | struct sbus_dma *dma; | ||
| 112 | struct resource r; | ||
| 113 | |||
| 114 | if(sun4_dma_physaddr) { | ||
| 115 | dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); | ||
| 116 | |||
| 117 | /* No SBUS */ | ||
| 118 | dma->sdev = NULL; | ||
| 119 | |||
| 120 | /* Only one DMA device */ | ||
| 121 | dma_chain = dma; | ||
| 122 | |||
| 123 | memset(&r, 0, sizeof(r)); | ||
| 124 | r.start = sun4_dma_physaddr; | ||
| 125 | dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma"); | ||
| 126 | |||
| 127 | /* No prom node */ | ||
| 128 | dma->node = 0x0; | ||
| 129 | |||
| 130 | init_one_dvma(dma, 0); | ||
| 131 | } else { | ||
| 132 | dma_chain = NULL; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | #endif | ||
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c deleted file mode 100644 index 9c129248466c..000000000000 --- a/drivers/sbus/sbus.c +++ /dev/null | |||
| @@ -1,316 +0,0 @@ | |||
| 1 | /* sbus.c: SBus support routines. | ||
| 2 | * | ||
| 3 | * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/slab.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/device.h> | ||
| 10 | #include <linux/of_device.h> | ||
| 11 | |||
| 12 | #include <asm/system.h> | ||
| 13 | #include <asm/sbus.h> | ||
| 14 | #include <asm/dma.h> | ||
| 15 | #include <asm/oplib.h> | ||
| 16 | #include <asm/prom.h> | ||
| 17 | #include <asm/bpp.h> | ||
| 18 | #include <asm/irq.h> | ||
| 19 | |||
| 20 | static ssize_t | ||
| 21 | show_sbusobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) | ||
| 22 | { | ||
| 23 | struct sbus_dev *sbus; | ||
| 24 | |||
| 25 | sbus = to_sbus_device(dev); | ||
| 26 | |||
| 27 | return snprintf (buf, PAGE_SIZE, "%s\n", sbus->ofdev.node->full_name); | ||
| 28 | } | ||
| 29 | |||
| 30 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_sbusobppath_attr, NULL); | ||
| 31 | |||
| 32 | struct sbus_bus *sbus_root; | ||
| 33 | |||
| 34 | static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) | ||
| 35 | { | ||
| 36 | struct dev_archdata *sd; | ||
| 37 | unsigned long base; | ||
| 38 | const void *pval; | ||
| 39 | int len, err; | ||
| 40 | |||
| 41 | sdev->prom_node = dp->node; | ||
| 42 | strcpy(sdev->prom_name, dp->name); | ||
| 43 | |||
| 44 | pval = of_get_property(dp, "reg", &len); | ||
| 45 | sdev->num_registers = 0; | ||
| 46 | if (pval) { | ||
| 47 | memcpy(sdev->reg_addrs, pval, len); | ||
| 48 | |||
| 49 | sdev->num_registers = | ||
| 50 | len / sizeof(struct linux_prom_registers); | ||
| 51 | |||
| 52 | base = (unsigned long) sdev->reg_addrs[0].phys_addr; | ||
| 53 | |||
| 54 | /* Compute the slot number. */ | ||
| 55 | if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) | ||
| 56 | sdev->slot = sbus_dev_slot(base); | ||
| 57 | else | ||
| 58 | sdev->slot = sdev->reg_addrs[0].which_io; | ||
| 59 | } | ||
| 60 | |||
| 61 | pval = of_get_property(dp, "ranges", &len); | ||
| 62 | sdev->num_device_ranges = 0; | ||
| 63 | if (pval) { | ||
| 64 | memcpy(sdev->device_ranges, pval, len); | ||
| 65 | sdev->num_device_ranges = | ||
| 66 | len / sizeof(struct linux_prom_ranges); | ||
| 67 | } | ||
| 68 | |||
| 69 | sbus_fill_device_irq(sdev); | ||
| 70 | |||
| 71 | sd = &sdev->ofdev.dev.archdata; | ||
| 72 | sd->prom_node = dp; | ||
| 73 | sd->op = &sdev->ofdev; | ||
| 74 | |||
| 75 | sdev->ofdev.node = dp; | ||
| 76 | if (sdev->parent) | ||
| 77 | sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; | ||
| 78 | else | ||
| 79 | sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; | ||
| 80 | sdev->ofdev.dev.bus = &sbus_bus_type; | ||
| 81 | dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node); | ||
| 82 | |||
| 83 | if (of_device_register(&sdev->ofdev) != 0) | ||
| 84 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", | ||
| 85 | dp->path_component_name); | ||
| 86 | |||
| 87 | /* WE HAVE BEEN INVADED BY ALIENS! */ | ||
| 88 | err = sysfs_create_file(&sdev->ofdev.dev.kobj, &dev_attr_obppath.attr); | ||
| 89 | } | ||
| 90 | |||
| 91 | static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) | ||
| 92 | { | ||
| 93 | const void *pval; | ||
| 94 | int len; | ||
| 95 | |||
| 96 | pval = of_get_property(dp, "ranges", &len); | ||
| 97 | sbus->num_sbus_ranges = 0; | ||
| 98 | if (pval) { | ||
| 99 | memcpy(sbus->sbus_ranges, pval, len); | ||
| 100 | sbus->num_sbus_ranges = | ||
| 101 | len / sizeof(struct linux_prom_ranges); | ||
| 102 | |||
| 103 | sbus_arch_bus_ranges_init(dp->parent, sbus); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, | ||
| 108 | int num_ranges, | ||
| 109 | struct linux_prom_registers *regs, | ||
| 110 | int num_regs) | ||
| 111 | { | ||
| 112 | if (num_ranges) { | ||
| 113 | int regnum; | ||
| 114 | |||
| 115 | for (regnum = 0; regnum < num_regs; regnum++) { | ||
| 116 | int rngnum; | ||
| 117 | |||
| 118 | for (rngnum = 0; rngnum < num_ranges; rngnum++) { | ||
| 119 | if (regs[regnum].which_io == ranges[rngnum].ot_child_space) | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | if (rngnum == num_ranges) { | ||
| 123 | /* We used to flag this as an error. Actually | ||
| 124 | * some devices do not report the regs as we expect. | ||
| 125 | * For example, see SUNW,pln device. In that case | ||
| 126 | * the reg property is in a format internal to that | ||
| 127 | * node, ie. it is not in the SBUS register space | ||
| 128 | * per se. -DaveM | ||
| 129 | */ | ||
| 130 | return; | ||
| 131 | } | ||
| 132 | regs[regnum].which_io = ranges[rngnum].ot_parent_space; | ||
| 133 | regs[regnum].phys_addr -= ranges[rngnum].ot_child_base; | ||
| 134 | regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | static void __init __fixup_regs_sdev(struct sbus_dev *sdev) | ||
| 140 | { | ||
| 141 | if (sdev->num_registers != 0) { | ||
| 142 | struct sbus_dev *parent = sdev->parent; | ||
| 143 | int i; | ||
| 144 | |||
| 145 | while (parent != NULL) { | ||
| 146 | __apply_ranges_to_regs(parent->device_ranges, | ||
| 147 | parent->num_device_ranges, | ||
| 148 | sdev->reg_addrs, | ||
| 149 | sdev->num_registers); | ||
| 150 | |||
| 151 | parent = parent->parent; | ||
| 152 | } | ||
| 153 | |||
| 154 | __apply_ranges_to_regs(sdev->bus->sbus_ranges, | ||
| 155 | sdev->bus->num_sbus_ranges, | ||
| 156 | sdev->reg_addrs, | ||
| 157 | sdev->num_registers); | ||
| 158 | |||
| 159 | for (i = 0; i < sdev->num_registers; i++) { | ||
| 160 | struct resource *res = &sdev->resource[i]; | ||
| 161 | |||
| 162 | res->start = sdev->reg_addrs[i].phys_addr; | ||
| 163 | res->end = (res->start + | ||
| 164 | (unsigned long)sdev->reg_addrs[i].reg_size - 1UL); | ||
| 165 | res->flags = IORESOURCE_IO | | ||
| 166 | (sdev->reg_addrs[i].which_io & 0xff); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev) | ||
| 172 | { | ||
| 173 | struct sbus_dev *sdev; | ||
| 174 | |||
| 175 | for (sdev = first_sdev; sdev; sdev = sdev->next) { | ||
| 176 | if (sdev->child) | ||
| 177 | sbus_fixup_all_regs(sdev->child); | ||
| 178 | __fixup_regs_sdev(sdev); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | /* We preserve the "probe order" of these bus and device lists to give | ||
| 183 | * the same ordering as the old code. | ||
| 184 | */ | ||
| 185 | static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) | ||
| 186 | { | ||
| 187 | while (*root) | ||
| 188 | root = &(*root)->next; | ||
| 189 | *root = sbus; | ||
| 190 | sbus->next = NULL; | ||
| 191 | } | ||
| 192 | |||
| 193 | static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) | ||
| 194 | { | ||
| 195 | while (*root) | ||
| 196 | root = &(*root)->next; | ||
| 197 | *root = sdev; | ||
| 198 | sdev->next = NULL; | ||
| 199 | } | ||
| 200 | |||
| 201 | static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) | ||
| 202 | { | ||
| 203 | dp = dp->child; | ||
| 204 | while (dp) { | ||
| 205 | struct sbus_dev *sdev; | ||
| 206 | |||
| 207 | sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | ||
| 208 | if (sdev) { | ||
| 209 | sdev_insert(sdev, &parent->child); | ||
| 210 | |||
| 211 | sdev->bus = sbus; | ||
| 212 | sdev->parent = parent; | ||
| 213 | sdev->ofdev.dev.archdata.iommu = | ||
| 214 | sbus->ofdev.dev.archdata.iommu; | ||
| 215 | sdev->ofdev.dev.archdata.stc = | ||
| 216 | sbus->ofdev.dev.archdata.stc; | ||
| 217 | |||
| 218 | fill_sbus_device(dp, sdev); | ||
| 219 | |||
| 220 | walk_children(dp, sdev, sbus); | ||
| 221 | } | ||
| 222 | dp = dp->sibling; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | static void __init build_one_sbus(struct device_node *dp, int num_sbus) | ||
| 227 | { | ||
| 228 | struct sbus_bus *sbus; | ||
| 229 | unsigned int sbus_clock; | ||
| 230 | struct device_node *dev_dp; | ||
| 231 | |||
| 232 | sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); | ||
| 233 | if (!sbus) | ||
| 234 | return; | ||
| 235 | |||
| 236 | sbus_insert(sbus, &sbus_root); | ||
| 237 | sbus->prom_node = dp->node; | ||
| 238 | |||
| 239 | sbus_setup_iommu(sbus, dp); | ||
| 240 | |||
| 241 | printk("sbus%d: ", num_sbus); | ||
| 242 | |||
| 243 | sbus_clock = of_getintprop_default(dp, "clock-frequency", | ||
| 244 | (25*1000*1000)); | ||
| 245 | sbus->clock_freq = sbus_clock; | ||
| 246 | |||
| 247 | printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), | ||
| 248 | (int) (((sbus_clock/1000)%1000 != 0) ? | ||
| 249 | (((sbus_clock/1000)%1000) + 1000) : 0)); | ||
| 250 | |||
| 251 | strcpy(sbus->prom_name, dp->name); | ||
| 252 | |||
| 253 | sbus_setup_arch_props(sbus, dp); | ||
| 254 | |||
| 255 | sbus_bus_ranges_init(dp, sbus); | ||
| 256 | |||
| 257 | sbus->ofdev.node = dp; | ||
| 258 | sbus->ofdev.dev.parent = NULL; | ||
| 259 | sbus->ofdev.dev.bus = &sbus_bus_type; | ||
| 260 | dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus); | ||
| 261 | |||
| 262 | if (of_device_register(&sbus->ofdev) != 0) | ||
| 263 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", | ||
| 264 | dev_name(&sbus->ofdev.dev)); | ||
| 265 | |||
| 266 | dev_dp = dp->child; | ||
| 267 | while (dev_dp) { | ||
| 268 | struct sbus_dev *sdev; | ||
| 269 | |||
| 270 | sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | ||
| 271 | if (sdev) { | ||
| 272 | sdev_insert(sdev, &sbus->devices); | ||
| 273 | |||
| 274 | sdev->bus = sbus; | ||
| 275 | sdev->parent = NULL; | ||
| 276 | sdev->ofdev.dev.archdata.iommu = | ||
| 277 | sbus->ofdev.dev.archdata.iommu; | ||
| 278 | sdev->ofdev.dev.archdata.stc = | ||
| 279 | sbus->ofdev.dev.archdata.stc; | ||
| 280 | |||
| 281 | fill_sbus_device(dev_dp, sdev); | ||
| 282 | |||
| 283 | walk_children(dev_dp, sdev, sbus); | ||
| 284 | } | ||
| 285 | dev_dp = dev_dp->sibling; | ||
| 286 | } | ||
| 287 | |||
| 288 | sbus_fixup_all_regs(sbus->devices); | ||
| 289 | |||
| 290 | dvma_init(sbus); | ||
| 291 | } | ||
| 292 | |||
| 293 | static int __init sbus_init(void) | ||
| 294 | { | ||
| 295 | struct device_node *dp; | ||
| 296 | const char *sbus_name = "sbus"; | ||
| 297 | int num_sbus = 0; | ||
| 298 | |||
| 299 | if (sbus_arch_preinit()) | ||
| 300 | return 0; | ||
| 301 | |||
| 302 | if (sparc_cpu_model == sun4d) | ||
| 303 | sbus_name = "sbi"; | ||
| 304 | |||
| 305 | for_each_node_by_name(dp, sbus_name) { | ||
| 306 | build_one_sbus(dp, num_sbus); | ||
| 307 | num_sbus++; | ||
| 308 | |||
| 309 | } | ||
| 310 | |||
| 311 | sbus_arch_postinit(); | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | subsys_initcall(sbus_init); | ||
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index bb43a1388188..28e22acf87ea 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h | |||
| @@ -521,7 +521,8 @@ struct esp { | |||
| 521 | 521 | ||
| 522 | struct completion *eh_reset; | 522 | struct completion *eh_reset; |
| 523 | 523 | ||
| 524 | struct sbus_dma *dma; | 524 | void *dma; |
| 525 | int dmarev; | ||
| 525 | }; | 526 | }; |
| 526 | 527 | ||
| 527 | /* A front-end driver for the ESP chip should do the following in | 528 | /* A front-end driver for the ESP chip should do the following in |
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 905350896725..69d6ad862b60 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver. | 1 | /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 1996, 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1996, 2006, 2008 David S. Miller (davem@davemloft.net) |
| 4 | * | 4 | * |
| 5 | * A lot of this driver was directly stolen from Erik H. Moe's PCI | 5 | * A lot of this driver was directly stolen from Erik H. Moe's PCI |
| 6 | * Qlogic ISP driver. Mucho kudos to him for this code. | 6 | * Qlogic ISP driver. Mucho kudos to him for this code. |
| @@ -25,12 +25,14 @@ | |||
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
| 28 | #include <linux/dma-mapping.h> | ||
| 29 | #include <linux/of.h> | ||
| 30 | #include <linux/of_device.h> | ||
| 28 | 31 | ||
| 29 | #include <asm/byteorder.h> | 32 | #include <asm/byteorder.h> |
| 30 | 33 | ||
| 31 | #include "qlogicpti.h" | 34 | #include "qlogicpti.h" |
| 32 | 35 | ||
| 33 | #include <asm/sbus.h> | ||
| 34 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
| 35 | #include <asm/system.h> | 37 | #include <asm/system.h> |
| 36 | #include <asm/ptrace.h> | 38 | #include <asm/ptrace.h> |
| @@ -157,7 +159,7 @@ static inline void set_sbus_cfg1(struct qlogicpti *qpti) | |||
| 157 | * is a nop and the chip ends up using the smallest burst | 159 | * is a nop and the chip ends up using the smallest burst |
| 158 | * size. -DaveM | 160 | * size. -DaveM |
| 159 | */ | 161 | */ |
| 160 | if (sbus_can_burst64(qpti->sdev) && (bursts & DMA_BURST64)) { | 162 | if (sbus_can_burst64() && (bursts & DMA_BURST64)) { |
| 161 | val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64); | 163 | val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64); |
| 162 | } else | 164 | } else |
| 163 | #endif | 165 | #endif |
| @@ -684,19 +686,19 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) | |||
| 684 | 686 | ||
| 685 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) | 687 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) |
| 686 | { | 688 | { |
| 687 | struct sbus_dev *sdev = qpti->sdev; | 689 | struct of_device *op = qpti->op; |
| 688 | 690 | ||
| 689 | qpti->qregs = sbus_ioremap(&sdev->resource[0], 0, | 691 | qpti->qregs = of_ioremap(&op->resource[0], 0, |
| 690 | sdev->reg_addrs[0].reg_size, | 692 | resource_size(&op->resource[0]), |
| 691 | "PTI Qlogic/ISP"); | 693 | "PTI Qlogic/ISP"); |
| 692 | if (!qpti->qregs) { | 694 | if (!qpti->qregs) { |
| 693 | printk("PTI: Qlogic/ISP registers are unmappable\n"); | 695 | printk("PTI: Qlogic/ISP registers are unmappable\n"); |
| 694 | return -1; | 696 | return -1; |
| 695 | } | 697 | } |
| 696 | if (qpti->is_pti) { | 698 | if (qpti->is_pti) { |
| 697 | qpti->sreg = sbus_ioremap(&sdev->resource[0], (16 * 4096), | 699 | qpti->sreg = of_ioremap(&op->resource[0], (16 * 4096), |
| 698 | sizeof(unsigned char), | 700 | sizeof(unsigned char), |
| 699 | "PTI Qlogic/ISP statreg"); | 701 | "PTI Qlogic/ISP statreg"); |
| 700 | if (!qpti->sreg) { | 702 | if (!qpti->sreg) { |
| 701 | printk("PTI: Qlogic/ISP status register is unmappable\n"); | 703 | printk("PTI: Qlogic/ISP status register is unmappable\n"); |
| 702 | return -1; | 704 | return -1; |
| @@ -707,9 +709,9 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) | |||
| 707 | 709 | ||
| 708 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) | 710 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) |
| 709 | { | 711 | { |
| 710 | struct sbus_dev *sdev = qpti->sdev; | 712 | struct of_device *op = qpti->op; |
| 711 | 713 | ||
| 712 | qpti->qhost->irq = qpti->irq = sdev->irqs[0]; | 714 | qpti->qhost->irq = qpti->irq = op->irqs[0]; |
| 713 | 715 | ||
| 714 | /* We used to try various overly-clever things to | 716 | /* We used to try various overly-clever things to |
| 715 | * reduce the interrupt processing overhead on | 717 | * reduce the interrupt processing overhead on |
| @@ -732,17 +734,19 @@ fail: | |||
| 732 | 734 | ||
| 733 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | 735 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) |
| 734 | { | 736 | { |
| 735 | qpti->scsi_id = prom_getintdefault(qpti->prom_node, | 737 | struct of_device *op = qpti->op; |
| 736 | "initiator-id", | 738 | struct device_node *dp; |
| 737 | -1); | 739 | |
| 740 | dp = op->node; | ||
| 741 | |||
| 742 | qpti->scsi_id = of_getintprop_default(dp, "initiator-id", -1); | ||
| 738 | if (qpti->scsi_id == -1) | 743 | if (qpti->scsi_id == -1) |
| 739 | qpti->scsi_id = prom_getintdefault(qpti->prom_node, | 744 | qpti->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", |
| 740 | "scsi-initiator-id", | 745 | -1); |
| 741 | -1); | ||
| 742 | if (qpti->scsi_id == -1) | 746 | if (qpti->scsi_id == -1) |
| 743 | qpti->scsi_id = | 747 | qpti->scsi_id = |
| 744 | prom_getintdefault(qpti->sdev->bus->prom_node, | 748 | of_getintprop_default(dp->parent, |
| 745 | "scsi-initiator-id", 7); | 749 | "scsi-initiator-id", 7); |
| 746 | qpti->qhost->this_id = qpti->scsi_id; | 750 | qpti->qhost->this_id = qpti->scsi_id; |
| 747 | qpti->qhost->max_sectors = 64; | 751 | qpti->qhost->max_sectors = 64; |
| 748 | 752 | ||
| @@ -751,12 +755,11 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | |||
| 751 | 755 | ||
| 752 | static void qpti_get_bursts(struct qlogicpti *qpti) | 756 | static void qpti_get_bursts(struct qlogicpti *qpti) |
| 753 | { | 757 | { |
| 754 | struct sbus_dev *sdev = qpti->sdev; | 758 | struct of_device *op = qpti->op; |
| 755 | u8 bursts, bmask; | 759 | u8 bursts, bmask; |
| 756 | 760 | ||
| 757 | bursts = prom_getintdefault(qpti->prom_node, "burst-sizes", 0xff); | 761 | bursts = of_getintprop_default(op->node, "burst-sizes", 0xff); |
| 758 | bmask = prom_getintdefault(sdev->bus->prom_node, | 762 | bmask = of_getintprop_default(op->node->parent, "burst-sizes", 0xff); |
| 759 | "burst-sizes", 0xff); | ||
| 760 | if (bmask != 0xff) | 763 | if (bmask != 0xff) |
| 761 | bursts &= bmask; | 764 | bursts &= bmask; |
| 762 | if (bursts == 0xff || | 765 | if (bursts == 0xff || |
| @@ -785,25 +788,25 @@ static void qpti_get_clock(struct qlogicpti *qpti) | |||
| 785 | */ | 788 | */ |
| 786 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) | 789 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) |
| 787 | { | 790 | { |
| 788 | struct sbus_dev *sdev = qpti->sdev; | 791 | struct of_device *op = qpti->op; |
| 789 | 792 | ||
| 790 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 793 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
| 791 | qpti->res_cpu = sbus_alloc_consistent(sdev, | 794 | qpti->res_cpu = dma_alloc_coherent(&op->dev, |
| 792 | QSIZE(RES_QUEUE_LEN), | 795 | QSIZE(RES_QUEUE_LEN), |
| 793 | &qpti->res_dvma); | 796 | &qpti->res_dvma, GFP_ATOMIC); |
| 794 | if (qpti->res_cpu == NULL || | 797 | if (qpti->res_cpu == NULL || |
| 795 | qpti->res_dvma == 0) { | 798 | qpti->res_dvma == 0) { |
| 796 | printk("QPTI: Cannot map response queue.\n"); | 799 | printk("QPTI: Cannot map response queue.\n"); |
| 797 | return -1; | 800 | return -1; |
| 798 | } | 801 | } |
| 799 | 802 | ||
| 800 | qpti->req_cpu = sbus_alloc_consistent(sdev, | 803 | qpti->req_cpu = dma_alloc_coherent(&op->dev, |
| 801 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), | 804 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), |
| 802 | &qpti->req_dvma); | 805 | &qpti->req_dvma, GFP_ATOMIC); |
| 803 | if (qpti->req_cpu == NULL || | 806 | if (qpti->req_cpu == NULL || |
| 804 | qpti->req_dvma == 0) { | 807 | qpti->req_dvma == 0) { |
| 805 | sbus_free_consistent(sdev, QSIZE(RES_QUEUE_LEN), | 808 | dma_free_coherent(&op->dev, QSIZE(RES_QUEUE_LEN), |
| 806 | qpti->res_cpu, qpti->res_dvma); | 809 | qpti->res_cpu, qpti->res_dvma); |
| 807 | printk("QPTI: Cannot map request queue.\n"); | 810 | printk("QPTI: Cannot map request queue.\n"); |
| 808 | return -1; | 811 | return -1; |
| 809 | } | 812 | } |
| @@ -875,8 +878,9 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, | |||
| 875 | int sg_count; | 878 | int sg_count; |
| 876 | 879 | ||
| 877 | sg = scsi_sglist(Cmnd); | 880 | sg = scsi_sglist(Cmnd); |
| 878 | sg_count = sbus_map_sg(qpti->sdev, sg, scsi_sg_count(Cmnd), | 881 | sg_count = dma_map_sg(&qpti->op->dev, sg, |
| 879 | Cmnd->sc_data_direction); | 882 | scsi_sg_count(Cmnd), |
| 883 | Cmnd->sc_data_direction); | ||
| 880 | 884 | ||
| 881 | ds = cmd->dataseg; | 885 | ds = cmd->dataseg; |
| 882 | cmd->segment_cnt = sg_count; | 886 | cmd->segment_cnt = sg_count; |
| @@ -1152,9 +1156,9 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) | |||
| 1152 | Cmnd->result = DID_ERROR << 16; | 1156 | Cmnd->result = DID_ERROR << 16; |
| 1153 | 1157 | ||
| 1154 | if (scsi_bufflen(Cmnd)) | 1158 | if (scsi_bufflen(Cmnd)) |
| 1155 | sbus_unmap_sg(qpti->sdev, | 1159 | dma_unmap_sg(&qpti->op->dev, |
| 1156 | scsi_sglist(Cmnd), scsi_sg_count(Cmnd), | 1160 | scsi_sglist(Cmnd), scsi_sg_count(Cmnd), |
| 1157 | Cmnd->sc_data_direction); | 1161 | Cmnd->sc_data_direction); |
| 1158 | 1162 | ||
| 1159 | qpti->cmd_count[Cmnd->device->id]--; | 1163 | qpti->cmd_count[Cmnd->device->id]--; |
| 1160 | sbus_writew(out_ptr, qpti->qregs + MBOX5); | 1164 | sbus_writew(out_ptr, qpti->qregs + MBOX5); |
| @@ -1268,34 +1272,32 @@ static struct scsi_host_template qpti_template = { | |||
| 1268 | .use_clustering = ENABLE_CLUSTERING, | 1272 | .use_clustering = ENABLE_CLUSTERING, |
| 1269 | }; | 1273 | }; |
| 1270 | 1274 | ||
| 1271 | static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 1275 | static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) |
| 1272 | { | 1276 | { |
| 1273 | static int nqptis; | ||
| 1274 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
| 1275 | struct device_node *dp = dev->node; | ||
| 1276 | struct scsi_host_template *tpnt = match->data; | 1277 | struct scsi_host_template *tpnt = match->data; |
| 1278 | struct device_node *dp = op->node; | ||
| 1277 | struct Scsi_Host *host; | 1279 | struct Scsi_Host *host; |
| 1278 | struct qlogicpti *qpti; | 1280 | struct qlogicpti *qpti; |
| 1281 | static int nqptis; | ||
| 1279 | const char *fcode; | 1282 | const char *fcode; |
| 1280 | 1283 | ||
| 1281 | /* Sometimes Antares cards come up not completely | 1284 | /* Sometimes Antares cards come up not completely |
| 1282 | * setup, and we get a report of a zero IRQ. | 1285 | * setup, and we get a report of a zero IRQ. |
| 1283 | */ | 1286 | */ |
| 1284 | if (sdev->irqs[0] == 0) | 1287 | if (op->irqs[0] == 0) |
| 1285 | return -ENODEV; | 1288 | return -ENODEV; |
| 1286 | 1289 | ||
| 1287 | host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); | 1290 | host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); |
| 1288 | if (!host) | 1291 | if (!host) |
| 1289 | return -ENOMEM; | 1292 | return -ENOMEM; |
| 1290 | 1293 | ||
| 1291 | qpti = (struct qlogicpti *) host->hostdata; | 1294 | qpti = shost_priv(host); |
| 1292 | 1295 | ||
| 1293 | host->max_id = MAX_TARGETS; | 1296 | host->max_id = MAX_TARGETS; |
| 1294 | qpti->qhost = host; | 1297 | qpti->qhost = host; |
| 1295 | qpti->sdev = sdev; | 1298 | qpti->op = op; |
| 1296 | qpti->qpti_id = nqptis; | 1299 | qpti->qpti_id = nqptis; |
| 1297 | qpti->prom_node = sdev->prom_node; | 1300 | strcpy(qpti->prom_name, op->node->name); |
| 1298 | strcpy(qpti->prom_name, sdev->ofdev.node->name); | ||
| 1299 | qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); | 1301 | qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); |
| 1300 | 1302 | ||
| 1301 | if (qpti_map_regs(qpti) < 0) | 1303 | if (qpti_map_regs(qpti) < 0) |
| @@ -1341,12 +1343,12 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi | |||
| 1341 | (qpti->ultra ? "Ultra" : "Fast"), | 1343 | (qpti->ultra ? "Ultra" : "Fast"), |
| 1342 | (qpti->differential ? "differential" : "single ended")); | 1344 | (qpti->differential ? "differential" : "single ended")); |
| 1343 | 1345 | ||
| 1344 | if (scsi_add_host(host, &dev->dev)) { | 1346 | if (scsi_add_host(host, &op->dev)) { |
| 1345 | printk("qlogicpti%d: Failed scsi_add_host\n", qpti->qpti_id); | 1347 | printk("qlogicpti%d: Failed scsi_add_host\n", qpti->qpti_id); |
| 1346 | goto fail_unmap_queues; | 1348 | goto fail_unmap_queues; |
| 1347 | } | 1349 | } |
| 1348 | 1350 | ||
| 1349 | dev_set_drvdata(&sdev->ofdev.dev, qpti); | 1351 | dev_set_drvdata(&op->dev, qpti); |
| 1350 | 1352 | ||
| 1351 | qpti_chain_add(qpti); | 1353 | qpti_chain_add(qpti); |
| 1352 | 1354 | ||
| @@ -1357,19 +1359,20 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi | |||
| 1357 | 1359 | ||
| 1358 | fail_unmap_queues: | 1360 | fail_unmap_queues: |
| 1359 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 1361 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
| 1360 | sbus_free_consistent(qpti->sdev, | 1362 | dma_free_coherent(&op->dev, |
| 1361 | QSIZE(RES_QUEUE_LEN), | 1363 | QSIZE(RES_QUEUE_LEN), |
| 1362 | qpti->res_cpu, qpti->res_dvma); | 1364 | qpti->res_cpu, qpti->res_dvma); |
| 1363 | sbus_free_consistent(qpti->sdev, | 1365 | dma_free_coherent(&op->dev, |
| 1364 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), | 1366 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), |
| 1365 | qpti->req_cpu, qpti->req_dvma); | 1367 | qpti->req_cpu, qpti->req_dvma); |
| 1366 | #undef QSIZE | 1368 | #undef QSIZE |
| 1367 | 1369 | ||
| 1368 | fail_unmap_regs: | 1370 | fail_unmap_regs: |
| 1369 | sbus_iounmap(qpti->qregs, | 1371 | of_iounmap(&op->resource[0], qpti->qregs, |
| 1370 | qpti->sdev->reg_addrs[0].reg_size); | 1372 | resource_size(&op->resource[0])); |
| 1371 | if (qpti->is_pti) | 1373 | if (qpti->is_pti) |
| 1372 | sbus_iounmap(qpti->sreg, sizeof(unsigned char)); | 1374 | of_iounmap(&op->resource[0], qpti->sreg, |
| 1375 | sizeof(unsigned char)); | ||
| 1373 | 1376 | ||
| 1374 | fail_free_irq: | 1377 | fail_free_irq: |
| 1375 | free_irq(qpti->irq, qpti); | 1378 | free_irq(qpti->irq, qpti); |
| @@ -1380,9 +1383,9 @@ fail_unlink: | |||
| 1380 | return -ENODEV; | 1383 | return -ENODEV; |
| 1381 | } | 1384 | } |
| 1382 | 1385 | ||
| 1383 | static int __devexit qpti_sbus_remove(struct of_device *dev) | 1386 | static int __devexit qpti_sbus_remove(struct of_device *op) |
| 1384 | { | 1387 | { |
| 1385 | struct qlogicpti *qpti = dev_get_drvdata(&dev->dev); | 1388 | struct qlogicpti *qpti = dev_get_drvdata(&op->dev); |
| 1386 | 1389 | ||
| 1387 | qpti_chain_del(qpti); | 1390 | qpti_chain_del(qpti); |
| 1388 | 1391 | ||
| @@ -1395,24 +1398,25 @@ static int __devexit qpti_sbus_remove(struct of_device *dev) | |||
| 1395 | free_irq(qpti->irq, qpti); | 1398 | free_irq(qpti->irq, qpti); |
| 1396 | 1399 | ||
| 1397 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 1400 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
| 1398 | sbus_free_consistent(qpti->sdev, | 1401 | dma_free_coherent(&op->dev, |
| 1399 | QSIZE(RES_QUEUE_LEN), | 1402 | QSIZE(RES_QUEUE_LEN), |
| 1400 | qpti->res_cpu, qpti->res_dvma); | 1403 | qpti->res_cpu, qpti->res_dvma); |
| 1401 | sbus_free_consistent(qpti->sdev, | 1404 | dma_free_coherent(&op->dev, |
| 1402 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), | 1405 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), |
| 1403 | qpti->req_cpu, qpti->req_dvma); | 1406 | qpti->req_cpu, qpti->req_dvma); |
| 1404 | #undef QSIZE | 1407 | #undef QSIZE |
| 1405 | 1408 | ||
| 1406 | sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); | 1409 | of_iounmap(&op->resource[0], qpti->qregs, |
| 1410 | resource_size(&op->resource[0])); | ||
| 1407 | if (qpti->is_pti) | 1411 | if (qpti->is_pti) |
| 1408 | sbus_iounmap(qpti->sreg, sizeof(unsigned char)); | 1412 | of_iounmap(&op->resource[0], qpti->sreg, sizeof(unsigned char)); |
| 1409 | 1413 | ||
| 1410 | scsi_host_put(qpti->qhost); | 1414 | scsi_host_put(qpti->qhost); |
| 1411 | 1415 | ||
| 1412 | return 0; | 1416 | return 0; |
| 1413 | } | 1417 | } |
| 1414 | 1418 | ||
| 1415 | static struct of_device_id qpti_match[] = { | 1419 | static const struct of_device_id qpti_match[] = { |
| 1416 | { | 1420 | { |
| 1417 | .name = "ptisp", | 1421 | .name = "ptisp", |
| 1418 | .data = &qpti_template, | 1422 | .data = &qpti_template, |
| @@ -1442,7 +1446,7 @@ static struct of_platform_driver qpti_sbus_driver = { | |||
| 1442 | 1446 | ||
| 1443 | static int __init qpti_init(void) | 1447 | static int __init qpti_init(void) |
| 1444 | { | 1448 | { |
| 1445 | return of_register_driver(&qpti_sbus_driver, &sbus_bus_type); | 1449 | return of_register_driver(&qpti_sbus_driver, &of_bus_type); |
| 1446 | } | 1450 | } |
| 1447 | 1451 | ||
| 1448 | static void __exit qpti_exit(void) | 1452 | static void __exit qpti_exit(void) |
| @@ -1453,7 +1457,7 @@ static void __exit qpti_exit(void) | |||
| 1453 | MODULE_DESCRIPTION("QlogicISP SBUS driver"); | 1457 | MODULE_DESCRIPTION("QlogicISP SBUS driver"); |
| 1454 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | 1458 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); |
| 1455 | MODULE_LICENSE("GPL"); | 1459 | MODULE_LICENSE("GPL"); |
| 1456 | MODULE_VERSION("2.0"); | 1460 | MODULE_VERSION("2.1"); |
| 1457 | 1461 | ||
| 1458 | module_init(qpti_init); | 1462 | module_init(qpti_init); |
| 1459 | module_exit(qpti_exit); | 1463 | module_exit(qpti_exit); |
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index ef6da2df584b..9c053bbaa877 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h | |||
| @@ -342,7 +342,7 @@ struct qlogicpti { | |||
| 342 | u_int req_in_ptr; /* index of next request slot */ | 342 | u_int req_in_ptr; /* index of next request slot */ |
| 343 | u_int res_out_ptr; /* index of next result slot */ | 343 | u_int res_out_ptr; /* index of next result slot */ |
| 344 | long send_marker; /* must we send a marker? */ | 344 | long send_marker; /* must we send a marker? */ |
| 345 | struct sbus_dev *sdev; | 345 | struct of_device *op; |
| 346 | unsigned long __pad; | 346 | unsigned long __pad; |
| 347 | 347 | ||
| 348 | int cmd_count[MAX_TARGETS]; | 348 | int cmd_count[MAX_TARGETS]; |
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index f9cf70151366..3d73aad4bc82 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* sun_esp.c: ESP front-end for Sparc SBUS systems. | 1 | /* sun_esp.c: ESP front-end for Sparc SBUS systems. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net) |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| @@ -9,60 +9,70 @@ | |||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/dma-mapping.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/of_device.h> | ||
| 12 | 15 | ||
| 13 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
| 14 | #include <asm/io.h> | 17 | #include <asm/io.h> |
| 15 | #include <asm/dma.h> | 18 | #include <asm/dma.h> |
| 16 | 19 | ||
| 17 | #include <asm/sbus.h> | ||
| 18 | |||
| 19 | #include <scsi/scsi_host.h> | 20 | #include <scsi/scsi_host.h> |
| 20 | 21 | ||
| 21 | #include "esp_scsi.h" | 22 | #include "esp_scsi.h" |
| 22 | 23 | ||
| 23 | #define DRV_MODULE_NAME "sun_esp" | 24 | #define DRV_MODULE_NAME "sun_esp" |
| 24 | #define PFX DRV_MODULE_NAME ": " | 25 | #define PFX DRV_MODULE_NAME ": " |
| 25 | #define DRV_VERSION "1.000" | 26 | #define DRV_VERSION "1.100" |
| 26 | #define DRV_MODULE_RELDATE "April 19, 2007" | 27 | #define DRV_MODULE_RELDATE "August 27, 2008" |
| 27 | 28 | ||
| 28 | #define dma_read32(REG) \ | 29 | #define dma_read32(REG) \ |
| 29 | sbus_readl(esp->dma_regs + (REG)) | 30 | sbus_readl(esp->dma_regs + (REG)) |
| 30 | #define dma_write32(VAL, REG) \ | 31 | #define dma_write32(VAL, REG) \ |
| 31 | sbus_writel((VAL), esp->dma_regs + (REG)) | 32 | sbus_writel((VAL), esp->dma_regs + (REG)) |
| 32 | 33 | ||
| 33 | static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sdev) | 34 | /* DVMA chip revisions */ |
| 34 | { | 35 | enum dvma_rev { |
| 35 | struct sbus_dev *sdev = esp->dev; | 36 | dvmarev0, |
| 36 | struct sbus_dma *dma; | 37 | dvmaesc1, |
| 38 | dvmarev1, | ||
| 39 | dvmarev2, | ||
| 40 | dvmarev3, | ||
| 41 | dvmarevplus, | ||
| 42 | dvmahme | ||
| 43 | }; | ||
| 37 | 44 | ||
| 38 | if (dma_sdev != NULL) { | 45 | static int __devinit esp_sbus_setup_dma(struct esp *esp, |
| 39 | for_each_dvma(dma) { | 46 | struct of_device *dma_of) |
| 40 | if (dma->sdev == dma_sdev) | 47 | { |
| 41 | break; | 48 | esp->dma = dma_of; |
| 42 | } | ||
| 43 | } else { | ||
| 44 | for_each_dvma(dma) { | ||
| 45 | if (dma->sdev == NULL) | ||
| 46 | break; | ||
| 47 | 49 | ||
| 48 | /* If bus + slot are the same and it has the | 50 | esp->dma_regs = of_ioremap(&dma_of->resource[0], 0, |
| 49 | * correct OBP name, it's ours. | 51 | resource_size(&dma_of->resource[0]), |
| 50 | */ | 52 | "espdma"); |
| 51 | if (sdev->bus == dma->sdev->bus && | 53 | if (!esp->dma_regs) |
| 52 | sdev->slot == dma->sdev->slot && | 54 | return -ENOMEM; |
| 53 | (!strcmp(dma->sdev->prom_name, "dma") || | ||
| 54 | !strcmp(dma->sdev->prom_name, "espdma"))) | ||
| 55 | break; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | 55 | ||
| 59 | if (dma == NULL) { | 56 | switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) { |
| 60 | printk(KERN_ERR PFX "[%s] Cannot find dma.\n", | 57 | case DMA_VERS0: |
| 61 | sdev->ofdev.node->full_name); | 58 | esp->dmarev = dvmarev0; |
| 62 | return -ENODEV; | 59 | break; |
| 60 | case DMA_ESCV1: | ||
| 61 | esp->dmarev = dvmaesc1; | ||
| 62 | break; | ||
| 63 | case DMA_VERS1: | ||
| 64 | esp->dmarev = dvmarev1; | ||
| 65 | break; | ||
| 66 | case DMA_VERS2: | ||
| 67 | esp->dmarev = dvmarev2; | ||
| 68 | break; | ||
| 69 | case DMA_VERHME: | ||
| 70 | esp->dmarev = dvmahme; | ||
| 71 | break; | ||
| 72 | case DMA_VERSPLUS: | ||
| 73 | esp->dmarev = dvmarevplus; | ||
| 74 | break; | ||
| 63 | } | 75 | } |
| 64 | esp->dma = dma; | ||
| 65 | esp->dma_regs = dma->regs; | ||
| 66 | 76 | ||
| 67 | return 0; | 77 | return 0; |
| 68 | 78 | ||
| @@ -70,18 +80,18 @@ static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sde | |||
| 70 | 80 | ||
| 71 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | 81 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) |
| 72 | { | 82 | { |
| 73 | struct sbus_dev *sdev = esp->dev; | 83 | struct of_device *op = esp->dev; |
| 74 | struct resource *res; | 84 | struct resource *res; |
| 75 | 85 | ||
| 76 | /* On HME, two reg sets exist, first is DVMA, | 86 | /* On HME, two reg sets exist, first is DVMA, |
| 77 | * second is ESP registers. | 87 | * second is ESP registers. |
| 78 | */ | 88 | */ |
| 79 | if (hme) | 89 | if (hme) |
| 80 | res = &sdev->resource[1]; | 90 | res = &op->resource[1]; |
| 81 | else | 91 | else |
| 82 | res = &sdev->resource[0]; | 92 | res = &op->resource[0]; |
| 83 | 93 | ||
| 84 | esp->regs = sbus_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP"); | 94 | esp->regs = of_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP"); |
| 85 | if (!esp->regs) | 95 | if (!esp->regs) |
| 86 | return -ENOMEM; | 96 | return -ENOMEM; |
| 87 | 97 | ||
| @@ -90,10 +100,11 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | |||
| 90 | 100 | ||
| 91 | static int __devinit esp_sbus_map_command_block(struct esp *esp) | 101 | static int __devinit esp_sbus_map_command_block(struct esp *esp) |
| 92 | { | 102 | { |
| 93 | struct sbus_dev *sdev = esp->dev; | 103 | struct of_device *op = esp->dev; |
| 94 | 104 | ||
| 95 | esp->command_block = sbus_alloc_consistent(sdev, 16, | 105 | esp->command_block = dma_alloc_coherent(&op->dev, 16, |
| 96 | &esp->command_block_dma); | 106 | &esp->command_block_dma, |
| 107 | GFP_ATOMIC); | ||
| 97 | if (!esp->command_block) | 108 | if (!esp->command_block) |
| 98 | return -ENOMEM; | 109 | return -ENOMEM; |
| 99 | return 0; | 110 | return 0; |
| @@ -102,17 +113,18 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) | |||
| 102 | static int __devinit esp_sbus_register_irq(struct esp *esp) | 113 | static int __devinit esp_sbus_register_irq(struct esp *esp) |
| 103 | { | 114 | { |
| 104 | struct Scsi_Host *host = esp->host; | 115 | struct Scsi_Host *host = esp->host; |
| 105 | struct sbus_dev *sdev = esp->dev; | 116 | struct of_device *op = esp->dev; |
| 106 | 117 | ||
| 107 | host->irq = sdev->irqs[0]; | 118 | host->irq = op->irqs[0]; |
| 108 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); | 119 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); |
| 109 | } | 120 | } |
| 110 | 121 | ||
| 111 | static void __devinit esp_get_scsi_id(struct esp *esp) | 122 | static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) |
| 112 | { | 123 | { |
| 113 | struct sbus_dev *sdev = esp->dev; | 124 | struct of_device *op = esp->dev; |
| 114 | struct device_node *dp = sdev->ofdev.node; | 125 | struct device_node *dp; |
| 115 | 126 | ||
| 127 | dp = op->node; | ||
| 116 | esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff); | 128 | esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff); |
| 117 | if (esp->scsi_id != 0xff) | 129 | if (esp->scsi_id != 0xff) |
| 118 | goto done; | 130 | goto done; |
| @@ -121,13 +133,7 @@ static void __devinit esp_get_scsi_id(struct esp *esp) | |||
| 121 | if (esp->scsi_id != 0xff) | 133 | if (esp->scsi_id != 0xff) |
| 122 | goto done; | 134 | goto done; |
| 123 | 135 | ||
| 124 | if (!sdev->bus) { | 136 | esp->scsi_id = of_getintprop_default(espdma->node, |
| 125 | /* SUN4 */ | ||
| 126 | esp->scsi_id = 7; | ||
| 127 | goto done; | ||
| 128 | } | ||
| 129 | |||
| 130 | esp->scsi_id = of_getintprop_default(sdev->bus->ofdev.node, | ||
| 131 | "scsi-initiator-id", 7); | 137 | "scsi-initiator-id", 7); |
| 132 | 138 | ||
| 133 | done: | 139 | done: |
| @@ -137,9 +143,10 @@ done: | |||
| 137 | 143 | ||
| 138 | static void __devinit esp_get_differential(struct esp *esp) | 144 | static void __devinit esp_get_differential(struct esp *esp) |
| 139 | { | 145 | { |
| 140 | struct sbus_dev *sdev = esp->dev; | 146 | struct of_device *op = esp->dev; |
| 141 | struct device_node *dp = sdev->ofdev.node; | 147 | struct device_node *dp; |
| 142 | 148 | ||
| 149 | dp = op->node; | ||
| 143 | if (of_find_property(dp, "differential", NULL)) | 150 | if (of_find_property(dp, "differential", NULL)) |
| 144 | esp->flags |= ESP_FLAG_DIFFERENTIAL; | 151 | esp->flags |= ESP_FLAG_DIFFERENTIAL; |
| 145 | else | 152 | else |
| @@ -148,43 +155,36 @@ static void __devinit esp_get_differential(struct esp *esp) | |||
| 148 | 155 | ||
| 149 | static void __devinit esp_get_clock_params(struct esp *esp) | 156 | static void __devinit esp_get_clock_params(struct esp *esp) |
| 150 | { | 157 | { |
| 151 | struct sbus_dev *sdev = esp->dev; | 158 | struct of_device *op = esp->dev; |
| 152 | struct device_node *dp = sdev->ofdev.node; | 159 | struct device_node *bus_dp, *dp; |
| 153 | struct device_node *bus_dp; | ||
| 154 | int fmhz; | 160 | int fmhz; |
| 155 | 161 | ||
| 156 | bus_dp = NULL; | 162 | dp = op->node; |
| 157 | if (sdev != NULL && sdev->bus != NULL) | 163 | bus_dp = dp->parent; |
| 158 | bus_dp = sdev->bus->ofdev.node; | ||
| 159 | 164 | ||
| 160 | fmhz = of_getintprop_default(dp, "clock-frequency", 0); | 165 | fmhz = of_getintprop_default(dp, "clock-frequency", 0); |
| 161 | if (fmhz == 0) | 166 | if (fmhz == 0) |
| 162 | fmhz = (!bus_dp) ? 0 : | 167 | fmhz = of_getintprop_default(bus_dp, "clock-frequency", 0); |
| 163 | of_getintprop_default(bus_dp, "clock-frequency", 0); | ||
| 164 | 168 | ||
| 165 | esp->cfreq = fmhz; | 169 | esp->cfreq = fmhz; |
| 166 | } | 170 | } |
| 167 | 171 | ||
| 168 | static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) | 172 | static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) |
| 169 | { | 173 | { |
| 170 | struct sbus_dev *sdev = esp->dev; | 174 | struct device_node *dma_dp = dma_of->node; |
| 171 | struct device_node *dp = sdev->ofdev.node; | 175 | struct of_device *op = esp->dev; |
| 172 | u8 bursts; | 176 | struct device_node *dp; |
| 177 | u8 bursts, val; | ||
| 173 | 178 | ||
| 179 | dp = op->node; | ||
| 174 | bursts = of_getintprop_default(dp, "burst-sizes", 0xff); | 180 | bursts = of_getintprop_default(dp, "burst-sizes", 0xff); |
| 175 | if (dma) { | 181 | val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); |
| 176 | struct device_node *dma_dp = dma->ofdev.node; | 182 | if (val != 0xff) |
| 177 | u8 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); | 183 | bursts &= val; |
| 178 | if (val != 0xff) | ||
| 179 | bursts &= val; | ||
| 180 | } | ||
| 181 | 184 | ||
| 182 | if (sdev->bus) { | 185 | val = of_getintprop_default(dma_dp->parent, "burst-sizes", 0xff); |
| 183 | u8 val = of_getintprop_default(sdev->bus->ofdev.node, | 186 | if (val != 0xff) |
| 184 | "burst-sizes", 0xff); | 187 | bursts &= val; |
| 185 | if (val != 0xff) | ||
| 186 | bursts &= val; | ||
| 187 | } | ||
| 188 | 188 | ||
| 189 | if (bursts == 0xff || | 189 | if (bursts == 0xff || |
| 190 | (bursts & DMA_BURST16) == 0 || | 190 | (bursts & DMA_BURST16) == 0 || |
| @@ -194,9 +194,9 @@ static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) | |||
| 194 | esp->bursts = bursts; | 194 | esp->bursts = bursts; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static void __devinit esp_sbus_get_props(struct esp *esp, struct sbus_dev *espdma) | 197 | static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) |
| 198 | { | 198 | { |
| 199 | esp_get_scsi_id(esp); | 199 | esp_get_scsi_id(esp, espdma); |
| 200 | esp_get_differential(esp); | 200 | esp_get_differential(esp); |
| 201 | esp_get_clock_params(esp); | 201 | esp_get_clock_params(esp); |
| 202 | esp_get_bursts(esp, espdma); | 202 | esp_get_bursts(esp, espdma); |
| @@ -215,25 +215,33 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) | |||
| 215 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, | 215 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, |
| 216 | size_t sz, int dir) | 216 | size_t sz, int dir) |
| 217 | { | 217 | { |
| 218 | return sbus_map_single(esp->dev, buf, sz, dir); | 218 | struct of_device *op = esp->dev; |
| 219 | |||
| 220 | return dma_map_single(&op->dev, buf, sz, dir); | ||
| 219 | } | 221 | } |
| 220 | 222 | ||
| 221 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, | 223 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, |
| 222 | int num_sg, int dir) | 224 | int num_sg, int dir) |
| 223 | { | 225 | { |
| 224 | return sbus_map_sg(esp->dev, sg, num_sg, dir); | 226 | struct of_device *op = esp->dev; |
| 227 | |||
| 228 | return dma_map_sg(&op->dev, sg, num_sg, dir); | ||
| 225 | } | 229 | } |
| 226 | 230 | ||
| 227 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, | 231 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, |
| 228 | size_t sz, int dir) | 232 | size_t sz, int dir) |
| 229 | { | 233 | { |
| 230 | sbus_unmap_single(esp->dev, addr, sz, dir); | 234 | struct of_device *op = esp->dev; |
| 235 | |||
| 236 | dma_unmap_single(&op->dev, addr, sz, dir); | ||
| 231 | } | 237 | } |
| 232 | 238 | ||
| 233 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, | 239 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, |
| 234 | int num_sg, int dir) | 240 | int num_sg, int dir) |
| 235 | { | 241 | { |
| 236 | sbus_unmap_sg(esp->dev, sg, num_sg, dir); | 242 | struct of_device *op = esp->dev; |
| 243 | |||
| 244 | dma_unmap_sg(&op->dev, sg, num_sg, dir); | ||
| 237 | } | 245 | } |
| 238 | 246 | ||
| 239 | static int sbus_esp_irq_pending(struct esp *esp) | 247 | static int sbus_esp_irq_pending(struct esp *esp) |
| @@ -247,24 +255,26 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
| 247 | { | 255 | { |
| 248 | int can_do_burst16, can_do_burst32, can_do_burst64; | 256 | int can_do_burst16, can_do_burst32, can_do_burst64; |
| 249 | int can_do_sbus64, lim; | 257 | int can_do_sbus64, lim; |
| 258 | struct of_device *op; | ||
| 250 | u32 val; | 259 | u32 val; |
| 251 | 260 | ||
| 252 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; | 261 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; |
| 253 | can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; | 262 | can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; |
| 254 | can_do_burst64 = 0; | 263 | can_do_burst64 = 0; |
| 255 | can_do_sbus64 = 0; | 264 | can_do_sbus64 = 0; |
| 256 | if (sbus_can_dma_64bit(esp->dev)) | 265 | op = esp->dev; |
| 266 | if (sbus_can_dma_64bit()) | ||
| 257 | can_do_sbus64 = 1; | 267 | can_do_sbus64 = 1; |
| 258 | if (sbus_can_burst64(esp->sdev)) | 268 | if (sbus_can_burst64()) |
| 259 | can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; | 269 | can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; |
| 260 | 270 | ||
| 261 | /* Put the DVMA into a known state. */ | 271 | /* Put the DVMA into a known state. */ |
| 262 | if (esp->dma->revision != dvmahme) { | 272 | if (esp->dmarev != dvmahme) { |
| 263 | val = dma_read32(DMA_CSR); | 273 | val = dma_read32(DMA_CSR); |
| 264 | dma_write32(val | DMA_RST_SCSI, DMA_CSR); | 274 | dma_write32(val | DMA_RST_SCSI, DMA_CSR); |
| 265 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); | 275 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); |
| 266 | } | 276 | } |
| 267 | switch (esp->dma->revision) { | 277 | switch (esp->dmarev) { |
| 268 | case dvmahme: | 278 | case dvmahme: |
| 269 | dma_write32(DMA_RESET_FAS366, DMA_CSR); | 279 | dma_write32(DMA_RESET_FAS366, DMA_CSR); |
| 270 | dma_write32(DMA_RST_SCSI, DMA_CSR); | 280 | dma_write32(DMA_RST_SCSI, DMA_CSR); |
| @@ -282,7 +292,7 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
| 282 | 292 | ||
| 283 | if (can_do_sbus64) { | 293 | if (can_do_sbus64) { |
| 284 | esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; | 294 | esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; |
| 285 | sbus_set_sbus64(esp->dev, esp->bursts); | 295 | sbus_set_sbus64(&op->dev, esp->bursts); |
| 286 | } | 296 | } |
| 287 | 297 | ||
| 288 | lim = 1000; | 298 | lim = 1000; |
| @@ -346,14 +356,14 @@ static void sbus_esp_dma_drain(struct esp *esp) | |||
| 346 | u32 csr; | 356 | u32 csr; |
| 347 | int lim; | 357 | int lim; |
| 348 | 358 | ||
| 349 | if (esp->dma->revision == dvmahme) | 359 | if (esp->dmarev == dvmahme) |
| 350 | return; | 360 | return; |
| 351 | 361 | ||
| 352 | csr = dma_read32(DMA_CSR); | 362 | csr = dma_read32(DMA_CSR); |
| 353 | if (!(csr & DMA_FIFO_ISDRAIN)) | 363 | if (!(csr & DMA_FIFO_ISDRAIN)) |
| 354 | return; | 364 | return; |
| 355 | 365 | ||
| 356 | if (esp->dma->revision != dvmarev3 && esp->dma->revision != dvmaesc1) | 366 | if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1) |
| 357 | dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); | 367 | dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); |
| 358 | 368 | ||
| 359 | lim = 1000; | 369 | lim = 1000; |
| @@ -369,7 +379,7 @@ static void sbus_esp_dma_drain(struct esp *esp) | |||
| 369 | 379 | ||
| 370 | static void sbus_esp_dma_invalidate(struct esp *esp) | 380 | static void sbus_esp_dma_invalidate(struct esp *esp) |
| 371 | { | 381 | { |
| 372 | if (esp->dma->revision == dvmahme) { | 382 | if (esp->dmarev == dvmahme) { |
| 373 | dma_write32(DMA_RST_SCSI, DMA_CSR); | 383 | dma_write32(DMA_RST_SCSI, DMA_CSR); |
| 374 | 384 | ||
| 375 | esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | | 385 | esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | |
| @@ -440,7 +450,7 @@ static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
| 440 | else | 450 | else |
| 441 | csr &= ~DMA_ST_WRITE; | 451 | csr &= ~DMA_ST_WRITE; |
| 442 | dma_write32(csr, DMA_CSR); | 452 | dma_write32(csr, DMA_CSR); |
| 443 | if (esp->dma->revision == dvmaesc1) { | 453 | if (esp->dmarev == dvmaesc1) { |
| 444 | u32 end = PAGE_ALIGN(addr + dma_count + 16U); | 454 | u32 end = PAGE_ALIGN(addr + dma_count + 16U); |
| 445 | dma_write32(end - addr, DMA_COUNT); | 455 | dma_write32(end - addr, DMA_COUNT); |
| 446 | } | 456 | } |
| @@ -476,10 +486,8 @@ static const struct esp_driver_ops sbus_esp_ops = { | |||
| 476 | .dma_error = sbus_esp_dma_error, | 486 | .dma_error = sbus_esp_dma_error, |
| 477 | }; | 487 | }; |
| 478 | 488 | ||
| 479 | static int __devinit esp_sbus_probe_one(struct device *dev, | 489 | static int __devinit esp_sbus_probe_one(struct of_device *op, |
| 480 | struct sbus_dev *esp_dev, | 490 | struct of_device *espdma, |
| 481 | struct sbus_dev *espdma, | ||
| 482 | struct sbus_bus *sbus, | ||
| 483 | int hme) | 491 | int hme) |
| 484 | { | 492 | { |
| 485 | struct scsi_host_template *tpnt = &scsi_esp_template; | 493 | struct scsi_host_template *tpnt = &scsi_esp_template; |
| @@ -497,13 +505,13 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
| 497 | esp = shost_priv(host); | 505 | esp = shost_priv(host); |
| 498 | 506 | ||
| 499 | esp->host = host; | 507 | esp->host = host; |
| 500 | esp->dev = esp_dev; | 508 | esp->dev = op; |
| 501 | esp->ops = &sbus_esp_ops; | 509 | esp->ops = &sbus_esp_ops; |
| 502 | 510 | ||
| 503 | if (hme) | 511 | if (hme) |
| 504 | esp->flags |= ESP_FLAG_WIDE_CAPABLE; | 512 | esp->flags |= ESP_FLAG_WIDE_CAPABLE; |
| 505 | 513 | ||
| 506 | err = esp_sbus_find_dma(esp, espdma); | 514 | err = esp_sbus_setup_dma(esp, espdma); |
| 507 | if (err < 0) | 515 | if (err < 0) |
| 508 | goto fail_unlink; | 516 | goto fail_unlink; |
| 509 | 517 | ||
| @@ -525,15 +533,15 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
| 525 | * come up with the reset bit set, so make sure that | 533 | * come up with the reset bit set, so make sure that |
| 526 | * is clear first. | 534 | * is clear first. |
| 527 | */ | 535 | */ |
| 528 | if (esp->dma->revision == dvmaesc1) { | 536 | if (esp->dmarev == dvmaesc1) { |
| 529 | u32 val = dma_read32(DMA_CSR); | 537 | u32 val = dma_read32(DMA_CSR); |
| 530 | 538 | ||
| 531 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); | 539 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); |
| 532 | } | 540 | } |
| 533 | 541 | ||
| 534 | dev_set_drvdata(&esp_dev->ofdev.dev, esp); | 542 | dev_set_drvdata(&op->dev, esp); |
| 535 | 543 | ||
| 536 | err = scsi_esp_register(esp, dev); | 544 | err = scsi_esp_register(esp, &op->dev); |
| 537 | if (err) | 545 | if (err) |
| 538 | goto fail_free_irq; | 546 | goto fail_free_irq; |
| 539 | 547 | ||
| @@ -542,41 +550,46 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
| 542 | fail_free_irq: | 550 | fail_free_irq: |
| 543 | free_irq(host->irq, esp); | 551 | free_irq(host->irq, esp); |
| 544 | fail_unmap_command_block: | 552 | fail_unmap_command_block: |
| 545 | sbus_free_consistent(esp->dev, 16, | 553 | dma_free_coherent(&op->dev, 16, |
| 546 | esp->command_block, | 554 | esp->command_block, |
| 547 | esp->command_block_dma); | 555 | esp->command_block_dma); |
| 548 | fail_unmap_regs: | 556 | fail_unmap_regs: |
| 549 | sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); | 557 | of_iounmap(&op->resource[(hme ? 1 : 0)], esp->regs, SBUS_ESP_REG_SIZE); |
| 550 | fail_unlink: | 558 | fail_unlink: |
| 551 | scsi_host_put(host); | 559 | scsi_host_put(host); |
| 552 | fail: | 560 | fail: |
| 553 | return err; | 561 | return err; |
| 554 | } | 562 | } |
| 555 | 563 | ||
| 556 | static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 564 | static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) |
| 557 | { | 565 | { |
| 558 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 566 | struct device_node *dma_node = NULL; |
| 559 | struct device_node *dp = dev->node; | 567 | struct device_node *dp = op->node; |
| 560 | struct sbus_dev *dma_sdev = NULL; | 568 | struct of_device *dma_of = NULL; |
| 561 | int hme = 0; | 569 | int hme = 0; |
| 562 | 570 | ||
| 563 | if (dp->parent && | 571 | if (dp->parent && |
| 564 | (!strcmp(dp->parent->name, "espdma") || | 572 | (!strcmp(dp->parent->name, "espdma") || |
| 565 | !strcmp(dp->parent->name, "dma"))) | 573 | !strcmp(dp->parent->name, "dma"))) |
| 566 | dma_sdev = sdev->parent; | 574 | dma_node = dp->parent; |
| 567 | else if (!strcmp(dp->name, "SUNW,fas")) { | 575 | else if (!strcmp(dp->name, "SUNW,fas")) { |
| 568 | dma_sdev = sdev; | 576 | dma_node = op->node; |
| 569 | hme = 1; | 577 | hme = 1; |
| 570 | } | 578 | } |
| 579 | if (dma_node) | ||
| 580 | dma_of = of_find_device_by_node(dma_node); | ||
| 581 | if (!dma_of) | ||
| 582 | return -ENODEV; | ||
| 571 | 583 | ||
| 572 | return esp_sbus_probe_one(&dev->dev, sdev, dma_sdev, | 584 | return esp_sbus_probe_one(op, dma_of, hme); |
| 573 | sdev->bus, hme); | ||
| 574 | } | 585 | } |
| 575 | 586 | ||
| 576 | static int __devexit esp_sbus_remove(struct of_device *dev) | 587 | static int __devexit esp_sbus_remove(struct of_device *op) |
| 577 | { | 588 | { |
| 578 | struct esp *esp = dev_get_drvdata(&dev->dev); | 589 | struct esp *esp = dev_get_drvdata(&op->dev); |
| 590 | struct of_device *dma_of = esp->dma; | ||
| 579 | unsigned int irq = esp->host->irq; | 591 | unsigned int irq = esp->host->irq; |
| 592 | bool is_hme; | ||
| 580 | u32 val; | 593 | u32 val; |
| 581 | 594 | ||
| 582 | scsi_esp_unregister(esp); | 595 | scsi_esp_unregister(esp); |
| @@ -586,17 +599,25 @@ static int __devexit esp_sbus_remove(struct of_device *dev) | |||
| 586 | dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); | 599 | dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); |
| 587 | 600 | ||
| 588 | free_irq(irq, esp); | 601 | free_irq(irq, esp); |
| 589 | sbus_free_consistent(esp->dev, 16, | 602 | |
| 590 | esp->command_block, | 603 | is_hme = (esp->dmarev == dvmahme); |
| 591 | esp->command_block_dma); | 604 | |
| 592 | sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); | 605 | dma_free_coherent(&op->dev, 16, |
| 606 | esp->command_block, | ||
| 607 | esp->command_block_dma); | ||
| 608 | of_iounmap(&op->resource[(is_hme ? 1 : 0)], esp->regs, | ||
| 609 | SBUS_ESP_REG_SIZE); | ||
| 610 | of_iounmap(&dma_of->resource[0], esp->dma_regs, | ||
| 611 | resource_size(&dma_of->resource[0])); | ||
| 593 | 612 | ||
| 594 | scsi_host_put(esp->host); | 613 | scsi_host_put(esp->host); |
| 595 | 614 | ||
| 615 | dev_set_drvdata(&op->dev, NULL); | ||
| 616 | |||
| 596 | return 0; | 617 | return 0; |
| 597 | } | 618 | } |
| 598 | 619 | ||
| 599 | static struct of_device_id esp_match[] = { | 620 | static const struct of_device_id esp_match[] = { |
| 600 | { | 621 | { |
| 601 | .name = "SUNW,esp", | 622 | .name = "SUNW,esp", |
| 602 | }, | 623 | }, |
| @@ -619,7 +640,7 @@ static struct of_platform_driver esp_sbus_driver = { | |||
| 619 | 640 | ||
| 620 | static int __init sunesp_init(void) | 641 | static int __init sunesp_init(void) |
| 621 | { | 642 | { |
| 622 | return of_register_driver(&esp_sbus_driver, &sbus_bus_type); | 643 | return of_register_driver(&esp_sbus_driver, &of_bus_type); |
| 623 | } | 644 | } |
| 624 | 645 | ||
| 625 | static void __exit sunesp_exit(void) | 646 | static void __exit sunesp_exit(void) |
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index e41766d08035..a94a2ab4b571 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
| @@ -616,7 +616,7 @@ static int __devexit hv_remove(struct of_device *dev) | |||
| 616 | return 0; | 616 | return 0; |
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | static struct of_device_id hv_match[] = { | 619 | static const struct of_device_id hv_match[] = { |
| 620 | { | 620 | { |
| 621 | .name = "console", | 621 | .name = "console", |
| 622 | .compatible = "qcn", | 622 | .compatible = "qcn", |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 29b4458abf74..0355efe115d9 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
| @@ -1078,7 +1078,7 @@ static int __devexit sab_remove(struct of_device *op) | |||
| 1078 | return 0; | 1078 | return 0; |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 1081 | static struct of_device_id sab_match[] = { | 1081 | static const struct of_device_id sab_match[] = { |
| 1082 | { | 1082 | { |
| 1083 | .name = "se", | 1083 | .name = "se", |
| 1084 | }, | 1084 | }, |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index a378464f9292..a4dc79b1d7ab 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
| @@ -1506,7 +1506,7 @@ static int __devexit su_remove(struct of_device *op) | |||
| 1506 | return 0; | 1506 | return 0; |
| 1507 | } | 1507 | } |
| 1508 | 1508 | ||
| 1509 | static struct of_device_id su_match[] = { | 1509 | static const struct of_device_id su_match[] = { |
| 1510 | { | 1510 | { |
| 1511 | .name = "su", | 1511 | .name = "su", |
| 1512 | }, | 1512 | }, |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 3cb4c8aee13f..45a299f35617 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
| @@ -1480,7 +1480,7 @@ static int __devexit zs_remove(struct of_device *op) | |||
| 1480 | return 0; | 1480 | return 0; |
| 1481 | } | 1481 | } |
| 1482 | 1482 | ||
| 1483 | static struct of_device_id zs_match[] = { | 1483 | static const struct of_device_id zs_match[] = { |
| 1484 | { | 1484 | { |
| 1485 | .name = "zs", | 1485 | .name = "zs", |
| 1486 | }, | 1486 | }, |
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index e721644bad74..1e35ba6f18e0 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
| @@ -372,7 +372,7 @@ static int __devexit bw2_remove(struct of_device *op) | |||
| 372 | return 0; | 372 | return 0; |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | static struct of_device_id bw2_match[] = { | 375 | static const struct of_device_id bw2_match[] = { |
| 376 | { | 376 | { |
| 377 | .name = "bwtwo", | 377 | .name = "bwtwo", |
| 378 | }, | 378 | }, |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index b17e74671779..a2d1882791a5 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
| @@ -589,7 +589,7 @@ static int __devexit cg14_remove(struct of_device *op) | |||
| 589 | return 0; | 589 | return 0; |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | static struct of_device_id cg14_match[] = { | 592 | static const struct of_device_id cg14_match[] = { |
| 593 | { | 593 | { |
| 594 | .name = "cgfourteen", | 594 | .name = "cgfourteen", |
| 595 | }, | 595 | }, |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 3aa7b6cb0268..99f87fb61d05 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
| @@ -456,7 +456,7 @@ static int __devexit cg3_remove(struct of_device *op) | |||
| 456 | return 0; | 456 | return 0; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static struct of_device_id cg3_match[] = { | 459 | static const struct of_device_id cg3_match[] = { |
| 460 | { | 460 | { |
| 461 | .name = "cgthree", | 461 | .name = "cgthree", |
| 462 | }, | 462 | }, |
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 2f64bb3bd254..940ec04f0f1b 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
| @@ -34,10 +34,11 @@ static int cg6_blank(int, struct fb_info *); | |||
| 34 | 34 | ||
| 35 | static void cg6_imageblit(struct fb_info *, const struct fb_image *); | 35 | static void cg6_imageblit(struct fb_info *, const struct fb_image *); |
| 36 | static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); | 36 | static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); |
| 37 | static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); | ||
| 37 | static int cg6_sync(struct fb_info *); | 38 | static int cg6_sync(struct fb_info *); |
| 38 | static int cg6_mmap(struct fb_info *, struct vm_area_struct *); | 39 | static int cg6_mmap(struct fb_info *, struct vm_area_struct *); |
| 39 | static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); | 40 | static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 40 | static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); | 41 | static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *); |
| 41 | 42 | ||
| 42 | /* | 43 | /* |
| 43 | * Frame buffer operations | 44 | * Frame buffer operations |
| @@ -47,6 +48,7 @@ static struct fb_ops cg6_ops = { | |||
| 47 | .owner = THIS_MODULE, | 48 | .owner = THIS_MODULE, |
| 48 | .fb_setcolreg = cg6_setcolreg, | 49 | .fb_setcolreg = cg6_setcolreg, |
| 49 | .fb_blank = cg6_blank, | 50 | .fb_blank = cg6_blank, |
| 51 | .fb_pan_display = cg6_pan_display, | ||
| 50 | .fb_fillrect = cg6_fillrect, | 52 | .fb_fillrect = cg6_fillrect, |
| 51 | .fb_copyarea = cg6_copyarea, | 53 | .fb_copyarea = cg6_copyarea, |
| 52 | .fb_imageblit = cg6_imageblit, | 54 | .fb_imageblit = cg6_imageblit, |
| @@ -161,6 +163,7 @@ static struct fb_ops cg6_ops = { | |||
| 161 | #define CG6_THC_MISC_INT_ENAB (1 << 5) | 163 | #define CG6_THC_MISC_INT_ENAB (1 << 5) |
| 162 | #define CG6_THC_MISC_INT (1 << 4) | 164 | #define CG6_THC_MISC_INT (1 << 4) |
| 163 | #define CG6_THC_MISC_INIT 0x9f | 165 | #define CG6_THC_MISC_INIT 0x9f |
| 166 | #define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16)) | ||
| 164 | 167 | ||
| 165 | /* The contents are unknown */ | 168 | /* The contents are unknown */ |
| 166 | struct cg6_tec { | 169 | struct cg6_tec { |
| @@ -280,6 +283,33 @@ static int cg6_sync(struct fb_info *info) | |||
| 280 | return 0; | 283 | return 0; |
| 281 | } | 284 | } |
| 282 | 285 | ||
| 286 | static void cg6_switch_from_graph(struct cg6_par *par) | ||
| 287 | { | ||
| 288 | struct cg6_thc __iomem *thc = par->thc; | ||
| 289 | unsigned long flags; | ||
| 290 | |||
| 291 | spin_lock_irqsave(&par->lock, flags); | ||
| 292 | |||
| 293 | /* Hide the cursor. */ | ||
| 294 | sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy); | ||
| 295 | |||
| 296 | spin_unlock_irqrestore(&par->lock, flags); | ||
| 297 | } | ||
| 298 | |||
| 299 | static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | ||
| 300 | { | ||
| 301 | struct cg6_par *par = (struct cg6_par *)info->par; | ||
| 302 | |||
| 303 | /* We just use this to catch switches out of | ||
| 304 | * graphics mode. | ||
| 305 | */ | ||
| 306 | cg6_switch_from_graph(par); | ||
| 307 | |||
| 308 | if (var->xoffset || var->yoffset || var->vmode) | ||
| 309 | return -EINVAL; | ||
| 310 | return 0; | ||
| 311 | } | ||
| 312 | |||
| 283 | /** | 313 | /** |
| 284 | * cg6_fillrect - Draws a rectangle on the screen. | 314 | * cg6_fillrect - Draws a rectangle on the screen. |
| 285 | * | 315 | * |
| @@ -643,9 +673,13 @@ static void __devinit cg6_chip_init(struct fb_info *info) | |||
| 643 | struct cg6_par *par = (struct cg6_par *)info->par; | 673 | struct cg6_par *par = (struct cg6_par *)info->par; |
| 644 | struct cg6_tec __iomem *tec = par->tec; | 674 | struct cg6_tec __iomem *tec = par->tec; |
| 645 | struct cg6_fbc __iomem *fbc = par->fbc; | 675 | struct cg6_fbc __iomem *fbc = par->fbc; |
| 676 | struct cg6_thc __iomem *thc = par->thc; | ||
| 646 | u32 rev, conf, mode; | 677 | u32 rev, conf, mode; |
| 647 | int i; | 678 | int i; |
| 648 | 679 | ||
| 680 | /* Hide the cursor. */ | ||
| 681 | sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy); | ||
| 682 | |||
| 649 | /* Turn off stuff in the Transform Engine. */ | 683 | /* Turn off stuff in the Transform Engine. */ |
| 650 | sbus_writel(0, &tec->tec_matrix); | 684 | sbus_writel(0, &tec->tec_matrix); |
| 651 | sbus_writel(0, &tec->tec_clip); | 685 | sbus_writel(0, &tec->tec_clip); |
| @@ -814,7 +848,7 @@ static int __devexit cg6_remove(struct of_device *op) | |||
| 814 | return 0; | 848 | return 0; |
| 815 | } | 849 | } |
| 816 | 850 | ||
| 817 | static struct of_device_id cg6_match[] = { | 851 | static const struct of_device_id cg6_match[] = { |
| 818 | { | 852 | { |
| 819 | .name = "cgsix", | 853 | .name = "cgsix", |
| 820 | }, | 854 | }, |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 7992b13ee68f..9dbb9646081f 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
| @@ -1042,7 +1042,7 @@ static int __devexit ffb_remove(struct of_device *op) | |||
| 1042 | return 0; | 1042 | return 0; |
| 1043 | } | 1043 | } |
| 1044 | 1044 | ||
| 1045 | static struct of_device_id ffb_match[] = { | 1045 | static const struct of_device_id ffb_match[] = { |
| 1046 | { | 1046 | { |
| 1047 | .name = "SUNW,ffb", | 1047 | .name = "SUNW,ffb", |
| 1048 | }, | 1048 | }, |
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 13fea61d6ae4..7c7e8c2da9d9 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
| @@ -33,6 +33,7 @@ static int leo_blank(int, struct fb_info *); | |||
| 33 | 33 | ||
| 34 | static int leo_mmap(struct fb_info *, struct vm_area_struct *); | 34 | static int leo_mmap(struct fb_info *, struct vm_area_struct *); |
| 35 | static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); | 35 | static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); |
| 36 | static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); | ||
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| 38 | * Frame buffer operations | 39 | * Frame buffer operations |
| @@ -42,6 +43,7 @@ static struct fb_ops leo_ops = { | |||
| 42 | .owner = THIS_MODULE, | 43 | .owner = THIS_MODULE, |
| 43 | .fb_setcolreg = leo_setcolreg, | 44 | .fb_setcolreg = leo_setcolreg, |
| 44 | .fb_blank = leo_blank, | 45 | .fb_blank = leo_blank, |
| 46 | .fb_pan_display = leo_pan_display, | ||
| 45 | .fb_fillrect = cfb_fillrect, | 47 | .fb_fillrect = cfb_fillrect, |
| 46 | .fb_copyarea = cfb_copyarea, | 48 | .fb_copyarea = cfb_copyarea, |
| 47 | .fb_imageblit = cfb_imageblit, | 49 | .fb_imageblit = cfb_imageblit, |
| @@ -206,6 +208,60 @@ static void leo_wait(struct leo_lx_krn __iomem *lx_krn) | |||
| 206 | return; | 208 | return; |
| 207 | } | 209 | } |
| 208 | 210 | ||
| 211 | static void leo_switch_from_graph(struct fb_info *info) | ||
| 212 | { | ||
| 213 | struct leo_par *par = (struct leo_par *) info->par; | ||
| 214 | struct leo_ld_ss0 __iomem *ss = par->ld_ss0; | ||
| 215 | struct leo_cursor __iomem *cursor = par->cursor; | ||
| 216 | unsigned long flags; | ||
| 217 | u32 val; | ||
| 218 | |||
| 219 | spin_lock_irqsave(&par->lock, flags); | ||
| 220 | |||
| 221 | par->extent = ((info->var.xres - 1) | | ||
| 222 | ((info->var.yres - 1) << 16)); | ||
| 223 | |||
| 224 | sbus_writel(0xffffffff, &ss->wid); | ||
| 225 | sbus_writel(0xffff, &ss->wmask); | ||
| 226 | sbus_writel(0, &ss->vclipmin); | ||
| 227 | sbus_writel(par->extent, &ss->vclipmax); | ||
| 228 | sbus_writel(0, &ss->fg); | ||
| 229 | sbus_writel(0xff000000, &ss->planemask); | ||
| 230 | sbus_writel(0x310850, &ss->rop); | ||
| 231 | sbus_writel(0, &ss->widclip); | ||
| 232 | sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), | ||
| 233 | &par->lc_ss0_usr->extent); | ||
| 234 | sbus_writel(4, &par->lc_ss0_usr->addrspace); | ||
| 235 | sbus_writel(0x80000000, &par->lc_ss0_usr->fill); | ||
| 236 | sbus_writel(0, &par->lc_ss0_usr->fontt); | ||
| 237 | do { | ||
| 238 | val = sbus_readl(&par->lc_ss0_usr->csr); | ||
| 239 | } while (val & 0x20000000); | ||
| 240 | |||
| 241 | /* setup screen buffer for cfb_* functions */ | ||
| 242 | sbus_writel(1, &ss->wid); | ||
| 243 | sbus_writel(0x00ffffff, &ss->planemask); | ||
| 244 | sbus_writel(0x310b90, &ss->rop); | ||
| 245 | sbus_writel(0, &par->lc_ss0_usr->addrspace); | ||
| 246 | |||
| 247 | /* hide cursor */ | ||
| 248 | sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc); | ||
| 249 | |||
| 250 | spin_unlock_irqrestore(&par->lock, flags); | ||
| 251 | } | ||
| 252 | |||
| 253 | static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | ||
| 254 | { | ||
| 255 | /* We just use this to catch switches out of | ||
| 256 | * graphics mode. | ||
| 257 | */ | ||
| 258 | leo_switch_from_graph(info); | ||
| 259 | |||
| 260 | if (var->xoffset || var->yoffset || var->vmode) | ||
| 261 | return -EINVAL; | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 209 | /** | 265 | /** |
| 210 | * leo_setcolreg - Optional function. Sets a color register. | 266 | * leo_setcolreg - Optional function. Sets a color register. |
| 211 | * @regno: boolean, 0 copy local, 1 get_user() function | 267 | * @regno: boolean, 0 copy local, 1 get_user() function |
| @@ -454,44 +510,6 @@ static void leo_init_wids(struct fb_info *info) | |||
| 454 | leo_wid_put(info, &wl); | 510 | leo_wid_put(info, &wl); |
| 455 | } | 511 | } |
| 456 | 512 | ||
| 457 | static void leo_switch_from_graph(struct fb_info *info) | ||
| 458 | { | ||
| 459 | struct leo_par *par = (struct leo_par *) info->par; | ||
| 460 | struct leo_ld_ss0 __iomem *ss = par->ld_ss0; | ||
| 461 | unsigned long flags; | ||
| 462 | u32 val; | ||
| 463 | |||
| 464 | spin_lock_irqsave(&par->lock, flags); | ||
| 465 | |||
| 466 | par->extent = ((info->var.xres - 1) | | ||
| 467 | ((info->var.yres - 1) << 16)); | ||
| 468 | |||
| 469 | sbus_writel(0xffffffff, &ss->wid); | ||
| 470 | sbus_writel(0xffff, &ss->wmask); | ||
| 471 | sbus_writel(0, &ss->vclipmin); | ||
| 472 | sbus_writel(par->extent, &ss->vclipmax); | ||
| 473 | sbus_writel(0, &ss->fg); | ||
| 474 | sbus_writel(0xff000000, &ss->planemask); | ||
| 475 | sbus_writel(0x310850, &ss->rop); | ||
| 476 | sbus_writel(0, &ss->widclip); | ||
| 477 | sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), | ||
| 478 | &par->lc_ss0_usr->extent); | ||
| 479 | sbus_writel(4, &par->lc_ss0_usr->addrspace); | ||
| 480 | sbus_writel(0x80000000, &par->lc_ss0_usr->fill); | ||
| 481 | sbus_writel(0, &par->lc_ss0_usr->fontt); | ||
| 482 | do { | ||
| 483 | val = sbus_readl(&par->lc_ss0_usr->csr); | ||
| 484 | } while (val & 0x20000000); | ||
| 485 | |||
| 486 | /* setup screen buffer for cfb_* functions */ | ||
| 487 | sbus_writel(1, &ss->wid); | ||
| 488 | sbus_writel(0x00ffffff, &ss->planemask); | ||
| 489 | sbus_writel(0x310b90, &ss->rop); | ||
| 490 | sbus_writel(0, &par->lc_ss0_usr->addrspace); | ||
| 491 | |||
| 492 | spin_unlock_irqrestore(&par->lock, flags); | ||
| 493 | } | ||
| 494 | |||
| 495 | static void leo_init_hw(struct fb_info *info) | 513 | static void leo_init_hw(struct fb_info *info) |
| 496 | { | 514 | { |
| 497 | struct leo_par *par = (struct leo_par *) info->par; | 515 | struct leo_par *par = (struct leo_par *) info->par; |
| @@ -641,7 +659,7 @@ static int __devexit leo_remove(struct of_device *op) | |||
| 641 | return 0; | 659 | return 0; |
| 642 | } | 660 | } |
| 643 | 661 | ||
| 644 | static struct of_device_id leo_match[] = { | 662 | static const struct of_device_id leo_match[] = { |
| 645 | { | 663 | { |
| 646 | .name = "SUNW,leo", | 664 | .name = "SUNW,leo", |
| 647 | }, | 665 | }, |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 9e903454ffc1..7000f2cd5854 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
| @@ -349,7 +349,7 @@ static int __devexit p9100_remove(struct of_device *op) | |||
| 349 | return 0; | 349 | return 0; |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | static struct of_device_id p9100_match[] = { | 352 | static const struct of_device_id p9100_match[] = { |
| 353 | { | 353 | { |
| 354 | .name = "p9100", | 354 | .name = "p9100", |
| 355 | }, | 355 | }, |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 2a03f78bbb0d..643afbfe8277 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
| @@ -505,7 +505,7 @@ static int __devexit tcx_remove(struct of_device *op) | |||
| 505 | return 0; | 505 | return 0; |
| 506 | } | 506 | } |
| 507 | 507 | ||
| 508 | static struct of_device_id tcx_match[] = { | 508 | static const struct of_device_id tcx_match[] = { |
| 509 | { | 509 | { |
| 510 | .name = "SUNW,tcx", | 510 | .name = "SUNW,tcx", |
| 511 | }, | 511 | }, |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e0ef123fbdea..6702d2ef0434 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
| @@ -123,6 +123,9 @@ obj-$(CONFIG_SH_WDT) += shwdt.o | |||
| 123 | 123 | ||
| 124 | # SPARC64 Architecture | 124 | # SPARC64 Architecture |
| 125 | 125 | ||
| 126 | obj-$(CONFIG_WATCHDOG_RIO) += riowd.o | ||
| 127 | obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o | ||
| 128 | |||
| 126 | # XTENSA Architecture | 129 | # XTENSA Architecture |
| 127 | 130 | ||
| 128 | # Architecture Independant | 131 | # Architecture Independant |
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c new file mode 100644 index 000000000000..084dfe9cecfb --- /dev/null +++ b/drivers/watchdog/cpwd.c | |||
| @@ -0,0 +1,695 @@ | |||
| 1 | /* cpwd.c - driver implementation for hardware watchdog | ||
| 2 | * timers found on Sun Microsystems CP1400 and CP1500 boards. | ||
| 3 | * | ||
| 4 | * This device supports both the generic Linux watchdog | ||
| 5 | * interface and Solaris-compatible ioctls as best it is | ||
| 6 | * able. | ||
| 7 | * | ||
| 8 | * NOTE: CP1400 systems appear to have a defective intr_mask | ||
| 9 | * register on the PLD, preventing the disabling of | ||
| 10 | * timer interrupts. We use a timer to periodically | ||
| 11 | * reset 'stopped' watchdogs on affected platforms. | ||
| 12 | * | ||
| 13 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | ||
| 14 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/fs.h> | ||
| 20 | #include <linux/errno.h> | ||
| 21 | #include <linux/major.h> | ||
| 22 | #include <linux/init.h> | ||
| 23 | #include <linux/miscdevice.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/ioport.h> | ||
| 26 | #include <linux/timer.h> | ||
| 27 | #include <linux/smp_lock.h> | ||
| 28 | #include <linux/io.h> | ||
| 29 | #include <linux/of.h> | ||
| 30 | #include <linux/of_device.h> | ||
| 31 | |||
| 32 | #include <asm/irq.h> | ||
| 33 | #include <asm/uaccess.h> | ||
| 34 | |||
| 35 | #include <asm/watchdog.h> | ||
| 36 | |||
| 37 | #define DRIVER_NAME "cpwd" | ||
| 38 | #define PFX DRIVER_NAME ": " | ||
| 39 | |||
| 40 | #define WD_OBPNAME "watchdog" | ||
| 41 | #define WD_BADMODEL "SUNW,501-5336" | ||
| 42 | #define WD_BTIMEOUT (jiffies + (HZ * 1000)) | ||
| 43 | #define WD_BLIMIT 0xFFFF | ||
| 44 | |||
| 45 | #define WD0_MINOR 212 | ||
| 46 | #define WD1_MINOR 213 | ||
| 47 | #define WD2_MINOR 214 | ||
| 48 | |||
| 49 | /* Internal driver definitions. */ | ||
| 50 | #define WD0_ID 0 | ||
| 51 | #define WD1_ID 1 | ||
| 52 | #define WD2_ID 2 | ||
| 53 | #define WD_NUMDEVS 3 | ||
| 54 | |||
| 55 | #define WD_INTR_OFF 0 | ||
| 56 | #define WD_INTR_ON 1 | ||
| 57 | |||
| 58 | #define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */ | ||
| 59 | #define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */ | ||
| 60 | #define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */ | ||
| 61 | |||
| 62 | /* Register value definitions | ||
| 63 | */ | ||
| 64 | #define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */ | ||
| 65 | #define WD1_INTR_MASK 0x02 | ||
| 66 | #define WD2_INTR_MASK 0x04 | ||
| 67 | |||
| 68 | #define WD_S_RUNNING 0x01 /* Watchdog device status running */ | ||
| 69 | #define WD_S_EXPIRED 0x02 /* Watchdog device status expired */ | ||
| 70 | |||
| 71 | struct cpwd { | ||
| 72 | void __iomem *regs; | ||
| 73 | spinlock_t lock; | ||
| 74 | |||
| 75 | unsigned int irq; | ||
| 76 | |||
| 77 | unsigned long timeout; | ||
| 78 | bool enabled; | ||
| 79 | bool reboot; | ||
| 80 | bool broken; | ||
| 81 | bool initialized; | ||
| 82 | |||
| 83 | struct { | ||
| 84 | struct miscdevice misc; | ||
| 85 | void __iomem *regs; | ||
| 86 | u8 intr_mask; | ||
| 87 | u8 runstatus; | ||
| 88 | u16 timeout; | ||
| 89 | } devs[WD_NUMDEVS]; | ||
| 90 | }; | ||
| 91 | |||
| 92 | static struct cpwd *cpwd_device; | ||
| 93 | |||
| 94 | /* Sun uses Altera PLD EPF8820ATC144-4 | ||
| 95 | * providing three hardware watchdogs: | ||
| 96 | * | ||
| 97 | * 1) RIC - sends an interrupt when triggered | ||
| 98 | * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU | ||
| 99 | * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board | ||
| 100 | * | ||
| 101 | *** Timer register block definition (struct wd_timer_regblk) | ||
| 102 | * | ||
| 103 | * dcntr and limit registers (halfword access): | ||
| 104 | * ------------------- | ||
| 105 | * | 15 | ...| 1 | 0 | | ||
| 106 | * ------------------- | ||
| 107 | * |- counter val -| | ||
| 108 | * ------------------- | ||
| 109 | * dcntr - Current 16-bit downcounter value. | ||
| 110 | * When downcounter reaches '0' watchdog expires. | ||
| 111 | * Reading this register resets downcounter with 'limit' value. | ||
| 112 | * limit - 16-bit countdown value in 1/10th second increments. | ||
| 113 | * Writing this register begins countdown with input value. | ||
| 114 | * Reading from this register does not affect counter. | ||
| 115 | * NOTES: After watchdog reset, dcntr and limit contain '1' | ||
| 116 | * | ||
| 117 | * status register (byte access): | ||
| 118 | * --------------------------- | ||
| 119 | * | 7 | ... | 2 | 1 | 0 | | ||
| 120 | * --------------+------------ | ||
| 121 | * |- UNUSED -| EXP | RUN | | ||
| 122 | * --------------------------- | ||
| 123 | * status- Bit 0 - Watchdog is running | ||
| 124 | * Bit 1 - Watchdog has expired | ||
| 125 | * | ||
| 126 | *** PLD register block definition (struct wd_pld_regblk) | ||
| 127 | * | ||
| 128 | * intr_mask register (byte access): | ||
| 129 | * --------------------------------- | ||
| 130 | * | 7 | ... | 3 | 2 | 1 | 0 | | ||
| 131 | * +-------------+------------------ | ||
| 132 | * |- UNUSED -| WD3 | WD2 | WD1 | | ||
| 133 | * --------------------------------- | ||
| 134 | * WD3 - 1 == Interrupt disabled for watchdog 3 | ||
| 135 | * WD2 - 1 == Interrupt disabled for watchdog 2 | ||
| 136 | * WD1 - 1 == Interrupt disabled for watchdog 1 | ||
| 137 | * | ||
| 138 | * pld_status register (byte access): | ||
| 139 | * UNKNOWN, MAGICAL MYSTERY REGISTER | ||
| 140 | * | ||
| 141 | */ | ||
| 142 | #define WD_TIMER_REGSZ 16 | ||
| 143 | #define WD0_OFF 0 | ||
| 144 | #define WD1_OFF (WD_TIMER_REGSZ * 1) | ||
| 145 | #define WD2_OFF (WD_TIMER_REGSZ * 2) | ||
| 146 | #define PLD_OFF (WD_TIMER_REGSZ * 3) | ||
| 147 | |||
| 148 | #define WD_DCNTR 0x00 | ||
| 149 | #define WD_LIMIT 0x04 | ||
| 150 | #define WD_STATUS 0x08 | ||
| 151 | |||
| 152 | #define PLD_IMASK (PLD_OFF + 0x00) | ||
| 153 | #define PLD_STATUS (PLD_OFF + 0x04) | ||
| 154 | |||
| 155 | static struct timer_list cpwd_timer; | ||
| 156 | |||
| 157 | static int wd0_timeout = 0; | ||
| 158 | static int wd1_timeout = 0; | ||
| 159 | static int wd2_timeout = 0; | ||
| 160 | |||
| 161 | module_param (wd0_timeout, int, 0); | ||
| 162 | MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); | ||
| 163 | module_param (wd1_timeout, int, 0); | ||
| 164 | MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); | ||
| 165 | module_param (wd2_timeout, int, 0); | ||
| 166 | MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); | ||
| 167 | |||
| 168 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); | ||
| 169 | MODULE_DESCRIPTION("Hardware watchdog driver for Sun Microsystems CP1400/1500"); | ||
| 170 | MODULE_LICENSE("GPL"); | ||
| 171 | MODULE_SUPPORTED_DEVICE("watchdog"); | ||
| 172 | |||
| 173 | static void cpwd_writew(u16 val, void __iomem *addr) | ||
| 174 | { | ||
| 175 | writew(cpu_to_le16(val), addr); | ||
| 176 | } | ||
| 177 | static u16 cpwd_readw(void __iomem *addr) | ||
| 178 | { | ||
| 179 | u16 val = readw(addr); | ||
| 180 | |||
| 181 | return le16_to_cpu(val); | ||
| 182 | } | ||
| 183 | |||
| 184 | static void cpwd_writeb(u8 val, void __iomem *addr) | ||
| 185 | { | ||
| 186 | writeb(val, addr); | ||
| 187 | } | ||
| 188 | |||
| 189 | static u8 cpwd_readb(void __iomem *addr) | ||
| 190 | { | ||
| 191 | return readb(addr); | ||
| 192 | } | ||
| 193 | |||
| 194 | /* Enable or disable watchdog interrupts | ||
| 195 | * Because of the CP1400 defect this should only be | ||
| 196 | * called during initialzation or by wd_[start|stop]timer() | ||
| 197 | * | ||
| 198 | * index - sub-device index, or -1 for 'all' | ||
| 199 | * enable - non-zero to enable interrupts, zero to disable | ||
| 200 | */ | ||
| 201 | static void cpwd_toggleintr(struct cpwd *p, int index, int enable) | ||
| 202 | { | ||
| 203 | unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK); | ||
| 204 | unsigned char setregs = | ||
| 205 | (index == -1) ? | ||
| 206 | (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : | ||
| 207 | (p->devs[index].intr_mask); | ||
| 208 | |||
| 209 | if (enable == WD_INTR_ON) | ||
| 210 | curregs &= ~setregs; | ||
| 211 | else | ||
| 212 | curregs |= setregs; | ||
| 213 | |||
| 214 | cpwd_writeb(curregs, p->regs + PLD_IMASK); | ||
| 215 | } | ||
| 216 | |||
| 217 | /* Restarts timer with maximum limit value and | ||
| 218 | * does not unset 'brokenstop' value. | ||
| 219 | */ | ||
| 220 | static void cpwd_resetbrokentimer(struct cpwd *p, int index) | ||
| 221 | { | ||
| 222 | cpwd_toggleintr(p, index, WD_INTR_ON); | ||
| 223 | cpwd_writew(WD_BLIMIT, p->devs[index].regs + WD_LIMIT); | ||
| 224 | } | ||
| 225 | |||
| 226 | /* Timer method called to reset stopped watchdogs-- | ||
| 227 | * because of the PLD bug on CP1400, we cannot mask | ||
| 228 | * interrupts within the PLD so me must continually | ||
| 229 | * reset the timers ad infinitum. | ||
| 230 | */ | ||
| 231 | static void cpwd_brokentimer(unsigned long data) | ||
| 232 | { | ||
| 233 | struct cpwd *p = (struct cpwd *) data; | ||
| 234 | int id, tripped = 0; | ||
| 235 | |||
| 236 | /* kill a running timer instance, in case we | ||
| 237 | * were called directly instead of by kernel timer | ||
| 238 | */ | ||
| 239 | if (timer_pending(&cpwd_timer)) | ||
| 240 | del_timer(&cpwd_timer); | ||
| 241 | |||
| 242 | for (id = 0; id < WD_NUMDEVS; id++) { | ||
| 243 | if (p->devs[id].runstatus & WD_STAT_BSTOP) { | ||
| 244 | ++tripped; | ||
| 245 | cpwd_resetbrokentimer(p, id); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | if (tripped) { | ||
| 250 | /* there is at least one timer brokenstopped-- reschedule */ | ||
| 251 | cpwd_timer.expires = WD_BTIMEOUT; | ||
| 252 | add_timer(&cpwd_timer); | ||
| 253 | } | ||
| 254 | } | ||
| 255 | |||
| 256 | /* Reset countdown timer with 'limit' value and continue countdown. | ||
| 257 | * This will not start a stopped timer. | ||
| 258 | */ | ||
| 259 | static void cpwd_pingtimer(struct cpwd *p, int index) | ||
| 260 | { | ||
| 261 | if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) | ||
| 262 | cpwd_readw(p->devs[index].regs + WD_DCNTR); | ||
| 263 | } | ||
| 264 | |||
| 265 | /* Stop a running watchdog timer-- the timer actually keeps | ||
| 266 | * running, but the interrupt is masked so that no action is | ||
| 267 | * taken upon expiration. | ||
| 268 | */ | ||
| 269 | static void cpwd_stoptimer(struct cpwd *p, int index) | ||
| 270 | { | ||
| 271 | if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) { | ||
| 272 | cpwd_toggleintr(p, index, WD_INTR_OFF); | ||
| 273 | |||
| 274 | if (p->broken) { | ||
| 275 | p->devs[index].runstatus |= WD_STAT_BSTOP; | ||
| 276 | cpwd_brokentimer((unsigned long) p); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Start a watchdog timer with the specified limit value | ||
| 282 | * If the watchdog is running, it will be restarted with | ||
| 283 | * the provided limit value. | ||
| 284 | * | ||
| 285 | * This function will enable interrupts on the specified | ||
| 286 | * watchdog. | ||
| 287 | */ | ||
| 288 | static void cpwd_starttimer(struct cpwd *p, int index) | ||
| 289 | { | ||
| 290 | if (p->broken) | ||
| 291 | p->devs[index].runstatus &= ~WD_STAT_BSTOP; | ||
| 292 | |||
| 293 | p->devs[index].runstatus &= ~WD_STAT_SVCD; | ||
| 294 | |||
| 295 | cpwd_writew(p->devs[index].timeout, p->devs[index].regs + WD_LIMIT); | ||
| 296 | cpwd_toggleintr(p, index, WD_INTR_ON); | ||
| 297 | } | ||
| 298 | |||
| 299 | static int cpwd_getstatus(struct cpwd *p, int index) | ||
| 300 | { | ||
| 301 | unsigned char stat = cpwd_readb(p->devs[index].regs + WD_STATUS); | ||
| 302 | unsigned char intr = cpwd_readb(p->devs[index].regs + PLD_IMASK); | ||
| 303 | unsigned char ret = WD_STOPPED; | ||
| 304 | |||
| 305 | /* determine STOPPED */ | ||
| 306 | if (!stat) | ||
| 307 | return ret; | ||
| 308 | |||
| 309 | /* determine EXPIRED vs FREERUN vs RUNNING */ | ||
| 310 | else if (WD_S_EXPIRED & stat) { | ||
| 311 | ret = WD_EXPIRED; | ||
| 312 | } else if(WD_S_RUNNING & stat) { | ||
| 313 | if (intr & p->devs[index].intr_mask) { | ||
| 314 | ret = WD_FREERUN; | ||
| 315 | } else { | ||
| 316 | /* Fudge WD_EXPIRED status for defective CP1400-- | ||
| 317 | * IF timer is running | ||
| 318 | * AND brokenstop is set | ||
| 319 | * AND an interrupt has been serviced | ||
| 320 | * we are WD_EXPIRED. | ||
| 321 | * | ||
| 322 | * IF timer is running | ||
| 323 | * AND brokenstop is set | ||
| 324 | * AND no interrupt has been serviced | ||
| 325 | * we are WD_FREERUN. | ||
| 326 | */ | ||
| 327 | if (p->broken && | ||
| 328 | (p->devs[index].runstatus & WD_STAT_BSTOP)) { | ||
| 329 | if (p->devs[index].runstatus & WD_STAT_SVCD) { | ||
| 330 | ret = WD_EXPIRED; | ||
| 331 | } else { | ||
| 332 | /* we could as well pretend we are expired */ | ||
| 333 | ret = WD_FREERUN; | ||
| 334 | } | ||
| 335 | } else { | ||
| 336 | ret = WD_RUNNING; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | /* determine SERVICED */ | ||
| 342 | if (p->devs[index].runstatus & WD_STAT_SVCD) | ||
| 343 | ret |= WD_SERVICED; | ||
| 344 | |||
| 345 | return(ret); | ||
| 346 | } | ||
| 347 | |||
| 348 | static irqreturn_t cpwd_interrupt(int irq, void *dev_id) | ||
| 349 | { | ||
| 350 | struct cpwd *p = dev_id; | ||
| 351 | |||
| 352 | /* Only WD0 will interrupt-- others are NMI and we won't | ||
| 353 | * see them here.... | ||
| 354 | */ | ||
| 355 | spin_lock_irq(&p->lock); | ||
| 356 | |||
| 357 | cpwd_stoptimer(p, WD0_ID); | ||
| 358 | p->devs[WD0_ID].runstatus |= WD_STAT_SVCD; | ||
| 359 | |||
| 360 | spin_unlock_irq(&p->lock); | ||
| 361 | |||
| 362 | return IRQ_HANDLED; | ||
| 363 | } | ||
| 364 | |||
| 365 | static int cpwd_open(struct inode *inode, struct file *f) | ||
| 366 | { | ||
| 367 | struct cpwd *p = cpwd_device; | ||
| 368 | |||
| 369 | lock_kernel(); | ||
| 370 | switch(iminor(inode)) { | ||
| 371 | case WD0_MINOR: | ||
| 372 | case WD1_MINOR: | ||
| 373 | case WD2_MINOR: | ||
| 374 | break; | ||
| 375 | |||
| 376 | default: | ||
| 377 | unlock_kernel(); | ||
| 378 | return -ENODEV; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* Register IRQ on first open of device */ | ||
| 382 | if (!p->initialized) { | ||
| 383 | if (request_irq(p->irq, &cpwd_interrupt, | ||
| 384 | IRQF_SHARED, DRIVER_NAME, p)) { | ||
| 385 | printk(KERN_ERR PFX "Cannot register IRQ %d\n", | ||
| 386 | p->irq); | ||
| 387 | unlock_kernel(); | ||
| 388 | return -EBUSY; | ||
| 389 | } | ||
| 390 | p->initialized = true; | ||
| 391 | } | ||
| 392 | |||
| 393 | unlock_kernel(); | ||
| 394 | |||
| 395 | return nonseekable_open(inode, f); | ||
| 396 | } | ||
| 397 | |||
| 398 | static int cpwd_release(struct inode *inode, struct file *file) | ||
| 399 | { | ||
| 400 | return 0; | ||
| 401 | } | ||
| 402 | |||
| 403 | static int cpwd_ioctl(struct inode *inode, struct file *file, | ||
| 404 | unsigned int cmd, unsigned long arg) | ||
| 405 | { | ||
| 406 | static struct watchdog_info info = { | ||
| 407 | .options = WDIOF_SETTIMEOUT, | ||
| 408 | .firmware_version = 1, | ||
| 409 | .identity = DRIVER_NAME, | ||
| 410 | }; | ||
| 411 | void __user *argp = (void __user *)arg; | ||
| 412 | int index = iminor(inode) - WD0_MINOR; | ||
| 413 | struct cpwd *p = cpwd_device; | ||
| 414 | int setopt = 0; | ||
| 415 | |||
| 416 | switch (cmd) { | ||
| 417 | /* Generic Linux IOCTLs */ | ||
| 418 | case WDIOC_GETSUPPORT: | ||
| 419 | if (copy_to_user(argp, &info, sizeof(struct watchdog_info))) | ||
| 420 | return -EFAULT; | ||
| 421 | break; | ||
| 422 | |||
| 423 | case WDIOC_GETSTATUS: | ||
| 424 | case WDIOC_GETBOOTSTATUS: | ||
| 425 | if (put_user(0, (int __user *)argp)) | ||
| 426 | return -EFAULT; | ||
| 427 | break; | ||
| 428 | |||
| 429 | case WDIOC_KEEPALIVE: | ||
| 430 | cpwd_pingtimer(p, index); | ||
| 431 | break; | ||
| 432 | |||
| 433 | case WDIOC_SETOPTIONS: | ||
| 434 | if (copy_from_user(&setopt, argp, sizeof(unsigned int))) | ||
| 435 | return -EFAULT; | ||
| 436 | |||
| 437 | if (setopt & WDIOS_DISABLECARD) { | ||
| 438 | if (p->enabled) | ||
| 439 | return -EINVAL; | ||
| 440 | cpwd_stoptimer(p, index); | ||
| 441 | } else if (setopt & WDIOS_ENABLECARD) { | ||
| 442 | cpwd_starttimer(p, index); | ||
| 443 | } else { | ||
| 444 | return -EINVAL; | ||
| 445 | } | ||
| 446 | break; | ||
| 447 | |||
| 448 | /* Solaris-compatible IOCTLs */ | ||
| 449 | case WIOCGSTAT: | ||
| 450 | setopt = cpwd_getstatus(p, index); | ||
| 451 | if (copy_to_user(argp, &setopt, sizeof(unsigned int))) | ||
| 452 | return -EFAULT; | ||
| 453 | break; | ||
| 454 | |||
| 455 | case WIOCSTART: | ||
| 456 | cpwd_starttimer(p, index); | ||
| 457 | break; | ||
| 458 | |||
| 459 | case WIOCSTOP: | ||
| 460 | if (p->enabled) | ||
| 461 | return(-EINVAL); | ||
| 462 | |||
| 463 | cpwd_stoptimer(p, index); | ||
| 464 | break; | ||
| 465 | |||
| 466 | default: | ||
| 467 | return -EINVAL; | ||
| 468 | } | ||
| 469 | |||
| 470 | return 0; | ||
| 471 | } | ||
| 472 | |||
| 473 | static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 474 | unsigned long arg) | ||
| 475 | { | ||
| 476 | int rval = -ENOIOCTLCMD; | ||
| 477 | |||
| 478 | switch (cmd) { | ||
| 479 | /* solaris ioctls are specific to this driver */ | ||
| 480 | case WIOCSTART: | ||
| 481 | case WIOCSTOP: | ||
| 482 | case WIOCGSTAT: | ||
| 483 | lock_kernel(); | ||
| 484 | rval = cpwd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | ||
| 485 | unlock_kernel(); | ||
| 486 | break; | ||
| 487 | |||
| 488 | /* everything else is handled by the generic compat layer */ | ||
| 489 | default: | ||
| 490 | break; | ||
| 491 | } | ||
| 492 | |||
| 493 | return rval; | ||
| 494 | } | ||
| 495 | |||
| 496 | static ssize_t cpwd_write(struct file *file, const char __user *buf, | ||
| 497 | size_t count, loff_t *ppos) | ||
| 498 | { | ||
| 499 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 500 | struct cpwd *p = cpwd_device; | ||
| 501 | int index = iminor(inode); | ||
| 502 | |||
| 503 | if (count) { | ||
| 504 | cpwd_pingtimer(p, index); | ||
| 505 | return 1; | ||
| 506 | } | ||
| 507 | |||
| 508 | return 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | static ssize_t cpwd_read(struct file * file, char __user *buffer, | ||
| 512 | size_t count, loff_t *ppos) | ||
| 513 | { | ||
| 514 | return -EINVAL; | ||
| 515 | } | ||
| 516 | |||
| 517 | static const struct file_operations cpwd_fops = { | ||
| 518 | .owner = THIS_MODULE, | ||
| 519 | .ioctl = cpwd_ioctl, | ||
| 520 | .compat_ioctl = cpwd_compat_ioctl, | ||
| 521 | .open = cpwd_open, | ||
| 522 | .write = cpwd_write, | ||
| 523 | .read = cpwd_read, | ||
| 524 | .release = cpwd_release, | ||
| 525 | }; | ||
| 526 | |||
| 527 | static int __devinit cpwd_probe(struct of_device *op, | ||
| 528 | const struct of_device_id *match) | ||
| 529 | { | ||
| 530 | struct device_node *options; | ||
| 531 | const char *str_prop; | ||
| 532 | const void *prop_val; | ||
| 533 | int i, err = -EINVAL; | ||
| 534 | struct cpwd *p; | ||
| 535 | |||
| 536 | if (cpwd_device) | ||
| 537 | return -EINVAL; | ||
| 538 | |||
| 539 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 540 | err = -ENOMEM; | ||
| 541 | if (!p) { | ||
| 542 | printk(KERN_ERR PFX "Unable to allocate struct cpwd.\n"); | ||
| 543 | goto out; | ||
| 544 | } | ||
| 545 | |||
| 546 | p->irq = op->irqs[0]; | ||
| 547 | |||
| 548 | spin_lock_init(&p->lock); | ||
| 549 | |||
| 550 | p->regs = of_ioremap(&op->resource[0], 0, | ||
| 551 | 4 * WD_TIMER_REGSZ, DRIVER_NAME); | ||
| 552 | if (!p->regs) { | ||
| 553 | printk(KERN_ERR PFX "Unable to map registers.\n"); | ||
| 554 | goto out_free; | ||
| 555 | } | ||
| 556 | |||
| 557 | options = of_find_node_by_path("/options"); | ||
| 558 | err = -ENODEV; | ||
| 559 | if (!options) { | ||
| 560 | printk(KERN_ERR PFX "Unable to find /options node.\n"); | ||
| 561 | goto out_iounmap; | ||
| 562 | } | ||
| 563 | |||
| 564 | prop_val = of_get_property(options, "watchdog-enable?", NULL); | ||
| 565 | p->enabled = (prop_val ? true : false); | ||
| 566 | |||
| 567 | prop_val = of_get_property(options, "watchdog-reboot?", NULL); | ||
| 568 | p->reboot = (prop_val ? true : false); | ||
| 569 | |||
| 570 | str_prop = of_get_property(options, "watchdog-timeout", NULL); | ||
| 571 | if (str_prop) | ||
| 572 | p->timeout = simple_strtoul(str_prop, NULL, 10); | ||
| 573 | |||
| 574 | /* CP1400s seem to have broken PLD implementations-- the | ||
| 575 | * interrupt_mask register cannot be written, so no timer | ||
| 576 | * interrupts can be masked within the PLD. | ||
| 577 | */ | ||
| 578 | str_prop = of_get_property(op->node, "model", NULL); | ||
| 579 | p->broken = (str_prop && !strcmp(str_prop, WD_BADMODEL)); | ||
| 580 | |||
| 581 | if (!p->enabled) | ||
| 582 | cpwd_toggleintr(p, -1, WD_INTR_OFF); | ||
| 583 | |||
| 584 | for (i = 0; i < WD_NUMDEVS; i++) { | ||
| 585 | static const char *cpwd_names[] = { "RIC", "XIR", "POR" }; | ||
| 586 | static int *parms[] = { &wd0_timeout, | ||
| 587 | &wd1_timeout, | ||
| 588 | &wd2_timeout }; | ||
| 589 | struct miscdevice *mp = &p->devs[i].misc; | ||
| 590 | |||
| 591 | mp->minor = WD0_MINOR + i; | ||
| 592 | mp->name = cpwd_names[i]; | ||
| 593 | mp->fops = &cpwd_fops; | ||
| 594 | |||
| 595 | p->devs[i].regs = p->regs + (i * WD_TIMER_REGSZ); | ||
| 596 | p->devs[i].intr_mask = (WD0_INTR_MASK << i); | ||
| 597 | p->devs[i].runstatus &= ~WD_STAT_BSTOP; | ||
| 598 | p->devs[i].runstatus |= WD_STAT_INIT; | ||
| 599 | p->devs[i].timeout = p->timeout; | ||
| 600 | if (*parms[i]) | ||
| 601 | p->devs[i].timeout = *parms[i]; | ||
| 602 | |||
| 603 | err = misc_register(&p->devs[i].misc); | ||
| 604 | if (err) { | ||
| 605 | printk(KERN_ERR "Could not register misc device for " | ||
| 606 | "dev %d\n", i); | ||
| 607 | goto out_unregister; | ||
| 608 | } | ||
| 609 | } | ||
| 610 | |||
| 611 | if (p->broken) { | ||
| 612 | init_timer(&cpwd_timer); | ||
| 613 | cpwd_timer.function = cpwd_brokentimer; | ||
| 614 | cpwd_timer.data = (unsigned long) p; | ||
| 615 | cpwd_timer.expires = WD_BTIMEOUT; | ||
| 616 | |||
| 617 | printk(KERN_INFO PFX "PLD defect workaround enabled for " | ||
| 618 | "model " WD_BADMODEL ".\n"); | ||
| 619 | } | ||
| 620 | |||
| 621 | dev_set_drvdata(&op->dev, p); | ||
| 622 | cpwd_device = p; | ||
| 623 | err = 0; | ||
| 624 | |||
| 625 | out: | ||
| 626 | return err; | ||
| 627 | |||
| 628 | out_unregister: | ||
| 629 | for (i--; i >= 0; i--) | ||
| 630 | misc_deregister(&p->devs[i].misc); | ||
| 631 | |||
| 632 | out_iounmap: | ||
| 633 | of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); | ||
| 634 | |||
| 635 | out_free: | ||
| 636 | kfree(p); | ||
| 637 | goto out; | ||
| 638 | } | ||
| 639 | |||
| 640 | static int __devexit cpwd_remove(struct of_device *op) | ||
| 641 | { | ||
| 642 | struct cpwd *p = dev_get_drvdata(&op->dev); | ||
| 643 | int i; | ||
| 644 | |||
| 645 | for (i = 0; i < 4; i++) { | ||
| 646 | misc_deregister(&p->devs[i].misc); | ||
| 647 | |||
| 648 | if (!p->enabled) { | ||
| 649 | cpwd_stoptimer(p, i); | ||
| 650 | if (p->devs[i].runstatus & WD_STAT_BSTOP) | ||
| 651 | cpwd_resetbrokentimer(p, i); | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | if (p->broken) | ||
| 656 | del_timer_sync(&cpwd_timer); | ||
| 657 | |||
| 658 | if (p->initialized) | ||
| 659 | free_irq(p->irq, p); | ||
| 660 | |||
| 661 | of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); | ||
| 662 | kfree(p); | ||
| 663 | |||
| 664 | cpwd_device = NULL; | ||
| 665 | |||
| 666 | return 0; | ||
| 667 | } | ||
| 668 | |||
| 669 | static const struct of_device_id cpwd_match[] = { | ||
| 670 | { | ||
| 671 | .name = "watchdog", | ||
| 672 | }, | ||
| 673 | {}, | ||
| 674 | }; | ||
| 675 | MODULE_DEVICE_TABLE(of, cpwd_match); | ||
| 676 | |||
| 677 | static struct of_platform_driver cpwd_driver = { | ||
| 678 | .name = DRIVER_NAME, | ||
| 679 | .match_table = cpwd_match, | ||
| 680 | .probe = cpwd_probe, | ||
| 681 | .remove = __devexit_p(cpwd_remove), | ||
| 682 | }; | ||
| 683 | |||
| 684 | static int __init cpwd_init(void) | ||
| 685 | { | ||
| 686 | return of_register_driver(&cpwd_driver, &of_bus_type); | ||
| 687 | } | ||
| 688 | |||
| 689 | static void __exit cpwd_exit(void) | ||
| 690 | { | ||
| 691 | of_unregister_driver(&cpwd_driver); | ||
| 692 | } | ||
| 693 | |||
| 694 | module_init(cpwd_init); | ||
| 695 | module_exit(cpwd_exit); | ||
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/watchdog/riowd.c index 88c0fc6395e1..09cb1833ea27 100644 --- a/drivers/sbus/char/riowatchdog.c +++ b/drivers/watchdog/riowd.c | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | /* $Id: riowatchdog.c,v 1.3.2.2 2002/01/23 18:48:02 davem Exp $ | 1 | /* riowd.c - driver for hw watchdog inside Super I/O of RIO |
| 2 | * riowatchdog.c - driver for hw watchdog inside Super I/O of RIO | ||
| 3 | * | 2 | * |
| 4 | * Copyright (C) 2001 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) |
| 5 | */ | 4 | */ |
| 6 | 5 | ||
| 7 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| @@ -12,14 +11,13 @@ | |||
| 12 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 13 | #include <linux/miscdevice.h> | 12 | #include <linux/miscdevice.h> |
| 14 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
| 14 | #include <linux/watchdog.h> | ||
| 15 | #include <linux/of.h> | ||
| 16 | #include <linux/of_device.h> | ||
| 15 | 17 | ||
| 16 | #include <asm/io.h> | 18 | #include <asm/io.h> |
| 17 | #include <asm/ebus.h> | ||
| 18 | #include <asm/bbc.h> | ||
| 19 | #include <asm/oplib.h> | ||
| 20 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
| 21 | 20 | ||
| 22 | #include <asm/watchdog.h> | ||
| 23 | 21 | ||
| 24 | /* RIO uses the NatSemi Super I/O power management logical device | 22 | /* RIO uses the NatSemi Super I/O power management logical device |
| 25 | * as its' watchdog. | 23 | * as its' watchdog. |
| @@ -45,74 +43,35 @@ | |||
| 45 | * The watchdog device generates no interrupts. | 43 | * The watchdog device generates no interrupts. |
| 46 | */ | 44 | */ |
| 47 | 45 | ||
| 48 | MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); | 46 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); |
| 49 | MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO"); | 47 | MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO"); |
| 50 | MODULE_SUPPORTED_DEVICE("watchdog"); | 48 | MODULE_SUPPORTED_DEVICE("watchdog"); |
| 51 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
| 52 | 50 | ||
| 53 | #define RIOWD_NAME "pmc" | 51 | #define DRIVER_NAME "riowd" |
| 54 | #define RIOWD_MINOR 215 | 52 | #define PFX DRIVER_NAME ": " |
| 55 | 53 | ||
| 56 | static DEFINE_SPINLOCK(riowd_lock); | 54 | struct riowd { |
| 55 | void __iomem *regs; | ||
| 56 | spinlock_t lock; | ||
| 57 | }; | ||
| 58 | |||
| 59 | static struct riowd *riowd_device; | ||
| 57 | 60 | ||
| 58 | static void __iomem *bbc_regs; | ||
| 59 | static void __iomem *riowd_regs; | ||
| 60 | #define WDTO_INDEX 0x05 | 61 | #define WDTO_INDEX 0x05 |
| 61 | 62 | ||
| 62 | static int riowd_timeout = 1; /* in minutes */ | 63 | static int riowd_timeout = 1; /* in minutes */ |
| 63 | module_param(riowd_timeout, int, 0); | 64 | module_param(riowd_timeout, int, 0); |
| 64 | MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes"); | 65 | MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes"); |
| 65 | 66 | ||
| 66 | #if 0 /* Currently unused. */ | 67 | static void riowd_writereg(struct riowd *p, u8 val, int index) |
| 67 | static u8 riowd_readreg(int index) | ||
| 68 | { | 68 | { |
| 69 | unsigned long flags; | 69 | unsigned long flags; |
| 70 | u8 ret; | ||
| 71 | 70 | ||
| 72 | spin_lock_irqsave(&riowd_lock, flags); | 71 | spin_lock_irqsave(&p->lock, flags); |
| 73 | writeb(index, riowd_regs + 0); | 72 | writeb(index, p->regs + 0); |
| 74 | ret = readb(riowd_regs + 1); | 73 | writeb(val, p->regs + 1); |
| 75 | spin_unlock_irqrestore(&riowd_lock, flags); | 74 | spin_unlock_irqrestore(&p->lock, flags); |
| 76 | |||
| 77 | return ret; | ||
| 78 | } | ||
| 79 | #endif | ||
| 80 | |||
| 81 | static void riowd_writereg(u8 val, int index) | ||
| 82 | { | ||
| 83 | unsigned long flags; | ||
| 84 | |||
| 85 | spin_lock_irqsave(&riowd_lock, flags); | ||
| 86 | writeb(index, riowd_regs + 0); | ||
| 87 | writeb(val, riowd_regs + 1); | ||
| 88 | spin_unlock_irqrestore(&riowd_lock, flags); | ||
| 89 | } | ||
| 90 | |||
| 91 | static void riowd_pingtimer(void) | ||
| 92 | { | ||
| 93 | riowd_writereg(riowd_timeout, WDTO_INDEX); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void riowd_stoptimer(void) | ||
| 97 | { | ||
| 98 | u8 val; | ||
| 99 | |||
| 100 | riowd_writereg(0, WDTO_INDEX); | ||
| 101 | |||
| 102 | val = readb(bbc_regs + BBC_WDACTION); | ||
| 103 | val &= ~BBC_WDACTION_RST; | ||
| 104 | writeb(val, bbc_regs + BBC_WDACTION); | ||
| 105 | } | ||
| 106 | |||
| 107 | static void riowd_starttimer(void) | ||
| 108 | { | ||
| 109 | u8 val; | ||
| 110 | |||
| 111 | riowd_writereg(riowd_timeout, WDTO_INDEX); | ||
| 112 | |||
| 113 | val = readb(bbc_regs + BBC_WDACTION); | ||
| 114 | val |= BBC_WDACTION_RST; | ||
| 115 | writeb(val, bbc_regs + BBC_WDACTION); | ||
| 116 | } | 75 | } |
| 117 | 76 | ||
| 118 | static int riowd_open(struct inode *inode, struct file *filp) | 77 | static int riowd_open(struct inode *inode, struct file *filp) |
| @@ -131,9 +90,12 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
| 131 | unsigned int cmd, unsigned long arg) | 90 | unsigned int cmd, unsigned long arg) |
| 132 | { | 91 | { |
| 133 | static struct watchdog_info info = { | 92 | static struct watchdog_info info = { |
| 134 | WDIOF_SETTIMEOUT, 0, "Natl. Semiconductor PC97317" | 93 | .options = WDIOF_SETTIMEOUT, |
| 94 | .firmware_version = 1, | ||
| 95 | .identity = DRIVER_NAME, | ||
| 135 | }; | 96 | }; |
| 136 | void __user *argp = (void __user *)arg; | 97 | void __user *argp = (void __user *)arg; |
| 98 | struct riowd *p = riowd_device; | ||
| 137 | unsigned int options; | 99 | unsigned int options; |
| 138 | int new_margin; | 100 | int new_margin; |
| 139 | 101 | ||
| @@ -150,7 +112,7 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
| 150 | break; | 112 | break; |
| 151 | 113 | ||
| 152 | case WDIOC_KEEPALIVE: | 114 | case WDIOC_KEEPALIVE: |
| 153 | riowd_pingtimer(); | 115 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
| 154 | break; | 116 | break; |
| 155 | 117 | ||
| 156 | case WDIOC_SETOPTIONS: | 118 | case WDIOC_SETOPTIONS: |
| @@ -158,9 +120,9 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
| 158 | return -EFAULT; | 120 | return -EFAULT; |
| 159 | 121 | ||
| 160 | if (options & WDIOS_DISABLECARD) | 122 | if (options & WDIOS_DISABLECARD) |
| 161 | riowd_stoptimer(); | 123 | riowd_writereg(p, 0, WDTO_INDEX); |
| 162 | else if (options & WDIOS_ENABLECARD) | 124 | else if (options & WDIOS_ENABLECARD) |
| 163 | riowd_starttimer(); | 125 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
| 164 | else | 126 | else |
| 165 | return -EINVAL; | 127 | return -EINVAL; |
| 166 | 128 | ||
| @@ -170,9 +132,9 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
| 170 | if (get_user(new_margin, (int __user *)argp)) | 132 | if (get_user(new_margin, (int __user *)argp)) |
| 171 | return -EFAULT; | 133 | return -EFAULT; |
| 172 | if ((new_margin < 60) || (new_margin > (255 * 60))) | 134 | if ((new_margin < 60) || (new_margin > (255 * 60))) |
| 173 | return -EINVAL; | 135 | return -EINVAL; |
| 174 | riowd_timeout = (new_margin + 59) / 60; | 136 | riowd_timeout = (new_margin + 59) / 60; |
| 175 | riowd_pingtimer(); | 137 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
| 176 | /* Fall */ | 138 | /* Fall */ |
| 177 | 139 | ||
| 178 | case WDIOC_GETTIMEOUT: | 140 | case WDIOC_GETTIMEOUT: |
| @@ -187,8 +149,10 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
| 187 | 149 | ||
| 188 | static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 150 | static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) |
| 189 | { | 151 | { |
| 152 | struct riowd *p = riowd_device; | ||
| 153 | |||
| 190 | if (count) { | 154 | if (count) { |
| 191 | riowd_pingtimer(); | 155 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
| 192 | return 1; | 156 | return 1; |
| 193 | } | 157 | } |
| 194 | 158 | ||
| @@ -197,99 +161,99 @@ static ssize_t riowd_write(struct file *file, const char __user *buf, size_t cou | |||
| 197 | 161 | ||
| 198 | static const struct file_operations riowd_fops = { | 162 | static const struct file_operations riowd_fops = { |
| 199 | .owner = THIS_MODULE, | 163 | .owner = THIS_MODULE, |
| 164 | .llseek = no_llseek, | ||
| 200 | .ioctl = riowd_ioctl, | 165 | .ioctl = riowd_ioctl, |
| 201 | .open = riowd_open, | 166 | .open = riowd_open, |
| 202 | .write = riowd_write, | 167 | .write = riowd_write, |
| 203 | .release = riowd_release, | 168 | .release = riowd_release, |
| 204 | }; | 169 | }; |
| 205 | 170 | ||
| 206 | static struct miscdevice riowd_miscdev = { RIOWD_MINOR, RIOWD_NAME, &riowd_fops }; | 171 | static struct miscdevice riowd_miscdev = { |
| 172 | .minor = WATCHDOG_MINOR, | ||
| 173 | .name = "watchdog", | ||
| 174 | .fops = &riowd_fops | ||
| 175 | }; | ||
| 207 | 176 | ||
| 208 | static int __init riowd_bbc_init(void) | 177 | static int __devinit riowd_probe(struct of_device *op, |
| 178 | const struct of_device_id *match) | ||
| 209 | { | 179 | { |
| 210 | struct linux_ebus *ebus = NULL; | 180 | struct riowd *p; |
| 211 | struct linux_ebus_device *edev = NULL; | 181 | int err = -EINVAL; |
| 212 | u8 val; | ||
| 213 | |||
| 214 | for_each_ebus(ebus) { | ||
| 215 | for_each_ebusdev(edev, ebus) { | ||
| 216 | if (!strcmp(edev->ofdev.node->name, "bbc")) | ||
| 217 | goto found_bbc; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | 182 | ||
| 221 | found_bbc: | 183 | if (riowd_device) |
| 222 | if (!edev) | 184 | goto out; |
| 223 | return -ENODEV; | ||
| 224 | bbc_regs = ioremap(edev->resource[0].start, BBC_REGS_SIZE); | ||
| 225 | if (!bbc_regs) | ||
| 226 | return -ENODEV; | ||
| 227 | 185 | ||
| 228 | /* Turn it off. */ | 186 | err = -ENOMEM; |
| 229 | val = readb(bbc_regs + BBC_WDACTION); | 187 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 230 | val &= ~BBC_WDACTION_RST; | 188 | if (!p) |
| 231 | writeb(val, bbc_regs + BBC_WDACTION); | 189 | goto out; |
| 232 | 190 | ||
| 233 | return 0; | 191 | spin_lock_init(&p->lock); |
| 234 | } | ||
| 235 | 192 | ||
| 236 | static int __init riowd_init(void) | 193 | p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME); |
| 237 | { | 194 | if (!p->regs) { |
| 238 | struct linux_ebus *ebus = NULL; | 195 | printk(KERN_ERR PFX "Cannot map registers.\n"); |
| 239 | struct linux_ebus_device *edev = NULL; | 196 | goto out_free; |
| 240 | |||
| 241 | for_each_ebus(ebus) { | ||
| 242 | for_each_ebusdev(edev, ebus) { | ||
| 243 | if (!strcmp(edev->ofdev.node->name, RIOWD_NAME)) | ||
| 244 | goto ebus_done; | ||
| 245 | } | ||
| 246 | } | 197 | } |
| 247 | 198 | ||
| 248 | ebus_done: | 199 | err = misc_register(&riowd_miscdev); |
| 249 | if (!edev) | 200 | if (err) { |
| 250 | goto fail; | 201 | printk(KERN_ERR PFX "Cannot register watchdog misc device.\n"); |
| 251 | 202 | goto out_iounmap; | |
| 252 | riowd_regs = ioremap(edev->resource[0].start, 2); | ||
| 253 | if (riowd_regs == NULL) { | ||
| 254 | printk(KERN_ERR "pmc: Cannot map registers.\n"); | ||
| 255 | return -ENODEV; | ||
| 256 | } | 203 | } |
| 257 | 204 | ||
| 258 | if (riowd_bbc_init()) { | 205 | printk(KERN_INFO PFX "Hardware watchdog [%i minutes], " |
| 259 | printk(KERN_ERR "pmc: Failure initializing BBC config.\n"); | 206 | "regs at %p\n", riowd_timeout, p->regs); |
| 260 | goto fail; | ||
| 261 | } | ||
| 262 | 207 | ||
| 263 | if (misc_register(&riowd_miscdev)) { | 208 | dev_set_drvdata(&op->dev, p); |
| 264 | printk(KERN_ERR "pmc: Cannot register watchdog misc device.\n"); | 209 | riowd_device = p; |
| 265 | goto fail; | 210 | err = 0; |
| 266 | } | ||
| 267 | 211 | ||
| 268 | printk(KERN_INFO "pmc: Hardware watchdog [%i minutes], " | 212 | out_iounmap: |
| 269 | "regs at %p\n", riowd_timeout, riowd_regs); | 213 | of_iounmap(&op->resource[0], p->regs, 2); |
| 270 | 214 | ||
| 271 | return 0; | 215 | out_free: |
| 216 | kfree(p); | ||
| 272 | 217 | ||
| 273 | fail: | 218 | out: |
| 274 | if (riowd_regs) { | 219 | return err; |
| 275 | iounmap(riowd_regs); | ||
| 276 | riowd_regs = NULL; | ||
| 277 | } | ||
| 278 | if (bbc_regs) { | ||
| 279 | iounmap(bbc_regs); | ||
| 280 | bbc_regs = NULL; | ||
| 281 | } | ||
| 282 | return -ENODEV; | ||
| 283 | } | 220 | } |
| 284 | 221 | ||
| 285 | static void __exit riowd_cleanup(void) | 222 | static int __devexit riowd_remove(struct of_device *op) |
| 286 | { | 223 | { |
| 224 | struct riowd *p = dev_get_drvdata(&op->dev); | ||
| 225 | |||
| 287 | misc_deregister(&riowd_miscdev); | 226 | misc_deregister(&riowd_miscdev); |
| 288 | iounmap(riowd_regs); | 227 | of_iounmap(&op->resource[0], p->regs, 2); |
| 289 | riowd_regs = NULL; | 228 | kfree(p); |
| 290 | iounmap(bbc_regs); | 229 | |
| 291 | bbc_regs = NULL; | 230 | return 0; |
| 231 | } | ||
| 232 | |||
| 233 | static const struct of_device_id riowd_match[] = { | ||
| 234 | { | ||
| 235 | .name = "pmc", | ||
| 236 | }, | ||
| 237 | {}, | ||
| 238 | }; | ||
| 239 | MODULE_DEVICE_TABLE(of, riowd_match); | ||
| 240 | |||
| 241 | static struct of_platform_driver riowd_driver = { | ||
| 242 | .name = DRIVER_NAME, | ||
| 243 | .match_table = riowd_match, | ||
| 244 | .probe = riowd_probe, | ||
| 245 | .remove = __devexit_p(riowd_remove), | ||
| 246 | }; | ||
| 247 | |||
| 248 | static int __init riowd_init(void) | ||
| 249 | { | ||
| 250 | return of_register_driver(&riowd_driver, &of_bus_type); | ||
| 251 | } | ||
| 252 | |||
| 253 | static void __exit riowd_exit(void) | ||
| 254 | { | ||
| 255 | of_unregister_driver(&riowd_driver); | ||
| 292 | } | 256 | } |
| 293 | 257 | ||
| 294 | module_init(riowd_init); | 258 | module_init(riowd_init); |
| 295 | module_exit(riowd_cleanup); | 259 | module_exit(riowd_exit); |
