diff options
| -rw-r--r-- | arch/m68k/amiga/platform.c | 63 | ||||
| -rw-r--r-- | arch/m68k/include/asm/amigayle.h | 6 | ||||
| -rw-r--r-- | drivers/ide/gayle.c | 147 |
3 files changed, 150 insertions, 66 deletions
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 027e4cae88ff..907f6f5f2cac 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/zorro.h> | 11 | #include <linux/zorro.h> |
| 12 | 12 | ||
| 13 | #include <asm/amigahw.h> | 13 | #include <asm/amigahw.h> |
| 14 | #include <asm/amigayle.h> | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | #ifdef CONFIG_ZORRO | 17 | #ifdef CONFIG_ZORRO |
| @@ -55,7 +56,24 @@ static int __init amiga_init_bus(void) | |||
| 55 | 56 | ||
| 56 | subsys_initcall(amiga_init_bus); | 57 | subsys_initcall(amiga_init_bus); |
| 57 | 58 | ||
| 58 | #endif /* CONFIG_ZORRO */ | 59 | |
| 60 | static int z_dev_present(zorro_id id) | ||
| 61 | { | ||
| 62 | unsigned int i; | ||
| 63 | |||
| 64 | for (i = 0; i < zorro_num_autocon; i++) | ||
| 65 | if (zorro_autocon[i].rom.er_Manufacturer == ZORRO_MANUF(id) && | ||
| 66 | zorro_autocon[i].rom.er_Product == ZORRO_PROD(id)) | ||
| 67 | return 1; | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | #else /* !CONFIG_ZORRO */ | ||
| 73 | |||
| 74 | static inline int z_dev_present(zorro_id id) { return 0; } | ||
| 75 | |||
| 76 | #endif /* !CONFIG_ZORRO */ | ||
| 59 | 77 | ||
| 60 | 78 | ||
| 61 | static const struct resource a3000_scsi_resource __initconst = { | 79 | static const struct resource a3000_scsi_resource __initconst = { |
| @@ -72,8 +90,36 @@ static const struct resource a4000t_scsi_resource __initconst = { | |||
| 72 | }; | 90 | }; |
| 73 | 91 | ||
| 74 | 92 | ||
| 93 | static const struct resource a1200_ide_resource __initconst = { | ||
| 94 | .start = 0xda0000, | ||
| 95 | .end = 0xda1fff, | ||
| 96 | .flags = IORESOURCE_MEM, | ||
| 97 | }; | ||
| 98 | |||
| 99 | static const struct gayle_ide_platform_data a1200_ide_pdata __initconst = { | ||
| 100 | .base = 0xda0000, | ||
| 101 | .irqport = 0xda9000, | ||
| 102 | .explicit_ack = 1, | ||
| 103 | }; | ||
| 104 | |||
| 105 | |||
| 106 | static const struct resource a4000_ide_resource __initconst = { | ||
| 107 | .start = 0xdd2000, | ||
| 108 | .end = 0xdd3fff, | ||
| 109 | .flags = IORESOURCE_MEM, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const struct gayle_ide_platform_data a4000_ide_pdata __initconst = { | ||
| 113 | .base = 0xdd2020, | ||
| 114 | .irqport = 0xdd3020, | ||
| 115 | .explicit_ack = 0, | ||
| 116 | }; | ||
| 117 | |||
| 118 | |||
| 75 | static int __init amiga_init_devices(void) | 119 | static int __init amiga_init_devices(void) |
| 76 | { | 120 | { |
| 121 | struct platform_device *pdev; | ||
| 122 | |||
| 77 | if (!MACH_IS_AMIGA) | 123 | if (!MACH_IS_AMIGA) |
| 78 | return -ENODEV; | 124 | return -ENODEV; |
| 79 | 125 | ||
| @@ -99,6 +145,21 @@ static int __init amiga_init_devices(void) | |||
| 99 | platform_device_register_simple("amiga-a4000t-scsi", -1, | 145 | platform_device_register_simple("amiga-a4000t-scsi", -1, |
| 100 | &a4000t_scsi_resource, 1); | 146 | &a4000t_scsi_resource, 1); |
| 101 | 147 | ||
| 148 | if (AMIGAHW_PRESENT(A1200_IDE) || | ||
| 149 | z_dev_present(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE)) { | ||
| 150 | pdev = platform_device_register_simple("amiga-gayle-ide", -1, | ||
| 151 | &a1200_ide_resource, 1); | ||
| 152 | platform_device_add_data(pdev, &a1200_ide_pdata, | ||
| 153 | sizeof(a1200_ide_pdata)); | ||
| 154 | } | ||
| 155 | |||
| 156 | if (AMIGAHW_PRESENT(A4000_IDE)) { | ||
| 157 | pdev = platform_device_register_simple("amiga-gayle-ide", -1, | ||
| 158 | &a4000_ide_resource, 1); | ||
| 159 | platform_device_add_data(pdev, &a4000_ide_pdata, | ||
| 160 | sizeof(a4000_ide_pdata)); | ||
| 161 | } | ||
| 162 | |||
| 102 | return 0; | 163 | return 0; |
| 103 | } | 164 | } |
| 104 | 165 | ||
diff --git a/arch/m68k/include/asm/amigayle.h b/arch/m68k/include/asm/amigayle.h index bb5a6aa329f3..a01453d9c231 100644 --- a/arch/m68k/include/asm/amigayle.h +++ b/arch/m68k/include/asm/amigayle.h | |||
| @@ -104,4 +104,10 @@ struct GAYLE { | |||
| 104 | #define GAYLE_CFG_250NS 0x00 | 104 | #define GAYLE_CFG_250NS 0x00 |
| 105 | #define GAYLE_CFG_720NS 0x0c | 105 | #define GAYLE_CFG_720NS 0x0c |
| 106 | 106 | ||
| 107 | struct gayle_ide_platform_data { | ||
| 108 | unsigned long base; | ||
| 109 | unsigned long irqport; | ||
| 110 | int explicit_ack; /* A1200 IDE needs explicit ack */ | ||
| 111 | }; | ||
| 112 | |||
| 107 | #endif /* asm-m68k/amigayle.h */ | 113 | #endif /* asm-m68k/amigayle.h */ |
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index b9e517de6a82..3feaa26410be 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/zorro.h> | 17 | #include <linux/zorro.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/platform_device.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
| 21 | #include <asm/amigahw.h> | 22 | #include <asm/amigahw.h> |
| @@ -24,15 +25,6 @@ | |||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | /* | 27 | /* |
| 27 | * Bases of the IDE interfaces | ||
| 28 | */ | ||
| 29 | |||
| 30 | #define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ | ||
| 31 | #define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */ | ||
| 32 | |||
| 33 | #define GAYLE_IDEREG_SIZE 0x2000 | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Offsets from one of the above bases | 28 | * Offsets from one of the above bases |
| 37 | */ | 29 | */ |
| 38 | 30 | ||
| @@ -68,20 +60,20 @@ MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); | |||
| 68 | 60 | ||
| 69 | static int gayle_test_irq(ide_hwif_t *hwif) | 61 | static int gayle_test_irq(ide_hwif_t *hwif) |
| 70 | { | 62 | { |
| 71 | unsigned char ch; | 63 | unsigned char ch; |
| 72 | 64 | ||
| 73 | ch = z_readb(hwif->io_ports.irq_addr); | 65 | ch = z_readb(hwif->io_ports.irq_addr); |
| 74 | if (!(ch & GAYLE_IRQ_IDE)) | 66 | if (!(ch & GAYLE_IRQ_IDE)) |
| 75 | return 0; | 67 | return 0; |
| 76 | return 1; | 68 | return 1; |
| 77 | } | 69 | } |
| 78 | 70 | ||
| 79 | static void gayle_a1200_clear_irq(ide_drive_t *drive) | 71 | static void gayle_a1200_clear_irq(ide_drive_t *drive) |
| 80 | { | 72 | { |
| 81 | ide_hwif_t *hwif = drive->hwif; | 73 | ide_hwif_t *hwif = drive->hwif; |
| 82 | 74 | ||
| 83 | (void)z_readb(hwif->io_ports.status_addr); | 75 | (void)z_readb(hwif->io_ports.status_addr); |
| 84 | z_writeb(0x7c, hwif->io_ports.irq_addr); | 76 | z_writeb(0x7c, hwif->io_ports.irq_addr); |
| 85 | } | 77 | } |
| 86 | 78 | ||
| 87 | static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, | 79 | static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, |
| @@ -122,64 +114,89 @@ static const struct ide_port_info gayle_port_info = { | |||
| 122 | * Probe for a Gayle IDE interface (and optionally for an IDE doubler) | 114 | * Probe for a Gayle IDE interface (and optionally for an IDE doubler) |
| 123 | */ | 115 | */ |
| 124 | 116 | ||
| 125 | static int __init gayle_init(void) | 117 | static int __init amiga_gayle_ide_probe(struct platform_device *pdev) |
| 126 | { | 118 | { |
| 127 | unsigned long phys_base, res_start, res_n; | 119 | struct resource *res; |
| 128 | unsigned long base, ctrlport, irqport; | 120 | struct gayle_ide_platform_data *pdata; |
| 129 | int a4000, i, rc; | 121 | unsigned long base, ctrlport, irqport; |
| 130 | struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; | 122 | unsigned int i; |
| 131 | struct ide_port_info d = gayle_port_info; | 123 | int error; |
| 132 | 124 | struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; | |
| 133 | if (!MACH_IS_AMIGA) | 125 | struct ide_port_info d = gayle_port_info; |
| 134 | return -ENODEV; | 126 | struct ide_host *host; |
| 135 | 127 | ||
| 136 | if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) | 128 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 137 | goto found; | 129 | if (!res) |
| 138 | 130 | return -ENODEV; | |
| 139 | #ifdef CONFIG_ZORRO | 131 | |
| 140 | if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, | 132 | if (!request_mem_region(res->start, resource_size(res), "IDE")) |
| 141 | NULL)) | 133 | return -EBUSY; |
| 142 | goto found; | 134 | |
| 143 | #endif | 135 | pdata = pdev->dev.platform_data; |
| 144 | return -ENODEV; | 136 | pr_info("ide: Gayle IDE controller (A%u style%s)\n", |
| 145 | 137 | pdata->explicit_ack ? 1200 : 4000, | |
| 146 | found: | 138 | ide_doubler ? ", IDE doubler" : ""); |
| 147 | printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", | 139 | |
| 148 | a4000 ? 4000 : 1200, | 140 | base = (unsigned long)ZTWO_VADDR(pdata->base); |
| 149 | ide_doubler ? ", IDE doubler" : ""); | 141 | ctrlport = 0; |
| 150 | 142 | irqport = (unsigned long)ZTWO_VADDR(pdata->irqport); | |
| 151 | if (a4000) { | 143 | if (pdata->explicit_ack) |
| 152 | phys_base = GAYLE_BASE_4000; | 144 | d.port_ops = &gayle_a1200_port_ops; |
| 153 | irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); | 145 | else |
| 154 | d.port_ops = &gayle_a4000_port_ops; | 146 | d.port_ops = &gayle_a4000_port_ops; |
| 155 | } else { | 147 | |
| 156 | phys_base = GAYLE_BASE_1200; | 148 | for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++, base += GAYLE_NEXT_PORT) { |
| 157 | irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); | 149 | if (GAYLE_HAS_CONTROL_REG) |
| 158 | d.port_ops = &gayle_a1200_port_ops; | 150 | ctrlport = base + GAYLE_CONTROL; |
| 151 | |||
| 152 | gayle_setup_ports(&hw[i], base, ctrlport, irqport); | ||
| 153 | hws[i] = &hw[i]; | ||
| 159 | } | 154 | } |
| 160 | 155 | ||
| 161 | res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); | 156 | error = ide_host_add(&d, hws, i, &host); |
| 162 | res_n = GAYLE_IDEREG_SIZE; | 157 | if (error) |
| 158 | goto out; | ||
| 163 | 159 | ||
| 164 | if (!request_mem_region(res_start, res_n, "IDE")) | 160 | platform_set_drvdata(pdev, host); |
| 165 | return -EBUSY; | 161 | return 0; |
| 166 | 162 | ||
| 167 | for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { | 163 | out: |
| 168 | base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT); | 164 | release_mem_region(res->start, resource_size(res)); |
| 169 | ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; | 165 | return error; |
| 166 | } | ||
| 167 | |||
| 168 | static int __exit amiga_gayle_ide_remove(struct platform_device *pdev) | ||
| 169 | { | ||
| 170 | struct ide_host *host = platform_get_drvdata(pdev); | ||
| 171 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 172 | |||
| 173 | ide_host_remove(host); | ||
| 174 | release_mem_region(res->start, resource_size(res)); | ||
| 175 | return 0; | ||
| 176 | } | ||
| 170 | 177 | ||
| 171 | gayle_setup_ports(&hw[i], base, ctrlport, irqport); | 178 | static struct platform_driver amiga_gayle_ide_driver = { |
| 179 | .remove = __exit_p(amiga_gayle_ide_remove), | ||
| 180 | .driver = { | ||
| 181 | .name = "amiga-gayle-ide", | ||
| 182 | .owner = THIS_MODULE, | ||
| 183 | }, | ||
| 184 | }; | ||
| 172 | 185 | ||
| 173 | hws[i] = &hw[i]; | 186 | static int __init amiga_gayle_ide_init(void) |
| 174 | } | 187 | { |
| 188 | return platform_driver_probe(&amiga_gayle_ide_driver, | ||
| 189 | amiga_gayle_ide_probe); | ||
| 190 | } | ||
| 175 | 191 | ||
| 176 | rc = ide_host_add(&d, hws, i, NULL); | 192 | module_init(amiga_gayle_ide_init); |
| 177 | if (rc) | ||
| 178 | release_mem_region(res_start, res_n); | ||
| 179 | 193 | ||
| 180 | return rc; | 194 | static void __exit amiga_gayle_ide_exit(void) |
| 195 | { | ||
| 196 | platform_driver_unregister(&amiga_gayle_ide_driver); | ||
| 181 | } | 197 | } |
| 182 | 198 | ||
| 183 | module_init(gayle_init); | 199 | module_exit(amiga_gayle_ide_exit); |
| 184 | 200 | ||
| 185 | MODULE_LICENSE("GPL"); | 201 | MODULE_LICENSE("GPL"); |
| 202 | MODULE_ALIAS("platform:amiga-gayle-ide"); | ||
