Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Bartlomiej Zolnierkiewicz and committed by
Tejun Heo
ae8723f8 fd990556

+124
+9
drivers/ata/Kconfig
··· 97 97 98 98 If unsure, say N. 99 99 100 + config AHCI_DA850 101 + tristate "DaVinci DA850 AHCI SATA support" 102 + depends on ARCH_DAVINCI_DA850 103 + help 104 + This option enables support for the DaVinci DA850 SoC's 105 + onboard AHCI SATA. 106 + 107 + If unsure, say N. 108 + 100 109 config AHCI_ST 101 110 tristate "ST AHCI SATA support" 102 111 depends on ARCH_STI
+1
drivers/ata/Makefile
··· 10 10 obj-$(CONFIG_SATA_SIL24) += sata_sil24.o 11 11 obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o 12 12 obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o 13 + obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o 13 14 obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o 14 15 obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o 15 16 obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o
+114
drivers/ata/ahci_da850.c
··· 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");