aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/sata_fsl.c111
1 files changed, 107 insertions, 4 deletions
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 0120b0d1e9a5..d6577b93bee3 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -6,7 +6,7 @@
6 * Author: Ashish Kalra <ashish.kalra@freescale.com> 6 * Author: Ashish Kalra <ashish.kalra@freescale.com>
7 * Li Yang <leoli@freescale.com> 7 * Li Yang <leoli@freescale.com>
8 * 8 *
9 * Copyright (c) 2006-2007, 2011 Freescale Semiconductor, Inc. 9 * Copyright (c) 2006-2007, 2011-2012 Freescale Semiconductor, Inc.
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify it 11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the 12 * under the terms of the GNU General Public License as published by the
@@ -26,6 +26,15 @@
26#include <asm/io.h> 26#include <asm/io.h>
27#include <linux/of_platform.h> 27#include <linux/of_platform.h>
28 28
29static unsigned int intr_coalescing_count;
30module_param(intr_coalescing_count, int, S_IRUGO);
31MODULE_PARM_DESC(intr_coalescing_count,
32 "INT coalescing count threshold (1..31)");
33
34static unsigned int intr_coalescing_ticks;
35module_param(intr_coalescing_ticks, int, S_IRUGO);
36MODULE_PARM_DESC(intr_coalescing_ticks,
37 "INT coalescing timer threshold in AHB ticks");
29/* Controller information */ 38/* Controller information */
30enum { 39enum {
31 SATA_FSL_QUEUE_DEPTH = 16, 40 SATA_FSL_QUEUE_DEPTH = 16,
@@ -83,6 +92,16 @@ enum {
83}; 92};
84 93
85/* 94/*
95 * Interrupt Coalescing Control Register bitdefs */
96enum {
97 ICC_MIN_INT_COUNT_THRESHOLD = 1,
98 ICC_MAX_INT_COUNT_THRESHOLD = ((1 << 5) - 1),
99 ICC_MIN_INT_TICKS_THRESHOLD = 0,
100 ICC_MAX_INT_TICKS_THRESHOLD = ((1 << 19) - 1),
101 ICC_SAFE_INT_TICKS = 1,
102};
103
104/*
86* Host Controller command register set - per port 105* Host Controller command register set - per port
87*/ 106*/
88enum { 107enum {
@@ -263,8 +282,65 @@ struct sata_fsl_host_priv {
263 void __iomem *csr_base; 282 void __iomem *csr_base;
264 int irq; 283 int irq;
265 int data_snoop; 284 int data_snoop;
285 struct device_attribute intr_coalescing;
266}; 286};
267 287
288static void fsl_sata_set_irq_coalescing(struct ata_host *host,
289 unsigned int count, unsigned int ticks)
290{
291 struct sata_fsl_host_priv *host_priv = host->private_data;
292 void __iomem *hcr_base = host_priv->hcr_base;
293
294 if (count > ICC_MAX_INT_COUNT_THRESHOLD)
295 count = ICC_MAX_INT_COUNT_THRESHOLD;
296 else if (count < ICC_MIN_INT_COUNT_THRESHOLD)
297 count = ICC_MIN_INT_COUNT_THRESHOLD;
298
299 if (ticks > ICC_MAX_INT_TICKS_THRESHOLD)
300 ticks = ICC_MAX_INT_TICKS_THRESHOLD;
301 else if ((ICC_MIN_INT_TICKS_THRESHOLD == ticks) &&
302 (count > ICC_MIN_INT_COUNT_THRESHOLD))
303 ticks = ICC_SAFE_INT_TICKS;
304
305 spin_lock(&host->lock);
306 iowrite32((count << 24 | ticks), hcr_base + ICC);
307
308 intr_coalescing_count = count;
309 intr_coalescing_ticks = ticks;
310 spin_unlock(&host->lock);
311
312 DPRINTK("intrrupt coalescing, count = 0x%x, ticks = %x\n",
313 intr_coalescing_count, intr_coalescing_ticks);
314 DPRINTK("ICC register status: (hcr base: 0x%x) = 0x%x\n",
315 hcr_base, ioread32(hcr_base + ICC));
316}
317
318static ssize_t fsl_sata_intr_coalescing_show(struct device *dev,
319 struct device_attribute *attr, char *buf)
320{
321 return sprintf(buf, "%d %d\n",
322 intr_coalescing_count, intr_coalescing_ticks);
323}
324
325static ssize_t fsl_sata_intr_coalescing_store(struct device *dev,
326 struct device_attribute *attr,
327 const char *buf, size_t count)
328{
329 unsigned int coalescing_count, coalescing_ticks;
330
331 if (sscanf(buf, "%d%d",
332 &coalescing_count,
333 &coalescing_ticks) != 2) {
334 printk(KERN_ERR "fsl-sata: wrong parameter format.\n");
335 return -EINVAL;
336 }
337
338 fsl_sata_set_irq_coalescing(dev_get_drvdata(dev),
339 coalescing_count, coalescing_ticks);
340
341 return strlen(buf);
342}
343
268static inline unsigned int sata_fsl_tag(unsigned int tag, 344static inline unsigned int sata_fsl_tag(unsigned int tag,
269 void __iomem *hcr_base) 345 void __iomem *hcr_base)
270{ 346{
@@ -346,10 +422,10 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
346 (unsigned long long)sg_addr, sg_len); 422 (unsigned long long)sg_addr, sg_len);
347 423
348 /* warn if each s/g element is not dword aligned */ 424 /* warn if each s/g element is not dword aligned */
349 if (sg_addr & 0x03) 425 if (unlikely(sg_addr & 0x03))
350 ata_port_err(qc->ap, "s/g addr unaligned : 0x%llx\n", 426 ata_port_err(qc->ap, "s/g addr unaligned : 0x%llx\n",
351 (unsigned long long)sg_addr); 427 (unsigned long long)sg_addr);
352 if (sg_len & 0x03) 428 if (unlikely(sg_len & 0x03))
353 ata_port_err(qc->ap, "s/g len unaligned : 0x%x\n", 429 ata_port_err(qc->ap, "s/g len unaligned : 0x%x\n",
354 sg_len); 430 sg_len);
355 431
@@ -1245,6 +1321,13 @@ static int sata_fsl_init_controller(struct ata_host *host)
1245 iowrite32(0x00000FFFF, hcr_base + CE); 1321 iowrite32(0x00000FFFF, hcr_base + CE);
1246 iowrite32(0x00000FFFF, hcr_base + DE); 1322 iowrite32(0x00000FFFF, hcr_base + DE);
1247 1323
1324 /*
1325 * reset the number of command complete bits which will cause the
1326 * interrupt to be signaled
1327 */
1328 fsl_sata_set_irq_coalescing(host, intr_coalescing_count,
1329 intr_coalescing_ticks);
1330
1248 /* 1331 /*
1249 * host controller will be brought on-line, during xx_port_start() 1332 * host controller will be brought on-line, during xx_port_start()
1250 * callback, that should also initiate the OOB, COMINIT sequence 1333 * callback, that should also initiate the OOB, COMINIT sequence
@@ -1309,7 +1392,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
1309 void __iomem *csr_base = NULL; 1392 void __iomem *csr_base = NULL;
1310 struct sata_fsl_host_priv *host_priv = NULL; 1393 struct sata_fsl_host_priv *host_priv = NULL;
1311 int irq; 1394 int irq;
1312 struct ata_host *host; 1395 struct ata_host *host = NULL;
1313 u32 temp; 1396 u32 temp;
1314 1397
1315 struct ata_port_info pi = sata_fsl_port_info[0]; 1398 struct ata_port_info pi = sata_fsl_port_info[0];
@@ -1356,6 +1439,10 @@ static int sata_fsl_probe(struct platform_device *ofdev)
1356 1439
1357 /* allocate host structure */ 1440 /* allocate host structure */
1358 host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS); 1441 host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
1442 if (!host) {
1443 retval = -ENOMEM;
1444 goto error_exit_with_cleanup;
1445 }
1359 1446
1360 /* host->iomap is not used currently */ 1447 /* host->iomap is not used currently */
1361 host->private_data = host_priv; 1448 host->private_data = host_priv;
@@ -1373,10 +1460,24 @@ static int sata_fsl_probe(struct platform_device *ofdev)
1373 1460
1374 dev_set_drvdata(&ofdev->dev, host); 1461 dev_set_drvdata(&ofdev->dev, host);
1375 1462
1463 host_priv->intr_coalescing.show = fsl_sata_intr_coalescing_show;
1464 host_priv->intr_coalescing.store = fsl_sata_intr_coalescing_store;
1465 sysfs_attr_init(&host_priv->intr_coalescing.attr);
1466 host_priv->intr_coalescing.attr.name = "intr_coalescing";
1467 host_priv->intr_coalescing.attr.mode = S_IRUGO | S_IWUSR;
1468 retval = device_create_file(host->dev, &host_priv->intr_coalescing);
1469 if (retval)
1470 goto error_exit_with_cleanup;
1471
1376 return 0; 1472 return 0;
1377 1473
1378error_exit_with_cleanup: 1474error_exit_with_cleanup:
1379 1475
1476 if (host) {
1477 dev_set_drvdata(&ofdev->dev, NULL);
1478 ata_host_detach(host);
1479 }
1480
1380 if (hcr_base) 1481 if (hcr_base)
1381 iounmap(hcr_base); 1482 iounmap(hcr_base);
1382 if (host_priv) 1483 if (host_priv)
@@ -1390,6 +1491,8 @@ static int sata_fsl_remove(struct platform_device *ofdev)
1390 struct ata_host *host = dev_get_drvdata(&ofdev->dev); 1491 struct ata_host *host = dev_get_drvdata(&ofdev->dev);
1391 struct sata_fsl_host_priv *host_priv = host->private_data; 1492 struct sata_fsl_host_priv *host_priv = host->private_data;
1392 1493
1494 device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
1495
1393 ata_host_detach(host); 1496 ata_host_detach(host);
1394 1497
1395 dev_set_drvdata(&ofdev->dev, NULL); 1498 dev_set_drvdata(&ofdev->dev, NULL);