]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.drivers/libata-sata_via-fix-support-for-5287
Disable build of xen kernel.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / libata-sata_via-fix-support-for-5287
1 From b9d5b89b487517cbd4cb4702da829e07ef9e4432 Mon Sep 17 00:00:00 2001
2 From: Tejun Heo <tj@kernel.org>
3 Date: Wed, 22 Oct 2008 00:46:36 +0900
4 Subject: [PATCH] sata_via: fix support for 5287
5 References: bnc#441718
6
7 5287 used to be treated as vt6420 but it didn't work. It's new family
8 of controllers called vt8251 which hosts four SATA ports as M/S of the
9 two ATA ports. This configuration is rather peculiar in that although
10 the M/S devices are on the same port, each have its own SCR (or
11 equivalent link status/control) registers which screws up the
12 port-link-device hierarchy assumed by libata. Another controller
13 which falls into this category is ata_piix w/ SIDPR access.
14
15 libata now has facility to deal with this class of controllers named
16 slave_link. A low level driver for such controllers can just call
17 ata_slave_link_init() on the respective ports and libata will handle
18 all the difficult parts like following up with single SRST after
19 hardresetting both ports.
20
21 This patch creates new controller class vt8251, implements slave_link
22 aware init sequence and config space based SCR access for it and moves
23 5287 to the new class.
24
25 This patch is based on Joseph Chan's larger patch which was created
26 before slave_link was implemented in libata.
27
28 http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640
29
30 Signed-off-by: Tejun Heo <tj@kernel.org>
31 Cc: Joseph Chan <JosephChan@via.com.tw>
32 Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
33 Signed-off-by: Tejun Heo <teheo@suse.de>
34 ---
35 drivers/ata/sata_via.c | 155 ++++++++++++++++++++++++++++++++++++++++++++----
36 1 files changed, 143 insertions(+), 12 deletions(-)
37
38 diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
39 index 5b72e73..62367fe 100644
40 --- a/drivers/ata/sata_via.c
41 +++ b/drivers/ata/sata_via.c
42 @@ -44,11 +44,16 @@
43 #include <linux/libata.h>
44
45 #define DRV_NAME "sata_via"
46 -#define DRV_VERSION "2.3"
47 +#define DRV_VERSION "2.4"
48
49 +/*
50 + * vt8251 is different from other sata controllers of VIA. It has two
51 + * channels, each channel has both Master and Slave slot.
52 + */
53 enum board_ids_enum {
54 vt6420,
55 vt6421,
56 + vt8251,
57 };
58
59 enum {
60 @@ -70,6 +75,8 @@ enum {
61 static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
62 static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
63 static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
64 +static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val);
65 +static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val);
66 static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf);
67 static void svia_noop_freeze(struct ata_port *ap);
68 static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
69 @@ -79,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
70
71 static const struct pci_device_id svia_pci_tbl[] = {
72 { PCI_VDEVICE(VIA, 0x5337), vt6420 },
73 - { PCI_VDEVICE(VIA, 0x0591), vt6420 },
74 - { PCI_VDEVICE(VIA, 0x3149), vt6420 },
75 - { PCI_VDEVICE(VIA, 0x3249), vt6421 },
76 - { PCI_VDEVICE(VIA, 0x5287), vt6420 },
77 + { PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */
78 + { PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */
79 + { PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */
80 { PCI_VDEVICE(VIA, 0x5372), vt6420 },
81 { PCI_VDEVICE(VIA, 0x7372), vt6420 },
82 + { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
83
84 { } /* terminate list */
85 };
86 @@ -128,6 +135,13 @@ static struct ata_port_operations vt6421_sata_ops = {
87 .scr_write = svia_scr_write,
88 };
89
90 +static struct ata_port_operations vt8251_ops = {
91 + .inherits = &svia_base_ops,
92 + .hardreset = sata_std_hardreset,
93 + .scr_read = vt8251_scr_read,
94 + .scr_write = vt8251_scr_write,
95 +};
96 +
97 static const struct ata_port_info vt6420_port_info = {
98 .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
99 .pio_mask = 0x1f,
100 @@ -152,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = {
101 .port_ops = &vt6421_pata_ops,
102 };
103
104 +static struct ata_port_info vt8251_port_info = {
105 + .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
106 + ATA_FLAG_NO_LEGACY,
107 + .pio_mask = 0x1f,
108 + .mwdma_mask = 0x07,
109 + .udma_mask = ATA_UDMA6,
110 + .port_ops = &vt8251_ops,
111 +};
112 +
113 MODULE_AUTHOR("Jeff Garzik");
114 MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
115 MODULE_LICENSE("GPL");
116 @@ -174,6 +197,83 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
117 return 0;
118 }
119
120 +static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
121 +{
122 + static const u8 ipm_tbl[] = { 1, 2, 6, 0 };
123 + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
124 + int slot = 2 * link->ap->port_no + link->pmp;
125 + u32 v = 0;
126 + u8 raw;
127 +
128 + switch (scr) {
129 + case SCR_STATUS:
130 + pci_read_config_byte(pdev, 0xA0 + slot, &raw);
131 +
132 + /* read the DET field, bit0 and 1 of the config byte */
133 + v |= raw & 0x03;
134 +
135 + /* read the SPD field, bit4 of the configure byte */
136 + if (raw & (1 << 4))
137 + v |= 0x02 << 4;
138 + else
139 + v |= 0x01 << 4;
140 +
141 + /* read the IPM field, bit2 and 3 of the config byte */
142 + v |= ipm_tbl[(raw >> 2) & 0x3];
143 + break;
144 +
145 + case SCR_ERROR:
146 + /* devices other than 5287 uses 0xA8 as base */
147 + WARN_ON(pdev->device != 0x5287);
148 + pci_read_config_dword(pdev, 0xB0 + slot * 4, &v);
149 + break;
150 +
151 + case SCR_CONTROL:
152 + pci_read_config_byte(pdev, 0xA4 + slot, &raw);
153 +
154 + /* read the DET field, bit0 and bit1 */
155 + v |= ((raw & 0x02) << 1) | (raw & 0x01);
156 +
157 + /* read the IPM field, bit2 and bit3 */
158 + v |= ((raw >> 2) & 0x03) << 8;
159 + break;
160 +
161 + default:
162 + return -EINVAL;
163 + }
164 +
165 + *val = v;
166 + return 0;
167 +}
168 +
169 +static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val)
170 +{
171 + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
172 + int slot = 2 * link->ap->port_no + link->pmp;
173 + u32 v = 0;
174 +
175 + switch (scr) {
176 + case SCR_ERROR:
177 + /* devices other than 5287 uses 0xA8 as base */
178 + WARN_ON(pdev->device != 0x5287);
179 + pci_write_config_dword(pdev, 0xB0 + slot * 4, val);
180 + return 0;
181 +
182 + case SCR_CONTROL:
183 + /* set the DET field */
184 + v |= ((val & 0x4) >> 1) | (val & 0x1);
185 +
186 + /* set the IPM field */
187 + v |= ((val >> 8) & 0x3) << 2;
188 +
189 + pci_write_config_byte(pdev, 0xA4 + slot, v);
190 + return 0;
191 +
192 + default:
193 + return -EINVAL;
194 + }
195 +}
196 +
197 /**
198 * svia_tf_load - send taskfile registers to host controller
199 * @ap: Port to which output is sent
200 @@ -396,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
201 return 0;
202 }
203
204 +static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
205 +{
206 + const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL };
207 + struct ata_host *host;
208 + int i, rc;
209 +
210 + rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
211 + if (rc)
212 + return rc;
213 + *r_host = host;
214 +
215 + rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME);
216 + if (rc) {
217 + dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n");
218 + return rc;
219 + }
220 +
221 + /* 8251 hosts four sata ports as M/S of the two channels */
222 + for (i = 0; i < host->n_ports; i++)
223 + ata_slave_link_init(host->ports[i]);
224 +
225 + return 0;
226 +}
227 +
228 static void svia_configure(struct pci_dev *pdev)
229 {
230 u8 tmp8;
231 @@ -451,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
232 if (rc)
233 return rc;
234
235 - if (board_id == vt6420)
236 - bar_sizes = &svia_bar_sizes[0];
237 - else
238 + if (board_id == vt6421)
239 bar_sizes = &vt6421_bar_sizes[0];
240 + else
241 + bar_sizes = &svia_bar_sizes[0];
242
243 for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
244 if ((pci_resource_start(pdev, i) == 0) ||
245 @@ -467,12 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
246 return -ENODEV;
247 }
248
249 - if (board_id == vt6420)
250 + switch (board_id) {
251 + case vt6420:
252 rc = vt6420_prepare_host(pdev, &host);
253 - else
254 + break;
255 + case vt6421:
256 rc = vt6421_prepare_host(pdev, &host);
257 - if (rc)
258 - return rc;
259 + break;
260 + case vt8251:
261 + rc = vt8251_prepare_host(pdev, &host);
262 + break;
263 + default:
264 + return -EINVAL;
265 + }
266
267 svia_configure(pdev);
268
269 --
270 1.5.4.5
271