Linux-libre 5.7.3-gnu
[librecmc/linux-libre.git] / drivers / ide / cs5536.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * CS5536 PATA support
4  * (C) 2007 Martin K. Petersen <mkp@mkp.net>
5  * (C) 2009 Bartlomiej Zolnierkiewicz
6  *
7  * Documentation:
8  *      Available from AMD web site.
9  *
10  * The IDE timing registers for the CS5536 live in the Geode Machine
11  * Specific Register file and not PCI config space.  Most BIOSes
12  * virtualize the PCI registers so the chip looks like a standard IDE
13  * controller.  Unfortunately not all implementations get this right.
14  * In particular some have problems with unaligned accesses to the
15  * virtualized PCI registers.  This driver always does full dword
16  * writes to work around the issue.  Also, in case of a bad BIOS this
17  * driver can be loaded with the "msr=1" parameter which forces using
18  * the Machine Specific Registers to configure the device.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/pci.h>
24 #include <linux/init.h>
25 #include <linux/ide.h>
26 #include <asm/msr.h>
27
28 #define DRV_NAME        "cs5536"
29
30 enum {
31         MSR_IDE_CFG             = 0x51300010,
32         PCI_IDE_CFG             = 0x40,
33
34         CFG                     = 0,
35         DTC                     = 2,
36         CAST                    = 3,
37         ETC                     = 4,
38
39         IDE_CFG_CHANEN          = (1 << 1),
40         IDE_CFG_CABLE           = (1 << 17) | (1 << 16),
41
42         IDE_D0_SHIFT            = 24,
43         IDE_D1_SHIFT            = 16,
44         IDE_DRV_MASK            = 0xff,
45
46         IDE_CAST_D0_SHIFT       = 6,
47         IDE_CAST_D1_SHIFT       = 4,
48         IDE_CAST_DRV_MASK       = 0x3,
49
50         IDE_CAST_CMD_SHIFT      = 24,
51         IDE_CAST_CMD_MASK       = 0xff,
52
53         IDE_ETC_UDMA_MASK       = 0xc0,
54 };
55
56 static int use_msr;
57
58 static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
59 {
60         if (unlikely(use_msr)) {
61                 u32 dummy;
62
63                 rdmsr(MSR_IDE_CFG + reg, *val, dummy);
64                 return 0;
65         }
66
67         return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
68 }
69
70 static int cs5536_write(struct pci_dev *pdev, int reg, int val)
71 {
72         if (unlikely(use_msr)) {
73                 wrmsr(MSR_IDE_CFG + reg, val, 0);
74                 return 0;
75         }
76
77         return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
78 }
79
80 static void cs5536_program_dtc(ide_drive_t *drive, u8 tim)
81 {
82         struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
83         int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
84         u32 dtc;
85
86         cs5536_read(pdev, DTC, &dtc);
87         dtc &= ~(IDE_DRV_MASK << dshift);
88         dtc |= tim << dshift;
89         cs5536_write(pdev, DTC, dtc);
90 }
91
92 /**
93  *      cs5536_cable_detect     -       detect cable type
94  *      @hwif: Port to detect on
95  *
96  *      Perform cable detection for ATA66 capable cable.
97  *
98  *      Returns a cable type.
99  */
100
101 static u8 cs5536_cable_detect(ide_hwif_t *hwif)
102 {
103         struct pci_dev *pdev = to_pci_dev(hwif->dev);
104         u32 cfg;
105
106         cs5536_read(pdev, CFG, &cfg);
107
108         if (cfg & IDE_CFG_CABLE)
109                 return ATA_CBL_PATA80;
110         else
111                 return ATA_CBL_PATA40;
112 }
113
114 /**
115  *      cs5536_set_pio_mode             -       PIO timing setup
116  *      @hwif: ATA port
117  *      @drive: ATA device
118  */
119
120 static void cs5536_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
121 {
122         static const u8 drv_timings[5] = {
123                 0x98, 0x55, 0x32, 0x21, 0x20,
124         };
125
126         static const u8 addr_timings[5] = {
127                 0x2, 0x1, 0x0, 0x0, 0x0,
128         };
129
130         static const u8 cmd_timings[5] = {
131                 0x99, 0x92, 0x90, 0x22, 0x20,
132         };
133
134         struct pci_dev *pdev = to_pci_dev(hwif->dev);
135         ide_drive_t *pair = ide_get_pair_dev(drive);
136         int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
137         unsigned long timings = (unsigned long)ide_get_drivedata(drive);
138         u32 cast;
139         const u8 pio = drive->pio_mode - XFER_PIO_0;
140         u8 cmd_pio = pio;
141
142         if (pair)
143                 cmd_pio = min_t(u8, pio, pair->pio_mode - XFER_PIO_0);
144
145         timings &= (IDE_DRV_MASK << 8);
146         timings |= drv_timings[pio];
147         ide_set_drivedata(drive, (void *)timings);
148
149         cs5536_program_dtc(drive, drv_timings[pio]);
150
151         cs5536_read(pdev, CAST, &cast);
152
153         cast &= ~(IDE_CAST_DRV_MASK << cshift);
154         cast |= addr_timings[pio] << cshift;
155
156         cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
157         cast |= cmd_timings[cmd_pio] << IDE_CAST_CMD_SHIFT;
158
159         cs5536_write(pdev, CAST, cast);
160 }
161
162 /**
163  *      cs5536_set_dma_mode             -       DMA timing setup
164  *      @hwif: ATA port
165  *      @drive: ATA device
166  */
167
168 static void cs5536_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
169 {
170         static const u8 udma_timings[6] = {
171                 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
172         };
173
174         static const u8 mwdma_timings[3] = {
175                 0x67, 0x21, 0x20,
176         };
177
178         struct pci_dev *pdev = to_pci_dev(hwif->dev);
179         int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
180         unsigned long timings = (unsigned long)ide_get_drivedata(drive);
181         u32 etc;
182         const u8 mode = drive->dma_mode;
183
184         cs5536_read(pdev, ETC, &etc);
185
186         if (mode >= XFER_UDMA_0) {
187                 etc &= ~(IDE_DRV_MASK << dshift);
188                 etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
189         } else { /* MWDMA */
190                 etc &= ~(IDE_ETC_UDMA_MASK << dshift);
191                 timings &= IDE_DRV_MASK;
192                 timings |= mwdma_timings[mode - XFER_MW_DMA_0] << 8;
193                 ide_set_drivedata(drive, (void *)timings);
194         }
195
196         cs5536_write(pdev, ETC, etc);
197 }
198
199 static void cs5536_dma_start(ide_drive_t *drive)
200 {
201         unsigned long timings = (unsigned long)ide_get_drivedata(drive);
202
203         if (drive->current_speed < XFER_UDMA_0 &&
204             (timings >> 8) != (timings & IDE_DRV_MASK))
205                 cs5536_program_dtc(drive, timings >> 8);
206
207         ide_dma_start(drive);
208 }
209
210 static int cs5536_dma_end(ide_drive_t *drive)
211 {
212         int ret = ide_dma_end(drive);
213         unsigned long timings = (unsigned long)ide_get_drivedata(drive);
214
215         if (drive->current_speed < XFER_UDMA_0 &&
216             (timings >> 8) != (timings & IDE_DRV_MASK))
217                 cs5536_program_dtc(drive, timings & IDE_DRV_MASK);
218
219         return ret;
220 }
221
222 static const struct ide_port_ops cs5536_port_ops = {
223         .set_pio_mode           = cs5536_set_pio_mode,
224         .set_dma_mode           = cs5536_set_dma_mode,
225         .cable_detect           = cs5536_cable_detect,
226 };
227
228 static const struct ide_dma_ops cs5536_dma_ops = {
229         .dma_host_set           = ide_dma_host_set,
230         .dma_setup              = ide_dma_setup,
231         .dma_start              = cs5536_dma_start,
232         .dma_end                = cs5536_dma_end,
233         .dma_test_irq           = ide_dma_test_irq,
234         .dma_lost_irq           = ide_dma_lost_irq,
235         .dma_timer_expiry       = ide_dma_sff_timer_expiry,
236         .dma_sff_read_status    = ide_dma_sff_read_status,
237 };
238
239 static const struct ide_port_info cs5536_info = {
240         .name           = DRV_NAME,
241         .port_ops       = &cs5536_port_ops,
242         .dma_ops        = &cs5536_dma_ops,
243         .host_flags     = IDE_HFLAG_SINGLE,
244         .pio_mask       = ATA_PIO4,
245         .mwdma_mask     = ATA_MWDMA2,
246         .udma_mask      = ATA_UDMA5,
247 };
248
249 /**
250  *      cs5536_init_one
251  *      @dev: PCI device
252  *      @id: Entry in match table
253  */
254
255 static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
256 {
257         u32 cfg;
258
259         if (use_msr)
260                 printk(KERN_INFO DRV_NAME ": Using MSR regs instead of PCI\n");
261
262         cs5536_read(dev, CFG, &cfg);
263
264         if ((cfg & IDE_CFG_CHANEN) == 0) {
265                 printk(KERN_ERR DRV_NAME ": disabled by BIOS\n");
266                 return -ENODEV;
267         }
268
269         return ide_pci_init_one(dev, &cs5536_info, NULL);
270 }
271
272 static const struct pci_device_id cs5536_pci_tbl[] = {
273         { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), },
274         { },
275 };
276
277 static struct pci_driver cs5536_pci_driver = {
278         .name           = DRV_NAME,
279         .id_table       = cs5536_pci_tbl,
280         .probe          = cs5536_init_one,
281         .remove         = ide_pci_remove,
282         .suspend        = ide_pci_suspend,
283         .resume         = ide_pci_resume,
284 };
285
286 module_pci_driver(cs5536_pci_driver);
287
288 MODULE_AUTHOR("Martin K. Petersen, Bartlomiej Zolnierkiewicz");
289 MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
290 MODULE_LICENSE("GPL");
291 MODULE_DEVICE_TABLE(pci, cs5536_pci_tbl);
292
293 module_param_named(msr, use_msr, int, 0644);
294 MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");