-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ata: ahci_mvebu: new driver for Marvell Armada 380 AHCI interfaces
The Marvell Armada 380 SoC includes two AHCI compatible interfaces. However, like all DMA-capable Marvell interface, they require special handling to configure MBus windows. Therefore, this commit adds a new ahci_mvebu driver, which relies on the libahci_platform.c code recently introduced. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Acked-by: Jason Cooper <jason@lakedaemon.net> Signed-off-by: Tejun Heo <tj@kernel.org>
- Loading branch information
Thomas Petazzoni
authored and
Tejun Heo
committed
May 4, 2014
1 parent
5799d6d
commit a3464ed
Showing
4 changed files
with
138 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
/* | ||
* AHCI glue platform driver for Marvell EBU SOCs | ||
* | ||
* Copyright (C) 2014 Marvell | ||
* | ||
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
* Marcin Wojtas <mw@semihalf.com> | ||
* | ||
* This file is licensed under the terms of the GNU General Public | ||
* License version 2. This program is licensed "as is" without any | ||
* warranty of any kind, whether express or implied. | ||
*/ | ||
|
||
#include <linux/ahci_platform.h> | ||
#include <linux/kernel.h> | ||
#include <linux/mbus.h> | ||
#include <linux/module.h> | ||
#include <linux/of_device.h> | ||
#include <linux/platform_device.h> | ||
#include "ahci.h" | ||
|
||
#define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 | ||
#define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 | ||
|
||
#define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4)) | ||
#define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4)) | ||
#define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4)) | ||
|
||
static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv, | ||
const struct mbus_dram_target_info *dram) | ||
{ | ||
int i; | ||
|
||
for (i = 0; i < 4; i++) { | ||
writel(0, hpriv->mmio + AHCI_WINDOW_CTRL(i)); | ||
writel(0, hpriv->mmio + AHCI_WINDOW_BASE(i)); | ||
writel(0, hpriv->mmio + AHCI_WINDOW_SIZE(i)); | ||
} | ||
|
||
for (i = 0; i < dram->num_cs; i++) { | ||
const struct mbus_dram_window *cs = dram->cs + i; | ||
|
||
writel((cs->mbus_attr << 8) | | ||
(dram->mbus_dram_target_id << 4) | 1, | ||
hpriv->mmio + AHCI_WINDOW_CTRL(i)); | ||
writel(cs->base, hpriv->mmio + AHCI_WINDOW_BASE(i)); | ||
writel(((cs->size - 1) & 0xffff0000), | ||
hpriv->mmio + AHCI_WINDOW_SIZE(i)); | ||
} | ||
} | ||
|
||
static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv) | ||
{ | ||
/* | ||
* Enable the regret bit to allow the SATA unit to regret a | ||
* request that didn't receive an acknowlegde and avoid a | ||
* deadlock | ||
*/ | ||
writel(0x4, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR); | ||
writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA); | ||
} | ||
|
||
static const struct ata_port_info ahci_mvebu_port_info = { | ||
.flags = AHCI_FLAG_COMMON, | ||
.pio_mask = ATA_PIO4, | ||
.udma_mask = ATA_UDMA6, | ||
.port_ops = &ahci_platform_ops, | ||
}; | ||
|
||
static int ahci_mvebu_probe(struct platform_device *pdev) | ||
{ | ||
struct ahci_host_priv *hpriv; | ||
const struct mbus_dram_target_info *dram; | ||
int rc; | ||
|
||
hpriv = ahci_platform_get_resources(pdev); | ||
if (IS_ERR(hpriv)) | ||
return PTR_ERR(hpriv); | ||
|
||
rc = ahci_platform_enable_resources(hpriv); | ||
if (rc) | ||
return rc; | ||
|
||
dram = mv_mbus_dram_info(); | ||
if (!dram) | ||
return -ENODEV; | ||
|
||
ahci_mvebu_mbus_config(hpriv, dram); | ||
ahci_mvebu_regret_option(hpriv); | ||
|
||
rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info, 0, 0); | ||
if (rc) | ||
goto disable_resources; | ||
|
||
return 0; | ||
|
||
disable_resources: | ||
ahci_platform_disable_resources(hpriv); | ||
return rc; | ||
} | ||
|
||
static const struct of_device_id ahci_mvebu_of_match[] = { | ||
{ .compatible = "marvell,armada-380-ahci", }, | ||
{ }, | ||
}; | ||
MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match); | ||
|
||
/* | ||
* We currently don't provide power management related operations, | ||
* since there is no suspend/resume support at the platform level for | ||
* Armada 38x for the moment. | ||
*/ | ||
static struct platform_driver ahci_mvebu_driver = { | ||
.probe = ahci_mvebu_probe, | ||
.remove = ata_platform_remove_one, | ||
.driver = { | ||
.name = "ahci-mvebu", | ||
.owner = THIS_MODULE, | ||
.of_match_table = ahci_mvebu_of_match, | ||
}, | ||
}; | ||
module_platform_driver(ahci_mvebu_driver); | ||
|
||
MODULE_DESCRIPTION("Marvell EBU AHCI SATA driver"); | ||
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>, Marcin Wojtas <mw@semihalf.com>"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_ALIAS("platform:ahci_mvebu"); |