diff options
author | Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> | 2014-03-25 14:51:40 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-03-25 15:17:13 -0400 |
commit | ae8723f8a9c8e804c2b906074d7d5f1265a385bb (patch) | |
tree | deef53af61b4e4940a20c40ed4f02e1818a63dab /drivers/ata/ahci_da850.c | |
parent | fd990556f0fa25446c6bfa9cf4c9e49d387d4472 (diff) |
ata: add new-style AHCI platform driver for DaVinci DA850 AHCI controller
Add the new ahci_da850 host driver.
Platform changes needed to make DaVinci DA850 SATA AHCI support
fully functional are in the separate "ARM: davinci: da850: update
SATA AHCI support" commit.
Please note that this driver doesn't have the superfluous clock
control code as clock is already handled by the generic AHCI
platform library code.
Cc: Sekhar Nori <nsekhar@ti.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata/ahci_da850.c')
-rw-r--r-- | drivers/ata/ahci_da850.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/ata/ahci_da850.c b/drivers/ata/ahci_da850.c new file mode 100644 index 000000000000..2c83613ce2db --- /dev/null +++ b/drivers/ata/ahci_da850.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * DaVinci DA850 AHCI SATA platform driver | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2, or (at your option) | ||
7 | * any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/pm.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/libata.h> | ||
16 | #include <linux/ahci_platform.h> | ||
17 | #include "ahci.h" | ||
18 | |||
19 | /* SATA PHY Control Register offset from AHCI base */ | ||
20 | #define SATA_P0PHYCR_REG 0x178 | ||
21 | |||
22 | #define SATA_PHY_MPY(x) ((x) << 0) | ||
23 | #define SATA_PHY_LOS(x) ((x) << 6) | ||
24 | #define SATA_PHY_RXCDR(x) ((x) << 10) | ||
25 | #define SATA_PHY_RXEQ(x) ((x) << 13) | ||
26 | #define SATA_PHY_TXSWING(x) ((x) << 19) | ||
27 | #define SATA_PHY_ENPLL(x) ((x) << 31) | ||
28 | |||
29 | /* | ||
30 | * The multiplier needed for 1.5GHz PLL output. | ||
31 | * | ||
32 | * NOTE: This is currently hardcoded to be suitable for 100MHz crystal | ||
33 | * frequency (which is used by DA850 EVM board) and may need to be changed | ||
34 | * if you would like to use this driver on some other board. | ||
35 | */ | ||
36 | #define DA850_SATA_CLK_MULTIPLIER 7 | ||
37 | |||
38 | static void da850_sata_init(struct device *dev, void __iomem *pwrdn_reg, | ||
39 | void __iomem *ahci_base) | ||
40 | { | ||
41 | unsigned int val; | ||
42 | |||
43 | /* Enable SATA clock receiver */ | ||
44 | val = readl(pwrdn_reg); | ||
45 | val &= ~BIT(0); | ||
46 | writel(val, pwrdn_reg); | ||
47 | |||
48 | val = SATA_PHY_MPY(DA850_SATA_CLK_MULTIPLIER + 1) | SATA_PHY_LOS(1) | | ||
49 | SATA_PHY_RXCDR(4) | SATA_PHY_RXEQ(1) | SATA_PHY_TXSWING(3) | | ||
50 | SATA_PHY_ENPLL(1); | ||
51 | |||
52 | writel(val, ahci_base + SATA_P0PHYCR_REG); | ||
53 | } | ||
54 | |||
55 | static const struct ata_port_info ahci_da850_port_info = { | ||
56 | .flags = AHCI_FLAG_COMMON, | ||
57 | .pio_mask = ATA_PIO4, | ||
58 | .udma_mask = ATA_UDMA6, | ||
59 | .port_ops = &ahci_platform_ops, | ||
60 | }; | ||
61 | |||
62 | static int ahci_da850_probe(struct platform_device *pdev) | ||
63 | { | ||
64 | struct device *dev = &pdev->dev; | ||
65 | struct ahci_host_priv *hpriv; | ||
66 | struct resource *res; | ||
67 | void __iomem *pwrdn_reg; | ||
68 | int rc; | ||
69 | |||
70 | hpriv = ahci_platform_get_resources(pdev); | ||
71 | if (IS_ERR(hpriv)) | ||
72 | return PTR_ERR(hpriv); | ||
73 | |||
74 | rc = ahci_platform_enable_resources(hpriv); | ||
75 | if (rc) | ||
76 | return rc; | ||
77 | |||
78 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
79 | if (!res) | ||
80 | goto disable_resources; | ||
81 | |||
82 | pwrdn_reg = devm_ioremap(dev, res->start, resource_size(res)); | ||
83 | if (!pwrdn_reg) | ||
84 | goto disable_resources; | ||
85 | |||
86 | da850_sata_init(dev, pwrdn_reg, hpriv->mmio); | ||
87 | |||
88 | rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, 0, 0); | ||
89 | if (rc) | ||
90 | goto disable_resources; | ||
91 | |||
92 | return 0; | ||
93 | disable_resources: | ||
94 | ahci_platform_disable_resources(hpriv); | ||
95 | return rc; | ||
96 | } | ||
97 | |||
98 | static SIMPLE_DEV_PM_OPS(ahci_da850_pm_ops, ahci_platform_suspend, | ||
99 | ahci_platform_resume); | ||
100 | |||
101 | static struct platform_driver ahci_da850_driver = { | ||
102 | .probe = ahci_da850_probe, | ||
103 | .remove = ata_platform_remove_one, | ||
104 | .driver = { | ||
105 | .name = "ahci_da850", | ||
106 | .owner = THIS_MODULE, | ||
107 | .pm = &ahci_da850_pm_ops, | ||
108 | }, | ||
109 | }; | ||
110 | module_platform_driver(ahci_da850_driver); | ||
111 | |||
112 | MODULE_DESCRIPTION("DaVinci DA850 AHCI SATA platform driver"); | ||
113 | MODULE_AUTHOR("Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>"); | ||
114 | MODULE_LICENSE("GPL"); | ||