From patchwork Tue Nov 30 03:26:18 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 73517 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 08CA6B70DE for ; Tue, 30 Nov 2010 14:25:00 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5BB34281D8; Tue, 30 Nov 2010 04:24:57 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gdWZsqVulEsd; Tue, 30 Nov 2010 04:24:57 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 79BA7281D1; Tue, 30 Nov 2010 04:24:55 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 25C52281D1 for ; Tue, 30 Nov 2010 04:24:53 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 3BM0ffNvMOcs for ; Tue, 30 Nov 2010 04:24:51 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-fx0-f44.google.com (mail-fx0-f44.google.com [209.85.161.44]) by theia.denx.de (Postfix) with ESMTP id 12FF9281CF for ; Tue, 30 Nov 2010 04:24:49 +0100 (CET) Received: by fxm9 with SMTP id 9so4007221fxm.3 for ; Mon, 29 Nov 2010 19:24:49 -0800 (PST) Received: by 10.223.73.199 with SMTP id r7mr4130489faj.76.1291087489150; Mon, 29 Nov 2010 19:24:49 -0800 (PST) Received: from mashiro.kolej.mff.cuni.cz (vasut.kolej.mff.cuni.cz [78.128.198.52]) by mx.google.com with ESMTPS id n15sm1461020fam.12.2010.11.29.19.24.47 (version=SSLv3 cipher=RC4-MD5); Mon, 29 Nov 2010 19:24:47 -0800 (PST) From: Marek Vasut To: u-boot@lists.denx.de Date: Tue, 30 Nov 2010 04:26:18 +0100 Message-Id: <1291087578-16714-1-git-send-email-marek.vasut@gmail.com> X-Mailer: git-send-email 1.7.2.3 Cc: mahesh.mahadevan@freescale.com Subject: [U-Boot] [PATCH v2] BLOCK: Add freescale IMX51 PATA driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Signed-off-by: Marek Vasut --- v2: Use structures instead of defines as Wolfgang proposed drivers/block/Makefile | 1 + drivers/block/mxc_ata.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 0 deletions(-) create mode 100644 drivers/block/mxc_ata.c diff --git a/drivers/block/Makefile b/drivers/block/Makefile index e27175b..aa7dc87 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o COBJS-$(CONFIG_LIBATA) += libata.o COBJS-$(CONFIG_CMD_MG_DISK) += mg_disk.o COBJS-$(CONFIG_MVSATA_IDE) += mvsata_ide.o +COBJS-$(CONFIG_MX51_PATA) += mxc_ata.o COBJS-$(CONFIG_PATA_BFIN) += pata_bfin.o COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o diff --git a/drivers/block/mxc_ata.c b/drivers/block/mxc_ata.c new file mode 100644 index 0000000..62c5cf4 --- /dev/null +++ b/drivers/block/mxc_ata.c @@ -0,0 +1,149 @@ +/* + * Freescale iMX51 ATA driver + * + * Copyright (C) 2010 Marek Vasut + * + * Based on code by: + * Mahesh Mahadevan + * + * Based on code from original FSL ATA driver, which is + * part of eCos, the Embedded Configurable Operating System. + * Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* MXC ATA register offsets */ +struct mxc_ata_config_regs { + u8 time_off; /* 0x00 */ + u8 time_on; + u8 time_1; + u8 time_2w; + u8 time_2r; + u8 time_ax; + u8 time_pio_rdx; + u8 time_4; + u8 time_9; + u8 time_m; + u8 time_jn; + u8 time_d; + u8 time_k; + u8 time_ack; + u8 time_env; + u8 time_udma_rdx; + u8 time_zah; /* 0x10 */ + u8 time_mlix; + u8 time_dvh; + u8 time_dzfs; + u8 time_dvs; + u8 time_cvh; + u8 time_ss; + u8 time_cyc; + u32 fifo_data_32; /* 0x18 */ + u32 fifo_data_16; + u32 fifo_fill; + u32 ata_control; + u32 interrupt_pending; + u32 interrupt_enable; + u32 interrupt_clear; + u32 fifo_alarm; +}; + +struct mxc_data_hdd_regs { + u32 drive_data; /* 0xa0 */ + u32 drive_features; + u32 drive_sector_count; + u32 drive_sector_num; + u32 drive_cyl_low; + u32 drive_cyl_high; + u32 drive_dev_head; + u32 command; + u32 status; + u32 alt_status; +}; + +/* PIO timing table */ +#define NR_PIO_SPECS 5 +uint16_t pio_t0[NR_PIO_SPECS] = { 600, 383, 240, 180, 120 }; +uint16_t pio_t1[NR_PIO_SPECS] = { 70, 50, 30, 30, 25 }; +uint16_t pio_t2_8[NR_PIO_SPECS] = { 290, 290, 290, 80, 70 }; +uint16_t pio_t2_16[NR_PIO_SPECS] = { 165, 125, 100, 80, 70 }; +uint16_t pio_t2i[NR_PIO_SPECS] = { 40, 0, 0, 0, 0 }; +uint16_t pio_t4[NR_PIO_SPECS] = { 30, 20, 15, 10, 10 }; +uint16_t pio_t9[NR_PIO_SPECS] = { 20, 15, 10, 10, 10 }; +uint16_t pio_tA[NR_PIO_SPECS] = { 50, 50, 50, 50, 50 }; + +#define REG2OFF(reg) ((((uint32_t)reg) & 0x3) * 8) +static void set_ata_bus_timing(unsigned char mode) +{ + uint32_t val; + uint32_t T = 1000000000 / mxc_get_clock(MXC_IPG_CLK); + + struct mxc_ata_config_regs *ata_cfg_regs; + ata_cfg_regs = (struct mxc_ata_config_regs *)CONFIG_SYS_ATA_BASE_ADDR; + + if (mode >= NR_PIO_SPECS) + return; + + /* Write TIME_OFF/ON/1/2W */ + val = (3 << REG2OFF(&ata_cfg_regs->time_off)) | + (3 << REG2OFF(&ata_cfg_regs->time_on)) | + (((pio_t1[mode] + T) / T) << REG2OFF(&ata_cfg_regs->time_1)) | + (((pio_t2_8[mode] + T) / T) << REG2OFF(&ata_cfg_regs->time_2w)); + writel(val, &ata_cfg_regs->time_off); + + /* Write TIME_2R/AX/RDX/4 */ + val = (((pio_t2_8[mode] + T) / T) << REG2OFF(&ata_cfg_regs->time_2r)) | + (((pio_tA[mode] + T) / T + 2) << REG2OFF(&ata_cfg_regs->time_ax)) | + (1 << REG2OFF(&ata_cfg_regs->time_pio_rdx)) | + (((pio_t4[mode] + T) / T) << REG2OFF(&ata_cfg_regs->time_4)); + writel(val, &ata_cfg_regs->time_2r); + + /* Write TIME_9 ; the rest of timing registers is irrelevant for PIO */ + val = (((pio_t9[mode] + T) / T) << REG2OFF(&ata_cfg_regs->time_9)); + writel(val, &ata_cfg_regs->time_9); +} + +int ide_preinit(void) +{ + struct mxc_ata_config_regs *ata_cfg_regs; + ata_cfg_regs = (struct mxc_ata_config_regs *)CONFIG_SYS_ATA_BASE_ADDR; + + /* 46.3.3.4 @ FSL iMX51 manual */ + /* FIFO normal op., drive reset */ + writel(0x80, &ata_cfg_regs->ata_control); + /* FIFO normal op., drive not reset */ + writel(0xc0, &ata_cfg_regs->ata_control); + + /* Configure the PIO timing */ + set_ata_bus_timing(CONFIG_MXC_ATA_PIO_MODE); + + /* 46.3.3.4 @ FSL iMX51 manual */ + /* Drive not reset, IORDY handshake */ + writel(0x41, &ata_cfg_regs->ata_control); + + return 0; +}