From: Zoltan Herpai Date: Sat, 4 Jan 2014 16:30:56 +0000 (+0000) Subject: sunxi: add sata driver for sun[47]i X-Git-Tag: reboot~8269 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=34ca9f355ec9504ed9458c5e693b79551893d2f8;p=oweals%2Fopenwrt.git sunxi: add sata driver for sun[47]i Signed-off-by: Zoltan HERPAI SVN-Revision: 39197 --- diff --git a/target/linux/sunxi/config-3.12 b/target/linux/sunxi/config-3.12 index 3b0d0b327b..4158cf6e2e 100644 --- a/target/linux/sunxi/config-3.12 +++ b/target/linux/sunxi/config-3.12 @@ -1,3 +1,4 @@ +# CONFIG_AHCI_SUNXI is not set CONFIG_ALIGNMENT_TRAP=y # CONFIG_APM_EMULATION is not set CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y diff --git a/target/linux/sunxi/modules.mk b/target/linux/sunxi/modules.mk index 5fffbc7a8b..1a54677046 100644 --- a/target/linux/sunxi/modules.mk +++ b/target/linux/sunxi/modules.mk @@ -38,3 +38,19 @@ endef $(eval $(call KernelPackage,eeprom-sunxi)) +define KernelPackage/ata-sunxi + TITLE:=AllWinner sunXi AHCI SATA support + SUBMENU:=$(BLOCK_MENU) + DEPENDS:=@TARGET_sunxi +kmod-scsi-core + KCONFIG:=\ + CONFIG_AHCI_SUNXI \ + CONFIG_SATA_AHCI_PLATFORM + FILES:=$(LINUX_DIR)/drivers/ata/ahci_sunxi.ko + AUTOLOAD:=$(call AutoLoad,41,ahci_sunxi,1) +endef + +define KernelPackage/ata-sunxi/description + SATA support for the AllWinner sunXi SoC's onboard AHCI SATA +endef + +$(eval $(call KernelPackage,ata-sunxi)) diff --git a/target/linux/sunxi/patches-3.12/190-ahci-missing-dma-for-sunxi.patch b/target/linux/sunxi/patches-3.12/190-ahci-missing-dma-for-sunxi.patch new file mode 100644 index 0000000000..c7a529967b --- /dev/null +++ b/target/linux/sunxi/patches-3.12/190-ahci-missing-dma-for-sunxi.patch @@ -0,0 +1,60 @@ +From a4c21089299ba411d998b16423a76cbae111194e Mon Sep 17 00:00:00 2001 +From: Oliver Schinagl +Date: Mon, 2 Dec 2013 16:13:32 +0100 +Subject: [PATCH] RFC: AHCI: libahci is missing DMA + +The Allwinner sunxi platforms have patched in the following to enable +DMA. This patch enables DMA controllers for the SUNXI Architecture. + +Signed-off-by: Olliver Schinagl +--- + drivers/ata/ahci.h | 6 ++++++ + drivers/ata/libahci.c | 8 ++++++++ + 2 files changed, 14 insertions(+) + +diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h +index 2289efd..2bf2423 100644 +--- a/drivers/ata/ahci.h ++++ b/drivers/ata/ahci.h +@@ -138,6 +138,7 @@ enum { + PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */ + PORT_FBS = 0x40, /* FIS-based Switching */ + PORT_DEVSLP = 0x44, /* device sleep */ ++ PORT_DMA = 0x70, /* direct memory access */ + + /* PORT_IRQ_{STAT,MASK} bits */ + PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ +@@ -209,6 +210,11 @@ enum { + PORT_DEVSLP_DSP = (1 << 1), /* DevSlp present */ + PORT_DEVSLP_ADSE = (1 << 0), /* Aggressive DevSlp enable */ + ++ /* PORT_DMA bits */ ++ PORT_DMA_SETUP_OFFSET = 8, /* dma setup offset */ ++ PORT_DMA_SETUP_MASK = (0xff << PORT_DMA_SETUP_OFFSET),/* dma mask */ ++ PORT_DMA_SETUP_INIT = (0x44 << 0), ++ + /* hpriv->flags bits */ + + #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index c482f8c..d697a74 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -570,6 +570,14 @@ void ahci_start_engine(struct ata_port *ap) + void __iomem *port_mmio = ahci_port_base(ap); + u32 tmp; + ++#ifdef CONFIG_ARCH_SUNXI ++ /* Setup DMA before DMA start */ ++ tmp = readl(port_mmio + PORT_DMA); ++ tmp &= ~PORT_DMA_SETUP_MASK; ++ tmp |= PORT_DMA_SETUP_INIT << PORT_DMA_SETUP_OFFSET; ++ writel(tmp, port_mmio + PORT_DMA); ++#endif ++ + /* start DMA */ + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_START; +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/191-add-sunxi-ahci.patch b/target/linux/sunxi/patches-3.12/191-add-sunxi-ahci.patch new file mode 100644 index 0000000000..9034be3101 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/191-add-sunxi-ahci.patch @@ -0,0 +1,436 @@ +From b7f492ca20e480ea3402692e165f919f20145935 Mon Sep 17 00:00:00 2001 +From: Oliver Schinagl +Date: Tue, 3 Dec 2013 12:07:01 +0100 +Subject: [PATCH] ARM: sunxi: Add an ahci-platform compatible AHCI driver for + the Allwinner SUNXi series of SoCs + +This patch adds support for the sunxi series of SoC's by allwinner. It +plugs into the ahci-platform framework. + +Note: Currently it uses a somewhat hackish approach that probably needs +a lot more work, but does the same as the IMX SoC's. + +Signed-off-by: Olliver Schinagl +--- + .../devicetree/bindings/ata/ahci-sunxi.txt | 24 ++ + drivers/ata/Kconfig | 9 + + drivers/ata/Makefile | 1 + + drivers/ata/ahci_platform.c | 12 + + drivers/ata/ahci_sunxi.c | 305 +++++++++++++++++++++ + 5 files changed, 351 insertions(+) + create mode 100644 Documentation/devicetree/bindings/ata/ahci-sunxi.txt + create mode 100644 drivers/ata/ahci_sunxi.c + +diff --git a/Documentation/devicetree/bindings/ata/ahci-sunxi.txt b/Documentation/devicetree/bindings/ata/ahci-sunxi.txt +new file mode 100644 +index 0000000..0792fa5 +--- /dev/null ++++ b/Documentation/devicetree/bindings/ata/ahci-sunxi.txt +@@ -0,0 +1,24 @@ ++Allwinner SUNXI AHCI SATA Controller ++ ++SATA nodes are defined to describe on-chip Serial ATA controllers. ++Each SATA controller should have its own node. ++ ++Required properties: ++- compatible : compatible list, contains "allwinner,sun4i-a10-ahci" ++- reg : ++- interrupts : ++- clocks : clocks for ACHI ++- clock-names : clock names for AHCI ++ ++Optional properties: ++- pwr-supply : regulator to control the power supply GPIO ++ ++Example: ++ ahci@01c18000 { ++ compatible = "allwinner,sun4i-a10-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = <0 56 1>; ++ clocks = <&ahb_gates 25>, <&pll6 0>; ++ clock-names = "ahb_sata", "pll6_sata"; ++ pwr-supply = <®_ahci_5v>; ++ }; +diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig +index 4e73772..b87e2ba 100644 +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -106,6 +106,15 @@ config AHCI_IMX + + If unsure, say N. + ++config AHCI_SUNXI ++ tristate "Allwinner sunxi AHCI SATA support" ++ depends on SATA_AHCI_PLATFORM && ARCH_SUNXI ++ help ++ This option enables support for the Allwinner sunxi SoC's ++ onboard AHCI SATA. ++ ++ If unsure, say N. ++ + config SATA_FSL + tristate "Freescale 3.0Gbps SATA support" + depends on FSL_SOC +diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile +index 46518c6..246050b 100644 +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_SATA_SIL24) += sata_sil24.o + obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o + obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o + obj-$(CONFIG_AHCI_IMX) += ahci_imx.o ++obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o + + # SFF w/ custom DMA + obj-$(CONFIG_PDC_ADMA) += pdc_adma.o +diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c +index 4b231ba..1046b44 100644 +--- a/drivers/ata/ahci_platform.c ++++ b/drivers/ata/ahci_platform.c +@@ -31,6 +31,7 @@ enum ahci_type { + AHCI, /* standard platform ahci */ + IMX53_AHCI, /* ahci on i.mx53 */ + STRICT_AHCI, /* delayed DMA engine start */ ++ SUNXI_AHCI, /* ahci on sunxi */ + }; + + static struct platform_device_id ahci_devtype[] = { +@@ -44,6 +45,9 @@ enum ahci_type { + .name = "strict-ahci", + .driver_data = STRICT_AHCI, + }, { ++ .name = "sunxi-ahci", ++ .driver_data = SUNXI_AHCI, ++ }, { + /* sentinel */ + } + }; +@@ -81,6 +85,14 @@ struct ata_port_operations ahci_platform_ops = { + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_platform_ops, + }, ++ [SUNXI_AHCI] = { ++ AHCI_HFLAGS (AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | ++ AHCI_HFLAG_NO_PMP | AHCI_HFLAG_YES_NCQ), ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_platform_ops, ++ }, + }; + + static struct scsi_host_template ahci_platform_sht = { +diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c +new file mode 100644 +index 0000000..982641f +--- /dev/null ++++ b/drivers/ata/ahci_sunxi.c +@@ -0,0 +1,305 @@ ++/* ++ * Allwinner sunxi AHCI SATA platform driver ++ * Copyright 2013 Olliver Schinagl ++ * ++ * Based on the AHCI SATA platform driver by Freescale and Allwinner ++ * Based on code from ++ * Allwinner Technology Co., Ltd. ++ * Daniel Wang ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ahci.h" ++ ++#define DRV_NAME "sunxi-sata" ++ ++#define AHCI_BISTAFR 0x00a0 ++#define AHCI_BISTCR 0x00a4 ++#define AHCI_BISTFCTR 0x00a8 ++#define AHCI_BISTSR 0x00ac ++#define AHCI_BISTDECR 0x00b0 ++#define AHCI_DIAGNR0 0x00b4 ++#define AHCI_DIAGNR1 0x00b8 ++#define AHCI_OOBR 0x00bc ++#define AHCI_PHYCS0R 0x00c0 ++#define AHCI_PHYCS1R 0x00c4 ++#define AHCI_PHYCS2R 0x00c8 ++#define AHCI_TIMER1MS 0x00e0 ++#define AHCI_GPARAM1R 0x00e8 ++#define AHCI_GPARAM2R 0x00ec ++#define AHCI_PPARAMR 0x00f0 ++#define AHCI_TESTR 0x00f4 ++#define AHCI_VERSIONR 0x00f8 ++#define AHCI_IDR 0x00fc ++#define AHCI_RWCR 0x00fc ++#define AHCI_P0DMACR 0x0170 ++#define AHCI_P0PHYCR 0x0178 ++#define AHCI_P0PHYSR 0x017c ++ ++struct sunxi_ahci_data { ++ struct platform_device *ahci_pdev; ++ struct regulator *regulator; ++ struct clk *sata_clk; ++ struct clk *ahb_clk; ++}; ++ ++static void sunxi_clrbits(void __iomem *reg, u32 clr_val) ++{ ++ u32 reg_val; ++ ++ reg_val = readl(reg); ++ reg_val &= ~(clr_val); ++ writel(reg_val, reg); ++} ++ ++static void sunxi_setbits(void __iomem *reg, u32 set_val) ++{ ++ u32 reg_val; ++ ++ reg_val = readl(reg); ++ reg_val |= set_val; ++ writel(reg_val, reg); ++} ++ ++static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val) ++{ ++ u32 reg_val; ++ ++ reg_val = readl(reg); ++ reg_val &= ~(clr_val); ++ reg_val |= set_val; ++ writel(reg_val, reg); ++} ++ ++static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift) ++{ ++ return (readl(reg) >> shift) & mask; ++} ++ ++static int sunxi_ahci_phy_init(struct device *dev, void __iomem *reg_base) ++{ ++ u32 reg_val; ++ int timeout; ++ ++ /* This magic is from the original code */ ++ writel(0, reg_base + AHCI_RWCR); ++ mdelay(5); ++ ++ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, ++ (0x7 << 24), ++ (0x5 << 24) | BIT(23) | BIT(18)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS1R, ++ (0x3 << 16) | (0x1f << 8) | (0x3 << 6), ++ (0x2 << 16) | (0x6 << 8) | (0x2 << 6)); ++ sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15)); ++ sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS0R, ++ (0x7 << 20), (0x3 << 20)); ++ sunxi_clrsetbits(reg_base + AHCI_PHYCS2R, ++ (0x1f << 5), (0x19 << 5)); ++ mdelay(5); ++ ++ sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19)); ++ ++ timeout = 0x100000; ++ do { ++ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28); ++ } while (--timeout && (reg_val != 0x2)); ++ if (!timeout) ++ dev_err(dev, "PHY power up failed.\n"); ++ ++ sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24)); ++ ++ timeout = 0x100000; ++ do { ++ reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24); ++ } while (--timeout && reg_val); ++ if (!timeout) ++ dev_err(dev, "PHY calibration failed.\n"); ++ mdelay(15); ++ ++ writel(0x7, reg_base + AHCI_RWCR); ++ ++ return 0; ++} ++ ++static int sunxi_ahci_init(struct device *dev, void __iomem *reg_base) ++{ ++ struct sunxi_ahci_data *ahci_data; ++ int ret; ++ ++ ahci_data = dev_get_drvdata(dev->parent); ++ ++ ret = clk_prepare_enable(ahci_data->sata_clk); ++ if (ret < 0) ++ return ret; ++ ++ ret = clk_prepare_enable(ahci_data->ahb_clk); ++ if (ret < 0) ++ return ret; ++ ++ ret = regulator_enable(ahci_data->regulator); ++ if (ret) ++ return ret; ++ ++ return sunxi_ahci_phy_init(dev, reg_base); ++} ++ ++static void sunxi_ahci_exit(struct device *dev) ++{ ++ struct sunxi_ahci_data *ahci_data; ++ ++ ahci_data = dev_get_drvdata(dev->parent); ++ ++ regulator_disable(ahci_data->regulator); ++ ++ clk_disable_unprepare(ahci_data->ahb_clk); ++ clk_disable_unprepare(ahci_data->sata_clk); ++} ++ ++static struct ahci_platform_data sunxi_ahci_pdata = { ++ .init = sunxi_ahci_init, ++ .exit = sunxi_ahci_exit, ++}; ++ ++static int sunxi_ahci_remove(struct platform_device *pdev) ++{ ++ struct sunxi_ahci_data *ahci_data; ++ ++ ahci_data = platform_get_drvdata(pdev); ++ platform_device_unregister(ahci_data->ahci_pdev); ++ ++ dev_dbg(&pdev->dev, "driver unloaded\n"); ++ ++ return 0; ++} ++ ++static const struct of_device_id sunxi_ahci_of_match[] = { ++ { .compatible = "allwinner,sun4i-a10-ahci", .data = &sunxi_ahci_pdata}, ++ {/* sentinel */}, ++}; ++MODULE_DEVICE_TABLE(of, sunxi_ahci_of_match); ++ ++static int sunxi_ahci_probe(struct platform_device *pdev) ++{ ++ const struct ahci_platform_data *pdata; ++ const struct of_device_id *of_dev_id; ++ struct resource *mem, *irq, res[2]; ++ struct platform_device *ahci_pdev; ++ struct sunxi_ahci_data *ahci_data; ++ struct regulator *regulator; ++ int ret; ++ ++ regulator = devm_regulator_get(&pdev->dev, "pwr"); ++ if (IS_ERR(regulator)) { ++ ret = PTR_ERR(regulator); ++ if (ret != -EPROBE_DEFER) ++ dev_err(&pdev->dev, "no regulator found (%d)\n", ret); ++ return ret; ++ } ++ ++ ahci_data = devm_kzalloc(&pdev->dev, sizeof(*ahci_data), GFP_KERNEL); ++ if (!ahci_data) ++ return -ENOMEM; ++ ++ ahci_pdev = platform_device_alloc("sunxi-ahci", -1); ++ if (!ahci_pdev) ++ return -ENODEV; ++ ++ ahci_pdev->dev.parent = &pdev->dev; ++ ++ ahci_data->regulator = regulator; ++ ahci_data->ahb_clk = devm_clk_get(&pdev->dev, "ahb_sata"); ++ if (IS_ERR(ahci_data->ahb_clk)) { ++ ret = PTR_ERR(ahci_data->ahb_clk); ++ goto err_out; ++ } ++ ++ ahci_data->sata_clk = devm_clk_get(&pdev->dev, "pll6_sata"); ++ if (IS_ERR(ahci_data->sata_clk)) { ++ ret = PTR_ERR(ahci_data->sata_clk); ++ goto err_out; ++ } ++ ++ ahci_data->ahci_pdev = ahci_pdev; ++ platform_set_drvdata(pdev, ahci_data); ++ ++ ahci_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ ahci_pdev->dev.dma_mask = &ahci_pdev->dev.coherent_dma_mask; ++ ahci_pdev->dev.of_node = pdev->dev.of_node; ++ ++ of_dev_id = of_match_device(sunxi_ahci_of_match, &pdev->dev); ++ if (of_dev_id) { ++ pdata = of_dev_id->data; ++ } else { ++ ret = -EINVAL; ++ goto err_out; ++ } ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!mem || !irq) { ++ ret = -ENOMEM; ++ goto err_out; ++ } ++ res[0] = *mem; ++ res[1] = *irq; ++ ret = platform_device_add_resources(ahci_pdev, res, 2); ++ if (ret) ++ goto err_out; ++ ++ ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata)); ++ if (ret) ++ goto err_out; ++ ++ ret = platform_device_add(ahci_pdev); ++ if (ret) ++ goto err_out; ++ ++ return 0; ++ ++err_out: ++ platform_device_put(ahci_pdev); ++ return ret; ++} ++ ++static struct platform_driver sunxi_ahci_driver = { ++ .probe = sunxi_ahci_probe, ++ .remove = sunxi_ahci_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = sunxi_ahci_of_match, ++ }, ++}; ++module_platform_driver(sunxi_ahci_driver); ++ ++MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA platform driver"); ++MODULE_AUTHOR("Olliver Schinagl "); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("ahci:sunxi"); +-- +1.8.5.1 + diff --git a/target/linux/sunxi/patches-3.12/192-dt-add-ahci-sun47i.patch b/target/linux/sunxi/patches-3.12/192-dt-add-ahci-sun47i.patch new file mode 100644 index 0000000000..a9d5056f93 --- /dev/null +++ b/target/linux/sunxi/patches-3.12/192-dt-add-ahci-sun47i.patch @@ -0,0 +1,193 @@ +From e5b4d58432bec91414e82069a402d61e6aed631e Mon Sep 17 00:00:00 2001 +From: Oliver Schinagl +Date: Tue, 3 Dec 2013 12:10:11 +0100 +Subject: [PATCH] ARM: sunxi: dts: Add ahci support to a few A10 and A20 boards + +This patch adds sunxi sata support to A10 and A20 boards that have such +a connector. Some boards also feature a regulator via a GPIO and support +for this is also added. + +Signed-off-by: Olliver Schinagl +--- + arch/arm/boot/dts/sun4i-a10-cubieboard.dts | 27 +++++++++++++++++++++++++ + arch/arm/boot/dts/sun4i-a10.dtsi | 9 +++++++++ + arch/arm/boot/dts/sun7i-a20-cubieboard2.dts | 27 +++++++++++++++++++++++++ + arch/arm/boot/dts/sun7i-a20-cubietruck.dts | 27 +++++++++++++++++++++++++ + arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts | 26 ++++++++++++++++++++++++ + arch/arm/boot/dts/sun7i-a20.dtsi | 9 +++++++++ + 6 files changed, 125 insertions(+) + +diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +index d193937..63bd00d 100644 +--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts ++++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts +@@ -51,7 +51,19 @@ + status = "okay"; + }; + ++ sata: ahci@01c18000 { ++ pwr-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { ++ ahci_pwr_pin: ahci_pwr_pin@0 { ++ allwinner,pins = "PB8"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ + mmc0_cd_pin_cubieboard: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; +@@ -102,4 +114,19 @@ + linux,default-trigger = "heartbeat"; + }; + }; ++ ++ regulators { ++ compatible = "simple-bus"; ++ pinctrl-names = "default"; ++ ++ reg_ahci_5v: ahci-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "ahci-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ pinctrl-0 = <&ahci_pwr_pin>; ++ gpio = <&pio 1 8 0>; ++ enable-active-high; ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi +index 13bccd5..a6dafec 100644 +--- a/arch/arm/boot/dts/sun4i-a10.dtsi ++++ b/arch/arm/boot/dts/sun4i-a10.dtsi +@@ -315,6 +315,15 @@ + status = "disabled"; + }; + ++ sata: ahci@01c18000 { ++ compatible = "allwinner,sun4i-a10-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = <56>; ++ clocks = <&ahb_gates 25>, <&pll6 0>; ++ clock-names = "ahb_sata", "pll6_sata"; ++ status = "disabled"; ++ }; ++ + intc: interrupt-controller@01c20400 { + compatible = "allwinner,sun4i-ic"; + reg = <0x01c20400 0x400>; +diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +index ea55563..1d810bb 100644 +--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts ++++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts +@@ -28,7 +28,19 @@ + status = "okay"; + }; + ++ sata: ahci@01c18000 { ++ pwr-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { ++ ahci_pwr_pin: ahci_pwr_pin@0 { ++ allwinner,pins = "PB8"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ + mmc0_cd_pin_cubieboard2: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; +@@ -86,4 +98,19 @@ + gpios = <&pio 7 20 0>; + }; + }; ++ ++ regulators { ++ compatible = "simple-bus"; ++ pinctrl-names = "default"; ++ ++ reg_ahci_5v: ahci-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "ahci-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ pinctrl-0 = <&ahci_pwr_pin>; ++ gpio = <&pio 1 8 0>; ++ enable-active-high; ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +index bc04cc7..5e9f2ab 100644 +--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts ++++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts +@@ -37,7 +37,19 @@ + status = "okay"; + }; + ++ sata: ahci@01c18000 { ++ pwr-supply = <®_ahci_5v>; ++ status = "okay"; ++ }; ++ + pinctrl@01c20800 { ++ ahci_pwr_pin: ahci_pwr_pin@0 { ++ allwinner,pins = "PB8"; ++ allwinner,function = "gpio_out"; ++ allwinner,drive = <0>; ++ allwinner,pull = <0>; ++ }; ++ + mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 { + allwinner,pins = "PH1"; + allwinner,function = "gpio_in"; +@@ -116,4 +128,18 @@ + default-state = "on"; + }; + }; ++ ++ regulators { ++ compatible = "simple-bus"; ++ ++ reg_ahci_5v: ahci-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "ahci-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ pinctrl-0 = <&ahci_pwr_pin>; ++ gpio = <&pio 1 8 0>; ++ enable-active-high; ++ }; ++ }; + }; +diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi +index 7ebfc89..f161590 100644 +--- a/arch/arm/boot/dts/sun7i-a20.dtsi ++++ b/arch/arm/boot/dts/sun7i-a20.dtsi +@@ -432,6 +432,15 @@ + }; + }; + ++ sata: ahci@01c18000 { ++ compatible = "allwinner,sun4i-a10-ahci"; ++ reg = <0x01c18000 0x1000>; ++ interrupts = <0 56 1>; ++ clocks = <&ahb_gates 25>, <&pll6 0>; ++ clock-names = "ahb_sata", "pll6_sata"; ++ status = "disabled"; ++ }; ++ + timer@01c20c00 { + compatible = "allwinner,sun4i-timer"; + reg = <0x01c20c00 0x90>; +-- +1.8.5.1 +