Commit fab43e14 authored by Vladimir Zapolskiy's avatar Vladimir Zapolskiy Committed by Tejun Heo

pata: imx: add support of setting timings for PIO modes

The controller is capable to operate in up to PIO4 mode, however
before the change the driver relies on timing settings done by
a bootloader for PIO0 mode only. The change adds more flexibility
in PIO mode selection at runtime and makes the driver to work even if
bootloader does not preset ATA timings.
Signed-off-by: default avatarVladimir Zapolskiy <vz@mleia.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 65a443ea
......@@ -11,7 +11,6 @@
*
* TODO:
* - dmaengine support
* - check if timing stuff needed
*/
#include <linux/ata.h>
......@@ -22,6 +21,16 @@
#define DRV_NAME "pata_imx"
#define PATA_IMX_ATA_TIME_OFF 0x00
#define PATA_IMX_ATA_TIME_ON 0x01
#define PATA_IMX_ATA_TIME_1 0x02
#define PATA_IMX_ATA_TIME_2W 0x03
#define PATA_IMX_ATA_TIME_2R 0x04
#define PATA_IMX_ATA_TIME_AX 0x05
#define PATA_IMX_ATA_TIME_PIO_RDX 0x06
#define PATA_IMX_ATA_TIME_4 0x07
#define PATA_IMX_ATA_TIME_9 0x08
#define PATA_IMX_ATA_CONTROL 0x24
#define PATA_IMX_ATA_CTRL_FIFO_RST_B (1<<7)
#define PATA_IMX_ATA_CTRL_ATA_RST_B (1<<6)
......@@ -31,6 +40,10 @@
#define PATA_IMX_DRIVE_DATA 0xA0
#define PATA_IMX_DRIVE_CONTROL 0xD8
static u32 pio_t4[] = { 30, 20, 15, 10, 10 };
static u32 pio_t9[] = { 20, 15, 10, 10, 10 };
static u32 pio_tA[] = { 35, 35, 35, 35, 35 };
struct pata_imx_priv {
struct clk *clk;
/* timings/interrupt/control regs */
......@@ -38,11 +51,43 @@ struct pata_imx_priv {
u32 ata_ctl;
};
static void pata_imx_set_timing(struct ata_device *adev,
struct pata_imx_priv *priv)
{
struct ata_timing timing;
unsigned long clkrate;
u32 T, mode;
clkrate = clk_get_rate(priv->clk);
if (adev->pio_mode < XFER_PIO_0 || adev->pio_mode > XFER_PIO_4 ||
!clkrate)
return;
T = 1000000000 / clkrate;
ata_timing_compute(adev, adev->pio_mode, &timing, T * 1000, 0);
mode = adev->pio_mode - XFER_PIO_0;
writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_OFF);
writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_ON);
writeb(timing.setup, priv->host_regs + PATA_IMX_ATA_TIME_1);
writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2W);
writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2R);
writeb(1, priv->host_regs + PATA_IMX_ATA_TIME_PIO_RDX);
writeb(pio_t4[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_4);
writeb(pio_t9[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_9);
writeb(pio_tA[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_AX);
}
static void pata_imx_set_piomode(struct ata_port *ap, struct ata_device *adev)
{
struct pata_imx_priv *priv = ap->host->private_data;
u32 val;
pata_imx_set_timing(adev, priv);
val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
if (ata_pio_need_iordy(adev))
val |= PATA_IMX_ATA_CTRL_IORDY_EN;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment