/* * TI AHCI SATA controler * * TI SATA controller on OMAPL138 platform. AHCI compliant controller. * * Copyright (C) 2009 Texas Instruments. * * --------------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * --------------------------------------------------------------------------- * History: * 0-1 Swaminathan Subbarathnam : Initial creation of AHCI platform specific * interface for non-PCI based SATA AHCI implementation. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if CONFIG_FUSIV_SATA_EXTERNAL_CLOCK #include #endif //#include //#include void ata_plat_init (void __iomem *base); void ata_plat_remove(struct ata_host *host); #define P0PHYCR 0x178 /* SATA PHY Control Register offset * from AHCI base) */ #define PHY_MPY 8 /* bits3:0 4 Clock Sources at 100MHz */ #define PHY_LB 0 /* bits5:4 2 */ #define PHY_LOS 1 /* bit6 1 */ #define PHY_RXINVPAIR 0 /* bit7 1 */ #define PHY_RXTERM 0 /* bits9:8 2 */ #define PHY_RXCDR 0 /* bits12:10 3 */ #define PHY_RXEQ 1 /* bits16:13 4 */ #define PHY_TXINVPAIR 0 /* bit17 1 */ #define PHY_TXCM 0 /* bit18 1 */ #define PHY_TXSWING 3 /* bits21:19 3 */ #define PHY_TXDE 0 /* bits25:22 4 */ #define PHY_OVERRIDE 0 /* bit30 1 */ #define PHY_ENPLL 1 /* bit31 1 */ /* ata_plat_init - Do platform specific init of the AHCI SATA controller. * @base - Base address of the AHCI SATA controller */ void ata_plat_init (void __iomem *base) { volatile unsigned int temp; #if CONFIG_FUSIV_SATA_EXTERNAL_CLOCK /* SN Select SATA ref clock as external source and value as 100MHz */ scu_regs->cpu_ctl_mask &= ~(1 << SATA_REF_CLK_SEL); scu_regs->cpu_ctl &= ~(1 << SATA_REF_CLK_SEL); scu_regs->cpu_ctl_mask |= (1 << SATA_REF_CLK_SEL); // Remove MASKS for clock source and prescalar ; // Write the value scu_regs->cpu_ctl_mask &= ~(0x3 << SATA_MPLL_PRESCALE); scu_regs->cpu_ctl &= ~(0x3 << SATA_MPLL_PRESCALE); // External source Bit31 - 0, Divide by 2 (bit 23:24 = 01) scu_regs->cpu_ctl |= (0x2 << SATA_MPLL_PRESCALE); // External source Bit31 - 0, Divide by 2 (bit 23:24 = 01) scu_regs->cpu_ctl_mask |= (0x3 << SATA_MPLL_PRESCALE); #endif /* Remove CLK and Reset write Mask for SATA */ *(volatile unsigned int *)0xb9000000 &= ~(1 << 13); /* Disable SATA reset */ *(volatile unsigned int *)0xb9000004 |= 1 << 13; /* Enable SATA Clock */ *(volatile unsigned int *)0xb900001c |= 1 << 13; /* Enable Byte Swap for SATA D-Bus access (Big endian to Little endian ??) */ //*(volatile unsigned int *)0xb9150178 |= 1 << 21; temp = *(volatile unsigned int *)0xb9150178; temp = (temp & 0xffdf0000 ) | 0x0020e210; *(volatile unsigned int *)0xb9150178 = temp; /* Set the address for read or write */ *(volatile unsigned int *)0xb9150178 = 0x00200014; *(volatile unsigned int *)0xb9150178 = 0x00210014; temp = *(volatile unsigned int *)0xb915017c; *(volatile unsigned int *)0xb9150178 = 0x00200014; /* The following will write with data 0xfe10 to the address we set */ *(volatile unsigned int *)0xb9150178 = 0x0020fe10; *(volatile unsigned int *)0xb9150178 = 0x0022fe10; temp = *(volatile unsigned int *)0xb915017c; *(volatile unsigned int *)0xb9150178 = 0x0020fe10; temp = *(volatile unsigned int *)0xb915017c; *(volatile unsigned int *)0xb9150178 = 0x0024fe10; temp = *(volatile unsigned int *)0xb915017c; *(volatile unsigned int *)0xb9150178 = 0x00200000; temp = *(volatile unsigned int *)0xb915017c; /* Initialize the port implement */ *(volatile unsigned int *)0xb915000c = 0x1; /* Configure the Link Layer OOB detection counters */ *(volatile unsigned int *)0xb91500bc = 0x82060b13; *(volatile unsigned int *)0xb91500bc = 0x82060b13; // Single write is not modifying the bits 30:24, hence 2 writes return; } /* ata_plat_remove - Do platform specific de-init of the AHCI SATA controller. * @host - ATA Host pointer of the controller. */ void ata_plat_remove(struct ata_host *host) { #if 0 /* Power down the PHY clock source */ if (cpu_is_davinci_da850()) __raw_writel(1, IO_ADDRESS(DA850_SATA_CLK_PWRDN)); #endif printk("KWANG TODO Power down the PHY clock source\n"); } void ahci_platform_suspend(struct platform_device *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); u32 phy_val = 0; #if 0 phy_val = readl(host->iomap + P0PHYCR); phy_val &= ~(PHY_ENPLL << 31); writel(phy_val, host->iomap + P0PHYCR); #endif printk("KWANG TODO ahci_platform_suspend\n"); } void ahci_platform_resume(struct platform_device *pdev) { struct ata_host *host = dev_get_drvdata(&pdev->dev); u32 phy_val = 0; #if 0 phy_val = readl(host->iomap + P0PHYCR); phy_val |= PHY_ENPLL << 31; writel(phy_val, host->iomap + P0PHYCR); #endif printk("KWANG TODO ahci_platform_resume\n"); } EXPORT_SYMBOL_GPL(ahci_platform_resume); EXPORT_SYMBOL_GPL(ata_plat_init); EXPORT_SYMBOL_GPL(ata_plat_remove); EXPORT_SYMBOL_GPL(ahci_platform_suspend);