cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pata_imx.c (7548B)


      1/*
      2 * Freescale iMX PATA driver
      3 *
      4 * Copyright (C) 2011 Arnaud Patard <arnaud.patard@rtp-net.org>
      5 *
      6 * Based on pata_platform - Copyright (C) 2006 - 2007  Paul Mundt
      7 *
      8 * This file is subject to the terms and conditions of the GNU General Public
      9 * License.  See the file "COPYING" in the main directory of this archive
     10 * for more details.
     11 *
     12 * TODO:
     13 * - dmaengine support
     14 */
     15
     16#include <linux/ata.h>
     17#include <linux/clk.h>
     18#include <linux/libata.h>
     19#include <linux/module.h>
     20#include <linux/mod_devicetable.h>
     21#include <linux/platform_device.h>
     22
     23#define DRV_NAME "pata_imx"
     24
     25#define PATA_IMX_ATA_TIME_OFF		0x00
     26#define PATA_IMX_ATA_TIME_ON		0x01
     27#define PATA_IMX_ATA_TIME_1		0x02
     28#define PATA_IMX_ATA_TIME_2W		0x03
     29#define PATA_IMX_ATA_TIME_2R		0x04
     30#define PATA_IMX_ATA_TIME_AX		0x05
     31#define PATA_IMX_ATA_TIME_PIO_RDX	0x06
     32#define PATA_IMX_ATA_TIME_4		0x07
     33#define PATA_IMX_ATA_TIME_9		0x08
     34
     35#define PATA_IMX_ATA_CONTROL		0x24
     36#define PATA_IMX_ATA_CTRL_FIFO_RST_B	(1<<7)
     37#define PATA_IMX_ATA_CTRL_ATA_RST_B	(1<<6)
     38#define PATA_IMX_ATA_CTRL_IORDY_EN	(1<<0)
     39#define PATA_IMX_ATA_INT_EN		0x2C
     40#define PATA_IMX_ATA_INTR_ATA_INTRQ2	(1<<3)
     41#define PATA_IMX_DRIVE_DATA		0xA0
     42#define PATA_IMX_DRIVE_CONTROL		0xD8
     43
     44static u32 pio_t4[] = { 30,  20,  15,  10,  10 };
     45static u32 pio_t9[] = { 20,  15,  10,  10,  10 };
     46static u32 pio_tA[] = { 35,  35,  35,  35,  35 };
     47
     48struct pata_imx_priv {
     49	struct clk *clk;
     50	/* timings/interrupt/control regs */
     51	void __iomem *host_regs;
     52	u32 ata_ctl;
     53};
     54
     55static void pata_imx_set_timing(struct ata_device *adev,
     56				struct pata_imx_priv *priv)
     57{
     58	struct ata_timing timing;
     59	unsigned long clkrate;
     60	u32 T, mode;
     61
     62	clkrate = clk_get_rate(priv->clk);
     63
     64	if (adev->pio_mode < XFER_PIO_0 || adev->pio_mode > XFER_PIO_4 ||
     65	    !clkrate)
     66		return;
     67
     68	T = 1000000000 / clkrate;
     69	ata_timing_compute(adev, adev->pio_mode, &timing, T * 1000, 0);
     70
     71	mode = adev->pio_mode - XFER_PIO_0;
     72
     73	writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_OFF);
     74	writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_ON);
     75	writeb(timing.setup, priv->host_regs + PATA_IMX_ATA_TIME_1);
     76	writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2W);
     77	writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2R);
     78	writeb(1, priv->host_regs + PATA_IMX_ATA_TIME_PIO_RDX);
     79
     80	writeb(pio_t4[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_4);
     81	writeb(pio_t9[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_9);
     82	writeb(pio_tA[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_AX);
     83}
     84
     85static void pata_imx_set_piomode(struct ata_port *ap, struct ata_device *adev)
     86{
     87	struct pata_imx_priv *priv = ap->host->private_data;
     88	u32 val;
     89
     90	pata_imx_set_timing(adev, priv);
     91
     92	val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
     93	if (ata_pio_need_iordy(adev))
     94		val |= PATA_IMX_ATA_CTRL_IORDY_EN;
     95	else
     96		val &= ~PATA_IMX_ATA_CTRL_IORDY_EN;
     97	__raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL);
     98}
     99
    100static struct scsi_host_template pata_imx_sht = {
    101	ATA_PIO_SHT(DRV_NAME),
    102};
    103
    104static struct ata_port_operations pata_imx_port_ops = {
    105	.inherits		= &ata_sff_port_ops,
    106	.sff_data_xfer		= ata_sff_data_xfer32,
    107	.cable_detect		= ata_cable_unknown,
    108	.set_piomode		= pata_imx_set_piomode,
    109};
    110
    111static void pata_imx_setup_port(struct ata_ioports *ioaddr)
    112{
    113	/* Fixup the port shift for platforms that need it */
    114	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << 2);
    115	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << 2);
    116	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << 2);
    117	ioaddr->nsect_addr	= ioaddr->cmd_addr + (ATA_REG_NSECT   << 2);
    118	ioaddr->lbal_addr	= ioaddr->cmd_addr + (ATA_REG_LBAL    << 2);
    119	ioaddr->lbam_addr	= ioaddr->cmd_addr + (ATA_REG_LBAM    << 2);
    120	ioaddr->lbah_addr	= ioaddr->cmd_addr + (ATA_REG_LBAH    << 2);
    121	ioaddr->device_addr	= ioaddr->cmd_addr + (ATA_REG_DEVICE  << 2);
    122	ioaddr->status_addr	= ioaddr->cmd_addr + (ATA_REG_STATUS  << 2);
    123	ioaddr->command_addr	= ioaddr->cmd_addr + (ATA_REG_CMD     << 2);
    124}
    125
    126static int pata_imx_probe(struct platform_device *pdev)
    127{
    128	struct ata_host *host;
    129	struct ata_port *ap;
    130	struct pata_imx_priv *priv;
    131	int irq = 0;
    132	struct resource *io_res;
    133	int ret;
    134
    135	irq = platform_get_irq(pdev, 0);
    136	if (irq < 0)
    137		return irq;
    138
    139	priv = devm_kzalloc(&pdev->dev,
    140				sizeof(struct pata_imx_priv), GFP_KERNEL);
    141	if (!priv)
    142		return -ENOMEM;
    143
    144	priv->clk = devm_clk_get(&pdev->dev, NULL);
    145	if (IS_ERR(priv->clk)) {
    146		dev_err(&pdev->dev, "Failed to get clock\n");
    147		return PTR_ERR(priv->clk);
    148	}
    149
    150	ret = clk_prepare_enable(priv->clk);
    151	if (ret)
    152		return ret;
    153
    154	host = ata_host_alloc(&pdev->dev, 1);
    155	if (!host) {
    156		ret = -ENOMEM;
    157		goto err;
    158	}
    159
    160	host->private_data = priv;
    161	ap = host->ports[0];
    162
    163	ap->ops = &pata_imx_port_ops;
    164	ap->pio_mask = ATA_PIO4;
    165	ap->flags |= ATA_FLAG_SLAVE_POSS;
    166
    167	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    168	priv->host_regs = devm_ioremap_resource(&pdev->dev, io_res);
    169	if (IS_ERR(priv->host_regs)) {
    170		ret = PTR_ERR(priv->host_regs);
    171		goto err;
    172	}
    173
    174	ap->ioaddr.cmd_addr = priv->host_regs + PATA_IMX_DRIVE_DATA;
    175	ap->ioaddr.ctl_addr = priv->host_regs + PATA_IMX_DRIVE_CONTROL;
    176
    177	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
    178
    179	pata_imx_setup_port(&ap->ioaddr);
    180
    181	ata_port_desc(ap, "cmd 0x%llx ctl 0x%llx",
    182		(unsigned long long)io_res->start + PATA_IMX_DRIVE_DATA,
    183		(unsigned long long)io_res->start + PATA_IMX_DRIVE_CONTROL);
    184
    185	/* deassert resets */
    186	__raw_writel(PATA_IMX_ATA_CTRL_FIFO_RST_B |
    187			PATA_IMX_ATA_CTRL_ATA_RST_B,
    188			priv->host_regs + PATA_IMX_ATA_CONTROL);
    189	/* enable interrupts */
    190	__raw_writel(PATA_IMX_ATA_INTR_ATA_INTRQ2,
    191			priv->host_regs + PATA_IMX_ATA_INT_EN);
    192
    193	/* activate */
    194	ret = ata_host_activate(host, irq, ata_sff_interrupt, 0,
    195				&pata_imx_sht);
    196
    197	if (ret)
    198		goto err;
    199
    200	return 0;
    201err:
    202	clk_disable_unprepare(priv->clk);
    203
    204	return ret;
    205}
    206
    207static int pata_imx_remove(struct platform_device *pdev)
    208{
    209	struct ata_host *host = platform_get_drvdata(pdev);
    210	struct pata_imx_priv *priv = host->private_data;
    211
    212	ata_host_detach(host);
    213
    214	__raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN);
    215
    216	clk_disable_unprepare(priv->clk);
    217
    218	return 0;
    219}
    220
    221#ifdef CONFIG_PM_SLEEP
    222static int pata_imx_suspend(struct device *dev)
    223{
    224	struct ata_host *host = dev_get_drvdata(dev);
    225	struct pata_imx_priv *priv = host->private_data;
    226
    227	ata_host_suspend(host, PMSG_SUSPEND);
    228
    229	__raw_writel(0, priv->host_regs + PATA_IMX_ATA_INT_EN);
    230	priv->ata_ctl = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
    231	clk_disable_unprepare(priv->clk);
    232
    233	return 0;
    234}
    235
    236static int pata_imx_resume(struct device *dev)
    237{
    238	struct ata_host *host = dev_get_drvdata(dev);
    239	struct pata_imx_priv *priv = host->private_data;
    240
    241	int ret = clk_prepare_enable(priv->clk);
    242	if (ret)
    243		return ret;
    244
    245	__raw_writel(priv->ata_ctl, priv->host_regs + PATA_IMX_ATA_CONTROL);
    246
    247	__raw_writel(PATA_IMX_ATA_INTR_ATA_INTRQ2,
    248			priv->host_regs + PATA_IMX_ATA_INT_EN);
    249
    250	ata_host_resume(host);
    251
    252	return 0;
    253}
    254#endif
    255
    256static SIMPLE_DEV_PM_OPS(pata_imx_pm_ops, pata_imx_suspend, pata_imx_resume);
    257
    258static const struct of_device_id imx_pata_dt_ids[] = {
    259	{
    260		.compatible = "fsl,imx27-pata",
    261	}, {
    262		/* sentinel */
    263	}
    264};
    265MODULE_DEVICE_TABLE(of, imx_pata_dt_ids);
    266
    267static struct platform_driver pata_imx_driver = {
    268	.probe		= pata_imx_probe,
    269	.remove		= pata_imx_remove,
    270	.driver = {
    271		.name		= DRV_NAME,
    272		.of_match_table	= imx_pata_dt_ids,
    273		.pm		= &pata_imx_pm_ops,
    274	},
    275};
    276
    277module_platform_driver(pata_imx_driver);
    278
    279MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
    280MODULE_DESCRIPTION("low-level driver for iMX PATA");
    281MODULE_LICENSE("GPL");
    282MODULE_ALIAS("platform:" DRV_NAME);