Blame view
drivers/ide/atiixp.c
5.6 KB
09c434b8a
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1da177e4c
|
2 |
/* |
1da177e4c
|
3 |
* Copyright (C) 2003 ATI Inc. <hyu@ati.com> |
485efc6cf
|
4 |
* Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz |
1da177e4c
|
5 |
*/ |
1da177e4c
|
6 7 8 |
#include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> |
1da177e4c
|
9 |
#include <linux/pci.h> |
1da177e4c
|
10 |
#include <linux/ide.h> |
1da177e4c
|
11 |
#include <linux/init.h> |
ced3ec8aa
|
12 |
#define DRV_NAME "atiixp" |
1da177e4c
|
13 14 15 16 17 18 |
#define ATIIXP_IDE_PIO_TIMING 0x40 #define ATIIXP_IDE_MDMA_TIMING 0x44 #define ATIIXP_IDE_PIO_CONTROL 0x48 #define ATIIXP_IDE_PIO_MODE 0x4a #define ATIIXP_IDE_UDMA_CONTROL 0x54 #define ATIIXP_IDE_UDMA_MODE 0x56 |
7546e52b5
|
19 |
struct atiixp_ide_timing { |
1da177e4c
|
20 21 |
u8 command_width; u8 recover_width; |
7546e52b5
|
22 |
}; |
1da177e4c
|
23 |
|
7546e52b5
|
24 |
static struct atiixp_ide_timing pio_timing[] = { |
1da177e4c
|
25 26 27 28 29 30 |
{ 0x05, 0x0d }, { 0x04, 0x07 }, { 0x03, 0x04 }, { 0x02, 0x02 }, { 0x02, 0x00 }, }; |
7546e52b5
|
31 |
static struct atiixp_ide_timing mdma_timing[] = { |
1da177e4c
|
32 33 34 35 |
{ 0x07, 0x07 }, { 0x02, 0x01 }, { 0x02, 0x00 }, }; |
6c5f8cc33
|
36 |
static DEFINE_SPINLOCK(atiixp_lock); |
1da177e4c
|
37 |
/** |
88b2b32ba
|
38 |
* atiixp_set_pio_mode - set host controller for PIO mode |
e085b3cae
|
39 |
* @hwif: port |
88b2b32ba
|
40 |
* @drive: drive |
1da177e4c
|
41 42 43 |
* * Set the interface PIO mode. */ |
e085b3cae
|
44 |
static void atiixp_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) |
1da177e4c
|
45 |
{ |
e085b3cae
|
46 |
struct pci_dev *dev = to_pci_dev(hwif->dev); |
1da177e4c
|
47 |
unsigned long flags; |
f76bee16f
|
48 |
int timing_shift = (drive->dn ^ 1) * 8; |
1da177e4c
|
49 50 |
u32 pio_timing_data; u16 pio_mode_data; |
e085b3cae
|
51 |
const u8 pio = drive->pio_mode - XFER_PIO_0; |
1da177e4c
|
52 |
|
6c5f8cc33
|
53 |
spin_lock_irqsave(&atiixp_lock, flags); |
1da177e4c
|
54 55 56 57 58 59 60 61 62 63 64 |
pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data); pio_mode_data &= ~(0x07 << (drive->dn * 4)); pio_mode_data |= (pio << (drive->dn * 4)); pci_write_config_word(dev, ATIIXP_IDE_PIO_MODE, pio_mode_data); pci_read_config_dword(dev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data); pio_timing_data &= ~(0xff << timing_shift); pio_timing_data |= (pio_timing[pio].recover_width << timing_shift) | (pio_timing[pio].command_width << (timing_shift + 4)); pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data); |
6c5f8cc33
|
65 |
spin_unlock_irqrestore(&atiixp_lock, flags); |
1da177e4c
|
66 67 68 |
} /** |
88b2b32ba
|
69 |
* atiixp_set_dma_mode - set host controller for DMA mode |
8776168ca
|
70 |
* @hwif: port |
88b2b32ba
|
71 |
* @drive: drive |
1da177e4c
|
72 |
* |
88b2b32ba
|
73 74 |
* Set a ATIIXP host controller to the desired DMA mode. This involves * programming the right timing data into the PCI configuration space. |
1da177e4c
|
75 |
*/ |
8776168ca
|
76 |
static void atiixp_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) |
1da177e4c
|
77 |
{ |
8776168ca
|
78 |
struct pci_dev *dev = to_pci_dev(hwif->dev); |
1da177e4c
|
79 |
unsigned long flags; |
f76bee16f
|
80 |
int timing_shift = (drive->dn ^ 1) * 8; |
1da177e4c
|
81 82 |
u32 tmp32; u16 tmp16; |
8ae60e34d
|
83 |
u16 udma_ctl = 0; |
8776168ca
|
84 |
const u8 speed = drive->dma_mode; |
94c7fa0fc
|
85 |
|
6c5f8cc33
|
86 |
spin_lock_irqsave(&atiixp_lock, flags); |
1da177e4c
|
87 |
|
8ae60e34d
|
88 |
pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl); |
1da177e4c
|
89 90 91 92 93 |
if (speed >= XFER_UDMA_0) { pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16); tmp16 &= ~(0x07 << (drive->dn * 4)); tmp16 |= ((speed & 0x07) << (drive->dn * 4)); pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16); |
8ae60e34d
|
94 95 96 97 98 99 100 101 102 103 104 105 |
udma_ctl |= (1 << drive->dn); } else if (speed >= XFER_MW_DMA_0) { u8 i = speed & 0x03; pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32); tmp32 &= ~(0xff << timing_shift); tmp32 |= (mdma_timing[i].recover_width << timing_shift) | (mdma_timing[i].command_width << (timing_shift + 4)); pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32); udma_ctl &= ~(1 << drive->dn); |
1da177e4c
|
106 |
} |
8ae60e34d
|
107 |
pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl); |
6c5f8cc33
|
108 |
spin_unlock_irqrestore(&atiixp_lock, flags); |
1da177e4c
|
109 |
} |
f454cbe8c
|
110 |
static u8 atiixp_cable_detect(ide_hwif_t *hwif) |
b4d1c73dc
|
111 112 113 114 115 116 117 118 119 120 121 |
{ struct pci_dev *pdev = to_pci_dev(hwif->dev); u8 udma_mode = 0, ch = hwif->channel; pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode); if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40) return ATA_CBL_PATA80; else return ATA_CBL_PATA40; } |
ac95beedf
|
122 123 124 125 126 |
static const struct ide_port_ops atiixp_port_ops = { .set_pio_mode = atiixp_set_pio_mode, .set_dma_mode = atiixp_set_dma_mode, .cable_detect = atiixp_cable_detect, }; |
1da177e4c
|
127 |
|
fe31edc8a
|
128 |
static const struct ide_port_info atiixp_pci_info[] = { |
ced3ec8aa
|
129 130 |
{ /* 0: IXP200/300/400/700 */ .name = DRV_NAME, |
1da177e4c
|
131 |
.enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, |
ac95beedf
|
132 |
.port_ops = &atiixp_port_ops, |
4099d1432
|
133 |
.pio_mask = ATA_PIO4, |
5f8b6c348
|
134 135 |
.mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, |
ced3ec8aa
|
136 137 138 |
}, { /* 1: IXP600 */ .name = DRV_NAME, |
b25168dfd
|
139 |
.enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, |
ac95beedf
|
140 |
.port_ops = &atiixp_port_ops, |
2467922a5
|
141 |
.host_flags = IDE_HFLAG_SINGLE, |
4099d1432
|
142 |
.pio_mask = ATA_PIO4, |
5f8b6c348
|
143 144 |
.mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, |
b25168dfd
|
145 |
}, |
1da177e4c
|
146 147 148 149 150 151 152 153 154 155 |
}; /** * atiixp_init_one - called when a ATIIXP is found * @dev: the atiixp device * @id: the matching pci id * * Called when the PCI registration layer (or the IDE initialization) * finds a device matching our IDE device tables. */ |
fe31edc8a
|
156 |
static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) |
1da177e4c
|
157 |
{ |
6cdf6eb35
|
158 |
return ide_pci_init_one(dev, &atiixp_pci_info[id->driver_data], NULL); |
1da177e4c
|
159 |
} |
9cbcc5e3c
|
160 161 162 163 164 165 |
static const struct pci_device_id atiixp_pci_tbl[] = { { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP200_IDE), 0 }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), 0 }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 }, |
5deab5366
|
166 |
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), 0 }, |
1da177e4c
|
167 168 169 |
{ 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); |
a9ab09e26
|
170 |
static struct pci_driver atiixp_pci_driver = { |
1da177e4c
|
171 172 173 |
.name = "ATIIXP_IDE", .id_table = atiixp_pci_tbl, .probe = atiixp_init_one, |
f354fbc4b
|
174 |
.remove = ide_pci_remove, |
feb22b7f8
|
175 176 |
.suspend = ide_pci_suspend, .resume = ide_pci_resume, |
1da177e4c
|
177 |
}; |
82ab1eece
|
178 |
static int __init atiixp_ide_init(void) |
1da177e4c
|
179 |
{ |
a9ab09e26
|
180 |
return ide_pci_register_driver(&atiixp_pci_driver); |
1da177e4c
|
181 |
} |
f354fbc4b
|
182 183 |
static void __exit atiixp_ide_exit(void) { |
a9ab09e26
|
184 |
pci_unregister_driver(&atiixp_pci_driver); |
f354fbc4b
|
185 |
} |
1da177e4c
|
186 |
module_init(atiixp_ide_init); |
f354fbc4b
|
187 |
module_exit(atiixp_ide_exit); |
1da177e4c
|
188 189 190 191 |
MODULE_AUTHOR("HUI YU"); MODULE_DESCRIPTION("PCI driver module for ATI IXP IDE"); MODULE_LICENSE("GPL"); |