brintos

brintos / linux-shallow public Read only

0
0
Text · 10.6 KiB · 11a2c19 Raw
417 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2015 Xilinx, Inc.4 * CEVA AHCI SATA platform driver5 *6 * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov7 */8 9#include <linux/ahci_platform.h>10#include <linux/kernel.h>11#include <linux/libata.h>12#include <linux/module.h>13#include <linux/of.h>14#include <linux/platform_device.h>15#include <linux/reset.h>16#include "ahci.h"17 18/* Vendor Specific Register Offsets */19#define AHCI_VEND_PCFG  0xA420#define AHCI_VEND_PPCFG 0xA821#define AHCI_VEND_PP2C  0xAC22#define AHCI_VEND_PP3C  0xB023#define AHCI_VEND_PP4C  0xB424#define AHCI_VEND_PP5C  0xB825#define AHCI_VEND_AXICC 0xBC26#define AHCI_VEND_PAXIC 0xC027#define AHCI_VEND_PTC   0xC828 29/* Vendor Specific Register bit definitions */30#define PAXIC_ADBW_BW64 0x131#define PAXIC_MAWID(i)	(((i) * 2) << 4)32#define PAXIC_MARID(i)	(((i) * 2) << 12)33#define PAXIC_MARIDD(i)	((((i) * 2) + 1) << 16)34#define PAXIC_MAWIDD(i)	((((i) * 2) + 1) << 8)35#define PAXIC_OTL	(0x4 << 20)36 37/* Register bit definitions for cache control */38#define AXICC_ARCA_VAL  (0xF << 0)39#define AXICC_ARCF_VAL  (0xF << 4)40#define AXICC_ARCH_VAL  (0xF << 8)41#define AXICC_ARCP_VAL  (0xF << 12)42#define AXICC_AWCFD_VAL (0xF << 16)43#define AXICC_AWCD_VAL  (0xF << 20)44#define AXICC_AWCF_VAL  (0xF << 24)45 46#define PCFG_TPSS_VAL	(0x32 << 16)47#define PCFG_TPRS_VAL	(0x2 << 12)48#define PCFG_PAD_VAL	0x249 50#define PPCFG_TTA	0x1FFFE51#define PPCFG_PSSO_EN	(1 << 28)52#define PPCFG_PSS_EN	(1 << 29)53#define PPCFG_ESDF_EN	(1 << 31)54 55#define PP5C_RIT	0x6021656#define PP5C_RCT	(0x7f0 << 20)57 58#define PTC_RX_WM_VAL	0x4059#define PTC_RSVD	(1 << 27)60 61#define PORT0_BASE	0x10062#define PORT1_BASE	0x18063 64/* Port Control Register Bit Definitions */65#define PORT_SCTL_SPD_GEN3	(0x3 << 4)66#define PORT_SCTL_SPD_GEN2	(0x2 << 4)67#define PORT_SCTL_SPD_GEN1	(0x1 << 4)68#define PORT_SCTL_IPM		(0x3 << 8)69 70#define PORT_BASE	0x10071#define PORT_OFFSET	0x8072#define NR_PORTS	273#define DRV_NAME	"ahci-ceva"74#define CEVA_FLAG_BROKEN_GEN2	175 76static unsigned int rx_watermark = PTC_RX_WM_VAL;77module_param(rx_watermark, uint, 0644);78MODULE_PARM_DESC(rx_watermark, "RxWaterMark value (0 - 0x80)");79 80struct ceva_ahci_priv {81	struct platform_device *ahci_pdev;82	/* Port Phy2Cfg Register */83	u32 pp2c[NR_PORTS];84	u32 pp3c[NR_PORTS];85	u32 pp4c[NR_PORTS];86	u32 pp5c[NR_PORTS];87	/* Axi Cache Control Register */88	u32 axicc;89	bool is_cci_enabled;90	int flags;91};92 93static unsigned int ceva_ahci_read_id(struct ata_device *dev,94				      struct ata_taskfile *tf, __le16 *id)95{96	u32 err_mask;97 98	err_mask = ata_do_dev_read_id(dev, tf, id);99	if (err_mask)100		return err_mask;101	/*102	 * Since CEVA controller does not support device sleep feature, we103	 * need to clear DEVSLP (bit 8) in word78 of the IDENTIFY DEVICE data.104	 */105	id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8));106 107	return 0;108}109 110static struct ata_port_operations ahci_ceva_ops = {111	.inherits = &ahci_platform_ops,112	.read_id = ceva_ahci_read_id,113};114 115static const struct ata_port_info ahci_ceva_port_info = {116	.flags          = AHCI_FLAG_COMMON,117	.pio_mask       = ATA_PIO4,118	.udma_mask      = ATA_UDMA6,119	.port_ops	= &ahci_ceva_ops,120};121 122static void ahci_ceva_setup(struct ahci_host_priv *hpriv)123{124	void __iomem *mmio = hpriv->mmio;125	struct ceva_ahci_priv *cevapriv = hpriv->plat_data;126	u32 tmp;127	int i;128 129	/* Set AHCI Enable */130	tmp = readl(mmio + HOST_CTL);131	tmp |= HOST_AHCI_EN;132	writel(tmp, mmio + HOST_CTL);133 134	for (i = 0; i < NR_PORTS; i++) {135		/* TPSS TPRS scalars, CISE and Port Addr */136		tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i);137		writel(tmp, mmio + AHCI_VEND_PCFG);138 139		/*140		 * AXI Data bus width to 64141		 * Set Mem Addr Read, Write ID for data transfers142		 * Set Mem Addr Read ID, Write ID for non-data transfers143		 * Transfer limit to 72 DWord144		 */145		tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD(i) | PAXIC_MARIDD(i) |146			PAXIC_MAWID(i) | PAXIC_MARID(i) | PAXIC_OTL;147		writel(tmp, mmio + AHCI_VEND_PAXIC);148 149		/* Set AXI cache control register if CCi is enabled */150		if (cevapriv->is_cci_enabled) {151			tmp = readl(mmio + AHCI_VEND_AXICC);152			tmp |= AXICC_ARCA_VAL | AXICC_ARCF_VAL |153				AXICC_ARCH_VAL | AXICC_ARCP_VAL |154				AXICC_AWCFD_VAL | AXICC_AWCD_VAL |155				AXICC_AWCF_VAL;156			writel(tmp, mmio + AHCI_VEND_AXICC);157		}158 159		/* Port Phy Cfg register enables */160		tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;161		writel(tmp, mmio + AHCI_VEND_PPCFG);162 163		/* Phy Control OOB timing parameters COMINIT */164		writel(cevapriv->pp2c[i], mmio + AHCI_VEND_PP2C);165 166		/* Phy Control OOB timing parameters COMWAKE */167		writel(cevapriv->pp3c[i], mmio + AHCI_VEND_PP3C);168 169		/* Phy Control Burst timing setting */170		writel(cevapriv->pp4c[i], mmio + AHCI_VEND_PP4C);171 172		/* Rate Change Timer and Retry Interval Timer setting */173		writel(cevapriv->pp5c[i], mmio + AHCI_VEND_PP5C);174 175		/* Rx Watermark setting  */176		tmp = rx_watermark | PTC_RSVD;177		writel(tmp, mmio + AHCI_VEND_PTC);178 179		/* Default to Gen 3 Speed and Gen 1 if Gen2 is broken */180		tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM;181		if (cevapriv->flags & CEVA_FLAG_BROKEN_GEN2)182			tmp = PORT_SCTL_SPD_GEN1 | PORT_SCTL_IPM;183		writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i);184	}185}186 187static const struct scsi_host_template ahci_platform_sht = {188	AHCI_SHT(DRV_NAME),189};190 191static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)192{193	int rc, i;194 195	rc = ahci_platform_enable_regulators(hpriv);196	if (rc)197		return rc;198 199	rc = ahci_platform_enable_clks(hpriv);200	if (rc)201		goto disable_regulator;202 203	/* Assert the controller reset */204	rc = ahci_platform_assert_rsts(hpriv);205	if (rc)206		goto disable_clks;207 208	for (i = 0; i < hpriv->nports; i++) {209		rc = phy_init(hpriv->phys[i]);210		if (rc)211			goto disable_rsts;212	}213 214	/* De-assert the controller reset */215	ahci_platform_deassert_rsts(hpriv);216 217	for (i = 0; i < hpriv->nports; i++) {218		rc = phy_power_on(hpriv->phys[i]);219		if (rc) {220			phy_exit(hpriv->phys[i]);221			goto disable_phys;222		}223	}224 225	return 0;226 227disable_rsts:228	ahci_platform_deassert_rsts(hpriv);229 230disable_phys:231	while (--i >= 0) {232		phy_power_off(hpriv->phys[i]);233		phy_exit(hpriv->phys[i]);234	}235 236disable_clks:237	ahci_platform_disable_clks(hpriv);238 239disable_regulator:240	ahci_platform_disable_regulators(hpriv);241 242	return rc;243}244 245static int ceva_ahci_probe(struct platform_device *pdev)246{247	struct device_node *np = pdev->dev.of_node;248	struct device *dev = &pdev->dev;249	struct ahci_host_priv *hpriv;250	struct ceva_ahci_priv *cevapriv;251	enum dev_dma_attr attr;252	int rc;253 254	cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL);255	if (!cevapriv)256		return -ENOMEM;257 258	cevapriv->ahci_pdev = pdev;259	hpriv = ahci_platform_get_resources(pdev, 0);260	if (IS_ERR(hpriv))261		return PTR_ERR(hpriv);262 263	hpriv->rsts = devm_reset_control_get_optional_exclusive(&pdev->dev,264								NULL);265	if (IS_ERR(hpriv->rsts))266		return dev_err_probe(&pdev->dev, PTR_ERR(hpriv->rsts),267				     "failed to get reset\n");268 269	rc = ceva_ahci_platform_enable_resources(hpriv);270	if (rc)271		return rc;272 273	if (of_property_read_bool(np, "ceva,broken-gen2"))274		cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;275 276	/* Read OOB timing value for COMINIT from device-tree */277	if (of_property_read_u8_array(np, "ceva,p0-cominit-params",278					(u8 *)&cevapriv->pp2c[0], 4) < 0) {279		dev_warn(dev, "ceva,p0-cominit-params property not defined\n");280		rc = -EINVAL;281		goto disable_resources;282	}283 284	if (of_property_read_u8_array(np, "ceva,p1-cominit-params",285					(u8 *)&cevapriv->pp2c[1], 4) < 0) {286		dev_warn(dev, "ceva,p1-cominit-params property not defined\n");287		rc = -EINVAL;288		goto disable_resources;289	}290 291	/* Read OOB timing value for COMWAKE from device-tree*/292	if (of_property_read_u8_array(np, "ceva,p0-comwake-params",293					(u8 *)&cevapriv->pp3c[0], 4) < 0) {294		dev_warn(dev, "ceva,p0-comwake-params property not defined\n");295		rc = -EINVAL;296		goto disable_resources;297	}298 299	if (of_property_read_u8_array(np, "ceva,p1-comwake-params",300					(u8 *)&cevapriv->pp3c[1], 4) < 0) {301		dev_warn(dev, "ceva,p1-comwake-params property not defined\n");302		rc = -EINVAL;303		goto disable_resources;304	}305 306	/* Read phy BURST timing value from device-tree */307	if (of_property_read_u8_array(np, "ceva,p0-burst-params",308					(u8 *)&cevapriv->pp4c[0], 4) < 0) {309		dev_warn(dev, "ceva,p0-burst-params property not defined\n");310		rc = -EINVAL;311		goto disable_resources;312	}313 314	if (of_property_read_u8_array(np, "ceva,p1-burst-params",315					(u8 *)&cevapriv->pp4c[1], 4) < 0) {316		dev_warn(dev, "ceva,p1-burst-params property not defined\n");317		rc = -EINVAL;318		goto disable_resources;319	}320 321	/* Read phy RETRY interval timing value from device-tree */322	if (of_property_read_u16_array(np, "ceva,p0-retry-params",323					(u16 *)&cevapriv->pp5c[0], 2) < 0) {324		dev_warn(dev, "ceva,p0-retry-params property not defined\n");325		rc = -EINVAL;326		goto disable_resources;327	}328 329	if (of_property_read_u16_array(np, "ceva,p1-retry-params",330					(u16 *)&cevapriv->pp5c[1], 2) < 0) {331		dev_warn(dev, "ceva,p1-retry-params property not defined\n");332		rc = -EINVAL;333		goto disable_resources;334	}335 336	/*337	 * Check if CCI is enabled for SATA. The DEV_DMA_COHERENT is returned338	 * if CCI is enabled, so check for DEV_DMA_COHERENT.339	 */340	attr = device_get_dma_attr(dev);341	cevapriv->is_cci_enabled = (attr == DEV_DMA_COHERENT);342 343	hpriv->plat_data = cevapriv;344 345	/* CEVA specific initialization */346	ahci_ceva_setup(hpriv);347 348	rc = ahci_platform_init_host(pdev, hpriv, &ahci_ceva_port_info,349					&ahci_platform_sht);350	if (rc)351		goto disable_resources;352 353	return 0;354 355disable_resources:356	ahci_platform_disable_resources(hpriv);357	return rc;358}359 360static int __maybe_unused ceva_ahci_suspend(struct device *dev)361{362	return ahci_platform_suspend(dev);363}364 365static int __maybe_unused ceva_ahci_resume(struct device *dev)366{367	struct ata_host *host = dev_get_drvdata(dev);368	struct ahci_host_priv *hpriv = host->private_data;369	int rc;370 371	rc = ceva_ahci_platform_enable_resources(hpriv);372	if (rc)373		return rc;374 375	/* Configure CEVA specific config before resuming HBA */376	ahci_ceva_setup(hpriv);377 378	rc = ahci_platform_resume_host(dev);379	if (rc)380		goto disable_resources;381 382	/* We resumed so update PM runtime state */383	pm_runtime_disable(dev);384	pm_runtime_set_active(dev);385	pm_runtime_enable(dev);386 387	return 0;388 389disable_resources:390	ahci_platform_disable_resources(hpriv);391 392	return rc;393}394 395static SIMPLE_DEV_PM_OPS(ahci_ceva_pm_ops, ceva_ahci_suspend, ceva_ahci_resume);396 397static const struct of_device_id ceva_ahci_of_match[] = {398	{ .compatible = "ceva,ahci-1v84" },399	{ /* sentinel */ }400};401MODULE_DEVICE_TABLE(of, ceva_ahci_of_match);402 403static struct platform_driver ceva_ahci_driver = {404	.probe = ceva_ahci_probe,405	.remove_new = ata_platform_remove_one,406	.driver = {407		.name = DRV_NAME,408		.of_match_table = ceva_ahci_of_match,409		.pm = &ahci_ceva_pm_ops,410	},411};412module_platform_driver(ceva_ahci_driver);413 414MODULE_DESCRIPTION("CEVA AHCI SATA platform driver");415MODULE_AUTHOR("Xilinx Inc.");416MODULE_LICENSE("GPL v2");417