diff options
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); |