linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Palmchip BK3710 IDE driver
@ 2008-01-17 18:50 Anton Salnikov
  2008-01-17 18:57 ` Sergei Shtylyov
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Anton Salnikov @ 2008-01-17 18:50 UTC (permalink / raw)
  To: linux-ide; +Cc: bzolnier

This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
Supports interface to compact Flash (CF) configured in True-IDE mode.

I had to export two functions (ide_dma_exec_cmd and __ide_dma_test_irq) from 
driver/ide/ide-dma.c to get rid of copying them.

Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
---

 drivers/ide/Kconfig           |    8 
 drivers/ide/arm/Makefile      |    1 
 drivers/ide/arm/palm_bk3710.c |  486 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ide/ide-dma.c         |    6 
 drivers/ide/ide-proc.c        |    1 
 include/linux/ide.h           |    4 
 6 files changed, 503 insertions(+), 3 deletions(-)

Index: 2.6.24-rc7.ide/drivers/ide/Kconfig
===================================================================
--- 2.6.24-rc7.ide.orig/drivers/ide/Kconfig
+++ 2.6.24-rc7.ide/drivers/ide/Kconfig
@@ -1008,6 +1008,14 @@ config BLK_DEV_Q40IDE
 	  normally be on; disable it only if you are running a custom hard
 	  drive subsystem through an expansion card.
 
+config BLK_DEV_PALMCHIP_BK3710
+	bool "Palmchip bk3710 IDE controller support"
+	depends on ARCH_DAVINCI
+	select BLK_DEV_IDEDMA_PCI
+	help
+	  Say Y here if you want to support the onchip IDE controller on the
+	  TI DaVinci SoC
+
 config BLK_DEV_MPC8xx_IDE
 	bool "MPC8xx IDE support"
 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
BLK_DEV_IDE=y && !PPC_MERGE
Index: 2.6.24-rc7.ide/drivers/ide/arm/Makefile
===================================================================
--- 2.6.24-rc7.ide.orig/drivers/ide/arm/Makefile
+++ 2.6.24-rc7.ide/drivers/ide/arm/Makefile
@@ -2,5 +2,6 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
Index: 2.6.24-rc7.ide/drivers/ide/arm/palm_bk3710.c
===================================================================
--- /dev/null
+++ 2.6.24-rc7.ide/drivers/ide/arm/palm_bk3710.c
@@ -0,0 +1,486 @@
+/*
+ * Palmchip bk3710 IDE controller
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Oct 2005, Swaminathan S
+ -
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Offset of the primary interface registers */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
+
+/* Primary Control Offset */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
+
+/*
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+struct palm_bk3710_udmatiming {
+	unsigned int rptime;	/* Ready to pause time  */
+	unsigned int cycletime;	/* Cycle Time           */
+};
+
+/*
+ * Register Layout Structure for DmaEngine
+ */
+struct palm_bk3710_dmaengineregs {
+	unsigned short bmicp;
+	unsigned short bmisp;
+	unsigned int bmidtp;
+	unsigned short bmics;
+	unsigned short bmiss;
+	unsigned int bmidts;
+};
+
+/*
+ * Register Layout Structure for Config
+ */
+struct palm_bk3710_ideconfigregs {
+	unsigned short idetimp __attribute__((packed));
+	unsigned short idetims __attribute__((packed));
+	unsigned char sidetim;
+	unsigned short slewctl __attribute__((packed));
+	unsigned char idestatus;
+	unsigned short udmactl __attribute__((packed));
+	unsigned short udmatim __attribute__((packed));
+	unsigned char rsvd0[4];
+	unsigned int miscctl __attribute__((packed));
+	unsigned int regstb __attribute__((packed));
+	unsigned int regrcvr __attribute__((packed));
+	unsigned int datstb __attribute__((packed));
+	unsigned int datrcvr __attribute__((packed));
+	unsigned int dmastb __attribute__((packed));
+	unsigned int dmarcvr __attribute__((packed));
+	unsigned int udmastb __attribute__((packed));
+	unsigned int udmatrp __attribute__((packed));
+	unsigned int udmaenv __attribute__((packed));
+	unsigned int iordytmp __attribute__((packed));
+	unsigned int iordytms __attribute__((packed));
+};
+
+/*
+ * Register Layout Structure
+ */
+struct palm_bk3710_ideregs {
+	struct palm_bk3710_dmaengineregs dmaengine;
+	unsigned char rsvd0[48];
+	struct palm_bk3710_ideconfigregs config;
+};
+
+#include "../ide-timing.h"
+
+static ide_hwif_t *palm_bk3710_hwif;
+static struct palm_bk3710_ideregs __iomem *palm_bk3710_base;
+static long ide_palm_clk;
+
+static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
+	{160, 240},		/* UDMA Mode 0 */
+	{125, 160},		/* UDMA Mode 1 */
+	{100, 120},		/* UDMA Mode 2 */
+	{100, 90},		/* UDMA Mode 3 */
+	{85,  60},		/* UDMA Mode 4 */
+	{85,  40}		/* UDMA Mode 5 */
+};
+
+static struct clk *ideclkp;
+
+static void palm_bk3710_setudmamode(unsigned int dev, unsigned int level)
+{
+	char ide_tenv, ide_trp, ide_t0;
+
+	/* DMA Data Setup */
+	ide_t0 = (palm_bk3710_udmatimings[level].cycletime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+	ide_tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+	ide_trp = (palm_bk3710_udmatimings[level].rptime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+
+
+	if (!dev) {
+		/* setup master device parameters */
+
+		/* udmatim Register */
+		palm_bk3710_base->config.udmatim &= 0xFFF0;
+		palm_bk3710_base->config.udmatim |= level;
+		/* udmastb Ultra DMA Access Strobe Width */
+		palm_bk3710_base->config.udmastb &= 0xFF00;
+		palm_bk3710_base->config.udmastb |= ide_t0;
+		/* udmatrp Ultra DMA Ready to Pause Time */
+		palm_bk3710_base->config.udmatrp &= 0xFF00;
+		palm_bk3710_base->config.udmatrp |= ide_trp;
+		/* udmaenv Ultra DMA envelop Time */
+		palm_bk3710_base->config.udmaenv &= 0xFF00;
+		palm_bk3710_base->config.udmaenv |= ide_tenv;
+		/* Enable UDMA for Device 0 */
+		palm_bk3710_base->config.udmactl |= 1;
+	} else {
+		/* setup slave device parameters */
+
+		/* udmatim Register */
+		palm_bk3710_base->config.udmatim &= 0xFF0F;
+		palm_bk3710_base->config.udmatim |= (level << 4);
+		/* udmastb Ultra DMA Access Strobe Width */
+		palm_bk3710_base->config.udmastb &= 0xFF;
+		palm_bk3710_base->config.udmastb |= (ide_t0 << 8);
+		/* udmatrp Ultra DMA Ready to Pause Time */
+		palm_bk3710_base->config.udmatrp &= 0xFF;
+		palm_bk3710_base->config.udmatrp |= (ide_trp << 8);
+		/* udmaenv Ultra DMA envelop Time */
+		palm_bk3710_base->config.udmaenv &= 0xFF;
+		palm_bk3710_base->config.udmaenv |= (ide_tenv << 8);
+		/* Enable UDMA for Device 1 */
+		palm_bk3710_base->config.udmactl |= (1 << 1);
+	}
+}
+
+static void palm_bk3710_setdmamode(unsigned int dev, unsigned int cycletime,
+				  unsigned int mode)
+{
+	char ide_td, ide_tkw, ide_t0;
+
+	if (cycletime < ide_timing[mode].cycle)
+		cycletime = ide_timing[mode].cycle;
+
+	/* DMA Data Setup */
+	ide_t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	ide_td = (ide_timing[mode].active + ide_palm_clk - 1) / ide_palm_clk;
+	ide_tkw = ide_t0 - ide_td - 1;
+	ide_td -= 1;
+
+	if (!dev) {
+		/* setup master device parameters */
+		palm_bk3710_base->config.dmastb &= 0xFF00;
+		palm_bk3710_base->config.dmastb |= ide_td;
+		palm_bk3710_base->config.dmarcvr &= 0xFF00;
+		palm_bk3710_base->config.dmarcvr |= ide_tkw;
+		/* Disable UDMA for Device 0 */
+		palm_bk3710_base->config.udmactl &= 0xFF02;
+	} else {
+		/* setup slave device parameters */
+		palm_bk3710_base->config.dmastb &= 0xFF;
+		palm_bk3710_base->config.dmastb |= (ide_td << 8);
+		palm_bk3710_base->config.dmarcvr &= 0xFF;
+		palm_bk3710_base->config.dmarcvr |= (ide_tkw << 8);
+		/* Disable UDMA for Device 1 */
+		palm_bk3710_base->config.udmactl &= 0xFF01;
+	}
+}
+
+static void palm_bk3710_setpiomode(ide_drive_t *mate, unsigned int dev,
+				  unsigned int cycletime, unsigned int mode)
+{
+	char ide_t2, ide_t2i, ide_t0;
+
+	/* PIO Data Setup */
+	ide_t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	ide_t2 = (ide_timing[19 - mode].active + ide_palm_clk - 1)
+			/ ide_palm_clk;
+
+	ide_t2i = ide_t0 - ide_t2 - 1;
+	ide_t2 -= 1;
+
+	if (!dev) {
+		/* setup master device parameters */
+		palm_bk3710_base->config.datstb &= 0xFF00;
+		palm_bk3710_base->config.datstb |= ide_t2;
+		palm_bk3710_base->config.datrcvr &= 0xFF00;
+		palm_bk3710_base->config.datrcvr |= ide_t2i;
+	} else {
+		/* setup slave device parameters */
+		palm_bk3710_base->config.datstb &= 0xFF;
+		palm_bk3710_base->config.datstb |= (ide_t2 << 8);
+		palm_bk3710_base->config.datrcvr &= 0xFF;
+		palm_bk3710_base->config.datrcvr |= (ide_t2i << 8);
+	}
+
+	if (mate && mate->present) {
+		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+
+		if (mode2 < mode)
+			mode = mode2;
+	}
+
+	/* TASKFILE Setup */
+	ide_t0 = (ide_timing[19 - mode].cyc8b + ide_palm_clk - 1)
+			/ ide_palm_clk;
+	ide_t2 = (ide_timing[19 - mode].act8b + ide_palm_clk - 1)
+			/ ide_palm_clk;
+	ide_t2i = ide_t0 - ide_t2 - 1;
+	ide_t2 -= 1;
+
+	if (!dev) {
+		/* setup master device parameters */
+		palm_bk3710_base->config.regstb &= 0xFF00;
+		palm_bk3710_base->config.regstb |= ide_t2;
+		palm_bk3710_base->config.regrcvr &= 0xFF00;
+		palm_bk3710_base->config.regrcvr |= ide_t2i;
+	} else {
+		/* setup slave device parameters */
+		palm_bk3710_base->config.regstb &= 0xFF;
+		palm_bk3710_base->config.regstb |= (ide_t2 << 8);
+		palm_bk3710_base->config.regrcvr &= 0xFF;
+		palm_bk3710_base->config.regrcvr |= (ide_t2i << 8);
+	}
+}
+
+static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+{
+	int is_slave = drive->dn & 1;
+
+	switch (xferspeed) {
+	case XFER_UDMA_4:
+	case XFER_UDMA_3:
+	case XFER_UDMA_2:
+	case XFER_UDMA_1:
+	case XFER_UDMA_0:
+		palm_bk3710_setudmamode(is_slave, xferspeed - XFER_UDMA_0);
+		break;
+	case XFER_MW_DMA_2:
+	case XFER_MW_DMA_1:
+	case XFER_MW_DMA_0:
+		{
+			int nspeed = 10 - xferspeed + XFER_MW_DMA_0;
+			unsigned ide_cycle = max(ide_timing[nspeed].cycle,
+					     drive->id->eide_dma_min);
+
+			palm_bk3710_setdmamode(is_slave, ide_cycle, nspeed);
+		}
+		break;
+	}
+}
+
+static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+	unsigned int cycle_time;
+	int is_slave = drive->dn & 1;
+	ide_drive_t *mate;
+
+	/*
+	 * Get the best PIO Mode supported by the drive
+	 * Obtain the drive PIO data for tuning the Palm Chip registers
+	 */
+	cycle_time = ide_pio_cycle_time(drive, pio);
+	mate = ide_get_paired_drive(drive);
+	palm_bk3710_setpiomode(mate, is_slave, cycle_time, pio);
+}
+
+static void palm_bk3710_chipinit(void)
+{
+	/*
+	 * enable the reset_en of ATA controller so that when ata signals
+	 * are brought out, by writing into device config. at that
+	 * time por_n signal should not be 'Z' and have a stable value.
+	 */
+	palm_bk3710_base->config.miscctl = 0x0300;
+
+	/* wait for some time and deassert the reset of ATA Device. */
+	mdelay(100);
+
+	/* Deassert the Reset */
+	palm_bk3710_base->config.miscctl = 0x0200;
+
+	/*
+	 * Program the IDETIMP Register Value based on the following assumptions
+	 *
+	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
+	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
+	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
+	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
+	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
+	 */
+
+	palm_bk3710_base->config.idetimp = 0xb388;
+
+	/*
+	 * Configure  SIDETIM  Register
+	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
+	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
+	 */
+	palm_bk3710_base->config.sidetim = 0;
+
+	/*
+	 * UDMACTL Ultra-ATA DMA Control
+	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
+	 * (ATA_UDMACTL_UDMAP0	, 0 )
+	 *
+	 */
+	palm_bk3710_base->config.udmactl = 0;
+
+	/*
+	 * MISCCTL Miscellaneous Conrol Register
+	 * (ATA_MISCCTL_RSTMODEP	, 1) |
+	 * (ATA_MISCCTL_RESETP		, 0) |
+	 * (ATA_MISCCTL_TIMORIDE	, 1)
+	 */
+	palm_bk3710_base->config.miscctl = 0x201;
+
+	/*
+	 * IORDYTMP IORDY Timer for Primary Register
+	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+	 */
+
+	palm_bk3710_base->config.iordytmp = 0xffff;
+
+	/*
+	 * Configure BMISP Register
+	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
+	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
+	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
+	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
+	 * (ATA_BMISP_DMAERROR	, CLEAR)
+	 */
+
+	palm_bk3710_base->dmaengine.bmisp = 0;
+
+	palm_bk3710_setpiomode(NULL, 0, 0, 0);
+	palm_bk3710_setpiomode(NULL, 1, 0, 0);
+}
+
+int palm_bk3710_probe(struct platform_device *pdev)
+{
+	hw_regs_t ide_ctlr_info;
+	int index = 0;
+	int pribase;
+	struct clk *clkp;
+	struct resource *mem, *irq;
+
+	clkp = clk_get(NULL, "IDECLK");
+	if (IS_ERR(clkp))
+		return -ENODEV;
+
+	ideclkp = clkp;
+	clk_enable(ideclkp);
+	ide_palm_clk = clk_get_rate(ideclkp)/100000;
+	ide_palm_clk = (10000/ide_palm_clk) + 1;
+	/* Register the IDE interface with Linux ATA Interface */
+	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem == NULL) {
+		printk(KERN_INFO "failed to get memory region resource\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq == NULL) {
+		printk(KERN_INFO "failed to get IRQ resource\n");
+		return -ENODEV;
+	}
+
+	palm_bk3710_base = (struct palm_bk3710_ideregs __iomem *)mem->start;
+	/* Configure the Palm Chip controller */
+	palm_bk3710_chipinit();
+
+	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
+	for (index = 0; index < IDE_NR_PORTS - 2; index++)
+		ide_ctlr_info.io_ports[index] = pribase + index;
+	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
+			IDE_PALM_ATA_PRI_CTL_OFFSET;
+	ide_ctlr_info.irq = irq->start;
+	ide_ctlr_info.chipset = ide_palm3710;
+	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &palm_bk3710_hwif) < 0) {
+		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
+		return -ENODEV;
+	}
+
+	palm_bk3710_hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
+	palm_bk3710_hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
+
+	palm_bk3710_hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
+						(input clk 99MHz) */
+	palm_bk3710_hwif->mwdma_mask = 0x7;
+	palm_bk3710_hwif->drives[0].autotune = 1;
+	palm_bk3710_hwif->drives[1].autotune = 1;
+
+	if (!request_region(mem->start, 8, palm_bk3710_hwif->name)) {
+		printk(KERN_ERR "Error, ports in use.\n");
+		return -EBUSY;
+	}
+
+	palm_bk3710_hwif->dmatable_cpu = dma_alloc_coherent(
+				NULL,
+				PRD_ENTRIES * PRD_BYTES,
+				&palm_bk3710_hwif->dmatable_dma,
+				GFP_ATOMIC);
+
+	if (!palm_bk3710_hwif->dmatable_cpu) {
+		printk(KERN_ERR "Error, unable to allocate DMA table.\n");
+		return -ENOMEM;
+	}
+
+	palm_bk3710_hwif->dma_base = mem->start;
+
+	palm_bk3710_hwif->dma_master = mem->start;
+
+	palm_bk3710_hwif->dma_command = mem->start;
+	palm_bk3710_hwif->dma_status = mem->start + 2;
+	palm_bk3710_hwif->dma_prdtable = mem->start + 4;
+
+	palm_bk3710_hwif->dma_off_quietly = &ide_dma_off_quietly;
+	palm_bk3710_hwif->ide_dma_on = &__ide_dma_on;
+	palm_bk3710_hwif->dma_host_off = &ide_dma_host_off;
+	palm_bk3710_hwif->dma_host_on = &ide_dma_host_on;
+	palm_bk3710_hwif->dma_setup = &ide_dma_setup;
+	palm_bk3710_hwif->dma_exec_cmd = &ide_dma_exec_cmd;
+	palm_bk3710_hwif->dma_start = &ide_dma_start;
+	palm_bk3710_hwif->ide_dma_end = &__ide_dma_end;
+	palm_bk3710_hwif->ide_dma_test_irq = &__ide_dma_test_irq;
+	palm_bk3710_hwif->dma_timeout = &ide_dma_timeout;
+	palm_bk3710_hwif->dma_lost_irq = &ide_dma_lost_irq;
+
+	return 0;
+}
+
+static struct platform_driver platform_bk_driver = {
+	.driver = {
+		.name = "palm_bk3710",
+	},
+	.probe = palm_bk3710_probe,
+	.remove = NULL,
+};
+
+int palm_bk3710_init(void)
+{
+	return platform_driver_register(&platform_bk_driver);
+}
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
+
Index: 2.6.24-rc7.ide/drivers/ide/ide-dma.c
===================================================================
--- 2.6.24-rc7.ide.orig/drivers/ide/ide-dma.c
+++ 2.6.24-rc7.ide/drivers/ide/ide-dma.c
@@ -556,11 +556,12 @@ int ide_dma_setup(ide_drive_t *drive)
 
 EXPORT_SYMBOL_GPL(ide_dma_setup);
 
-static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
+void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
 {
 	/* issue cmd to drive */
 	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, 
dma_timer_expiry);
 }
+EXPORT_SYMBOL(ide_dma_exec_cmd);
 
 void ide_dma_start(ide_drive_t *drive)
 {
@@ -606,7 +607,7 @@ int __ide_dma_end (ide_drive_t *drive)
 EXPORT_SYMBOL(__ide_dma_end);
 
 /* returns 1 if dma irq issued, 0 otherwise */
-static int __ide_dma_test_irq(ide_drive_t *drive)
+int __ide_dma_test_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	u8 dma_stat		= hwif->INB(hwif->dma_status);
@@ -619,6 +620,7 @@ static int __ide_dma_test_irq(ide_drive_
 			drive->name, __FUNCTION__);
 	return 0;
 }
+EXPORT_SYMBOL(__ide_dma_test_irq);
 #else
 static inline int config_drive_for_dma(ide_drive_t *drive) { return 0; }
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
Index: 2.6.24-rc7.ide/drivers/ide/ide-proc.c
===================================================================
--- 2.6.24-rc7.ide.orig/drivers/ide/ide-proc.c
+++ 2.6.24-rc7.ide/drivers/ide/ide-proc.c
@@ -67,6 +67,7 @@ static int proc_ide_read_imodel
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
 		case ide_au1xxx:	name = "au1xxx";	break;
+		case ide_palm3710:      name = "palm3710";      break;
 		case ide_etrax100:	name = "etrax100";	break;
 		case ide_acorn:		name = "acorn";		break;
 		default:		name = "(unknown)";	break;
Index: 2.6.24-rc7.ide/include/linux/ide.h
===================================================================
--- 2.6.24-rc7.ide.orig/include/linux/ide.h
+++ 2.6.24-rc7.ide/include/linux/ide.h
@@ -202,7 +202,7 @@ enum {		ide_unknown,	ide_generic,	ide_pc
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_au1xxx, ide_forced
+		ide_au1xxx,	ide_palm3710,	ide_forced
 };
 
 typedef u8 hwif_chipset_t;
@@ -1280,8 +1280,10 @@ void ide_dma_off_quietly(ide_drive_t *);
 void ide_dma_host_on(ide_drive_t *);
 extern int __ide_dma_on(ide_drive_t *);
 extern int ide_dma_setup(ide_drive_t *);
+extern void ide_dma_exec_cmd(ide_drive_t *drive, u8 command);
 extern void ide_dma_start(ide_drive_t *);
 extern int __ide_dma_end(ide_drive_t *);
+extern int __ide_dma_test_irq(ide_drive_t *drive);
 extern void ide_dma_lost_irq(ide_drive_t *);
 extern void ide_dma_timeout(ide_drive_t *);
 #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-17 18:50 [PATCH] Palmchip BK3710 IDE driver Anton Salnikov
@ 2008-01-17 18:57 ` Sergei Shtylyov
  2008-01-17 23:23 ` Alan Cox
  2008-01-18 22:19 ` Bartlomiej Zolnierkiewicz
  2 siblings, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-17 18:57 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

Hello.

Anton Salnikov wrote:

> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

> I had to export two functions (ide_dma_exec_cmd and __ide_dma_test_irq) from 
> driver/ide/ide-dma.c to get rid of copying them.

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>

Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-17 18:50 [PATCH] Palmchip BK3710 IDE driver Anton Salnikov
  2008-01-17 18:57 ` Sergei Shtylyov
@ 2008-01-17 23:23 ` Alan Cox
  2008-01-18 14:14   ` Sergei Shtylyov
  2008-01-18 22:19 ` Bartlomiej Zolnierkiewicz
  2 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2008-01-17 23:23 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

On Thu, 17 Jan 2008 21:50:56 +0300
Anton Salnikov <asalnikov@ru.mvista.com> wrote:

> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

New drivers should really be going at least parallel into drivers/ata and
legacy IDE.

> +struct palm_bk3710_ideconfigregs {
> +	unsigned short idetimp __attribute__((packed));
> +	unsigned short idetims __attribute__((packed));
> +	unsigned char sidetim;
> +	unsigned short slewctl __attribute__((packed));
> +	unsigned char idestatus;
> +	unsigned short udmactl __attribute__((packed));
> +	unsigned short udmatim __attribute__((packed));
> +	unsigned char rsvd0[4];
> +	unsigned int miscctl __attribute__((packed));
> +	unsigned int regstb __attribute__((packed));

NAK - the size of an unsigned int in the kernel isn't defined. All the
packed stuff is also horribly platform dependant. True the driver is ARM
only currently but that doesn't make it a good idea.

Can't you use defined offsets ?


> +struct palm_bk3710_ideregs {
> +	struct palm_bk3710_dmaengineregs dmaengine;

So why are only some packed ?

> +		/* udmatim Register */
> +		palm_bk3710_base->config.udmatim &= 0xFFF0;
> +		palm_bk3710_base->config.udmatim |= level;

Direct memory access to I/O space - should be using read/write functions


> +	if (mate && mate->present) {
> +		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);

If the pair device is present but not in the best mode it can do this
will be wrong surely ?


> +	if (!request_region(mem->start, 8, palm_bk3710_hwif->name)) {
> +		printk(KERN_ERR "Error, ports in use.\n");
> +		return -EBUSY;
> +	}
> +
> +	palm_bk3710_hwif->dmatable_cpu = dma_alloc_coherent(
> +				NULL,
> +				PRD_ENTRIES * PRD_BYTES,
> +				&palm_bk3710_hwif->dmatable_dma,
> +				GFP_ATOMIC);
> +
> +	if (!palm_bk3710_hwif->dmatable_cpu) {

Leaks the reserved region

> +		printk(KERN_ERR "Error, unable to allocate DMA table.\n");
> +		return -ENOMEM;
> +	}

> -static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
> +void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
>  {
>  	/* issue cmd to drive */
>  	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, 
> dma_timer_expiry);
>  }
> +EXPORT_SYMBOL(ide_dma_exec_cmd);

These are not needed the NULL default request will fill them in for you

Alan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-17 23:23 ` Alan Cox
@ 2008-01-18 14:14   ` Sergei Shtylyov
  2008-01-18 15:04     ` Alan Cox
  0 siblings, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-18 14:14 UTC (permalink / raw)
  To: Alan Cox; +Cc: Anton Salnikov, linux-ide, bzolnier

Hello.

Alan Cox wrote:

>>This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
>>The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
>>Supports interface to compact Flash (CF) configured in True-IDE mode.

> New drivers should really be going at least parallel into drivers/ata and
> legacy IDE.

    Alas, it's unlikely that we can spend more time on developing libata 
equivalent which we don't need at this point.

>>+struct palm_bk3710_ideconfigregs {
>>+	unsigned short idetimp __attribute__((packed));
>>+	unsigned short idetims __attribute__((packed));
>>+	unsigned char sidetim;
>>+	unsigned short slewctl __attribute__((packed));
>>+	unsigned char idestatus;
>>+	unsigned short udmactl __attribute__((packed));
>>+	unsigned short udmatim __attribute__((packed));
>>+	unsigned char rsvd0[4];
>>+	unsigned int miscctl __attribute__((packed));
>>+	unsigned int regstb __attribute__((packed));

> NAK - the size of an unsigned int in the kernel isn't defined. All the
> packed stuff is also horribly platform dependant. True the driver is ARM
> only currently but that doesn't make it a good idea.

> Can't you use defined offsets ?

>>+struct palm_bk3710_ideregs {
>>+	struct palm_bk3710_dmaengineregs dmaengine;

> So why are only some packed ?

>>+		/* udmatim Register */
>>+		palm_bk3710_base->config.udmatim &= 0xFFF0;
>>+		palm_bk3710_base->config.udmatim |= level;

> Direct memory access to I/O space - should be using read/write functions

    Sigh, I was anticipationg that somebody would say that... :-)

>>+	if (mate && mate->present) {
>>+		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);

> If the pair device is present but not in the best mode it can do this
> will be wrong surely ?

    Why?  ATA/PI says in the note to the table "Register transfer to/from device":

5 Mode shall be selected no higher than the *highest* mode supported by the 
*slowest* device.

    Some other drivers are already using the same code (I'm not even sure it's 
needed here -- never saw the chip documentation).

>>+	if (!request_region(mem->start, 8, palm_bk3710_hwif->name)) {
>>+		printk(KERN_ERR "Error, ports in use.\n");
>>+		return -EBUSY;
>>+	}
>>+
>>+	palm_bk3710_hwif->dmatable_cpu = dma_alloc_coherent(
>>+				NULL,
>>+				PRD_ENTRIES * PRD_BYTES,
>>+				&palm_bk3710_hwif->dmatable_dma,
>>+				GFP_ATOMIC);
>>+
>>+	if (!palm_bk3710_hwif->dmatable_cpu) {

> Leaks the reserved region

    My bad -- I've managed to overlook this while reviewing.

>>+		printk(KERN_ERR "Error, unable to allocate DMA table.\n");
>>+		return -ENOMEM;
>>+	}

>>-static void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
>>+void ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
>> {
>> 	/* issue cmd to drive */
>> 	ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, 
>>dma_timer_expiry);
>> }
>>+EXPORT_SYMBOL(ide_dma_exec_cmd);

> These are not needed the NULL default request will fill them in for you

    It won't -- we can *not* call ide_setup_dma() which fills them out as this 
is not a PCI chip.

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-18 14:14   ` Sergei Shtylyov
@ 2008-01-18 15:04     ` Alan Cox
  2008-01-18 18:03       ` Sergei Shtylyov
  0 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2008-01-18 15:04 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Anton Salnikov, linux-ide, bzolnier

> >>+		/* udmatim Register */
> >>+		palm_bk3710_base->config.udmatim &= 0xFFF0;
> >>+		palm_bk3710_base->config.udmatim |= level;
> 
> > Direct memory access to I/O space - should be using read/write functions
> 
>     Sigh, I was anticipationg that somebody would say that... :-)

Well yes - its not very nice code and it isn't really upstream to scratch.

>     Why?  ATA/PI says in the note to the table "Register transfer to/from device":
> 
> 5 Mode shall be selected no higher than the *highest* mode supported by the 
> *slowest* device.

You are correct, ignore that. You don't touch the timing for the other
device.

>     It won't -- we can *not* call ide_setup_dma() which fills them out as this 
> is not a PCI chip.

Gak.

Alan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-18 15:04     ` Alan Cox
@ 2008-01-18 18:03       ` Sergei Shtylyov
  2008-01-18 22:20         ` Bartlomiej Zolnierkiewicz
  0 siblings, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-18 18:03 UTC (permalink / raw)
  To: Alan Cox; +Cc: Anton Salnikov, linux-ide, bzolnier

Alan Cox wrote:

>>    It won't -- we can *not* call ide_setup_dma() which fills them out as this 
>>is not a PCI chip.

> Gak.

    Or maybe we still can -- with hwif->mmio set?
    AFAIR (from the 2006 discussion) Bart said it's *only* for PCI devices...

> Alan

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-17 18:50 [PATCH] Palmchip BK3710 IDE driver Anton Salnikov
  2008-01-17 18:57 ` Sergei Shtylyov
  2008-01-17 23:23 ` Alan Cox
@ 2008-01-18 22:19 ` Bartlomiej Zolnierkiewicz
  2 siblings, 0 replies; 27+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-01-18 22:19 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, Alan Cox, Sergei Shtylyov


Hi,

On Thursday 17 January 2008, Anton Salnikov wrote:
> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

Thanks, overall it looks good but the way in which controller registers are
accessed needs to be reworked according to Alan's comments before this driver
can be accepted in the mainline.

> I had to export two functions (ide_dma_exec_cmd and __ide_dma_test_irq) from 
> driver/ide/ide-dma.c to get rid of copying them.

Please make the exports _GPL.

Also some minor comments below.

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
> ---
> 
>  drivers/ide/Kconfig           |    8 
>  drivers/ide/arm/Makefile      |    1 
>  drivers/ide/arm/palm_bk3710.c |  486 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/ide/ide-dma.c         |    6 
>  drivers/ide/ide-proc.c        |    1 
>  include/linux/ide.h           |    4 
>  6 files changed, 503 insertions(+), 3 deletions(-)
> 
> Index: 2.6.24-rc7.ide/drivers/ide/Kconfig
> ===================================================================
> --- 2.6.24-rc7.ide.orig/drivers/ide/Kconfig
> +++ 2.6.24-rc7.ide/drivers/ide/Kconfig
> @@ -1008,6 +1008,14 @@ config BLK_DEV_Q40IDE
>  	  normally be on; disable it only if you are running a custom hard
>  	  drive subsystem through an expansion card.
>  
> +config BLK_DEV_PALMCHIP_BK3710
> +	bool "Palmchip bk3710 IDE controller support"

tristate?

> +	depends on ARCH_DAVINCI
> +	select BLK_DEV_IDEDMA_PCI
> +	help
> +	  Say Y here if you want to support the onchip IDE controller on the
> +	  TI DaVinci SoC

[...]

> Index: 2.6.24-rc7.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.24-rc7.ide/drivers/ide/arm/palm_bk3710.c
> @@ -0,0 +1,486 @@
> +/*
> + * Palmchip bk3710 IDE controller
> + *
> + * Copyright (C) 2006 Texas Instruments.
> + * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>

[...]

> + Modifications:
> + ver. 1.0: Oct 2005, Swaminathan S
> + -

I would prefer revision history to be removed if possible (we keep changelogs
in git tree, also the date doesn't match with Copyrights notice).

[...]

> +static ide_hwif_t *palm_bk3710_hwif;

palm_bk3710_hwif is only accessed in palm_bk3710_probe() so may be as well
moved there (+ renamed to hwif to match usual naming used by other drivers)

> +static struct palm_bk3710_ideregs __iomem *palm_bk3710_base;
> +static long ide_palm_clk;
> +
> +static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
> +	{160, 240},		/* UDMA Mode 0 */
> +	{125, 160},		/* UDMA Mode 1 */
> +	{100, 120},		/* UDMA Mode 2 */
> +	{100, 90},		/* UDMA Mode 3 */
> +	{85,  60},		/* UDMA Mode 4 */
> +	{85,  40}		/* UDMA Mode 5 */
> +};

Hmmm, but palm_bk3710_probe() limits max UDMA to UDMA4...?

> +static struct clk *ideclkp;
> +
> +static void palm_bk3710_setudmamode(unsigned int dev, unsigned int level)

'level' is a bit confusing name for UDMA mode number

> +{
> +	char ide_tenv, ide_trp, ide_t0;

- char -> u8
- "ide_" prefix may as well be dropped

> +	/* DMA Data Setup */
> +	ide_t0 = (palm_bk3710_udmatimings[level].cycletime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +	ide_tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
> +	ide_trp = (palm_bk3710_udmatimings[level].rptime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +
> +
> +	if (!dev) {

Since this code needs to be recasted anyway it would be a nice cleanup
to merge '!dev' and 'dev' cases.

> +		/* setup master device parameters */
> +
> +		/* udmatim Register */
> +		palm_bk3710_base->config.udmatim &= 0xFFF0;
> +		palm_bk3710_base->config.udmatim |= level;
> +		/* udmastb Ultra DMA Access Strobe Width */
> +		palm_bk3710_base->config.udmastb &= 0xFF00;
> +		palm_bk3710_base->config.udmastb |= ide_t0;
> +		/* udmatrp Ultra DMA Ready to Pause Time */
> +		palm_bk3710_base->config.udmatrp &= 0xFF00;
> +		palm_bk3710_base->config.udmatrp |= ide_trp;
> +		/* udmaenv Ultra DMA envelop Time */
> +		palm_bk3710_base->config.udmaenv &= 0xFF00;
> +		palm_bk3710_base->config.udmaenv |= ide_tenv;
> +		/* Enable UDMA for Device 0 */
> +		palm_bk3710_base->config.udmactl |= 1;
> +	} else {
> +		/* setup slave device parameters */
> +
> +		/* udmatim Register */
> +		palm_bk3710_base->config.udmatim &= 0xFF0F;
> +		palm_bk3710_base->config.udmatim |= (level << 4);
> +		/* udmastb Ultra DMA Access Strobe Width */
> +		palm_bk3710_base->config.udmastb &= 0xFF;
> +		palm_bk3710_base->config.udmastb |= (ide_t0 << 8);
> +		/* udmatrp Ultra DMA Ready to Pause Time */
> +		palm_bk3710_base->config.udmatrp &= 0xFF;
> +		palm_bk3710_base->config.udmatrp |= (ide_trp << 8);
> +		/* udmaenv Ultra DMA envelop Time */
> +		palm_bk3710_base->config.udmaenv &= 0xFF;
> +		palm_bk3710_base->config.udmaenv |= (ide_tenv << 8);
> +		/* Enable UDMA for Device 1 */
> +		palm_bk3710_base->config.udmactl |= (1 << 1);
> +	}
> +}
> +
> +static void palm_bk3710_setdmamode(unsigned int dev, unsigned int cycletime,
> +				  unsigned int mode)
> +{
> +	char ide_td, ide_tkw, ide_t0;

- char -> u8
- "ide_" prefix may as well be dropped

> +	if (cycletime < ide_timing[mode].cycle)
> +		cycletime = ide_timing[mode].cycle;
> +
> +	/* DMA Data Setup */
> +	ide_t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	ide_td = (ide_timing[mode].active + ide_palm_clk - 1) / ide_palm_clk;

once ide-timing.h gets converted to ide-timing.c (or the new modes are added)
the above will break, please use ide_timing_find_mode() to access ide_timing[]

[ even better would be to use ide_timing_compute() so non-standard PIO/DMA
  timings specified by some drives are handled correctly ]

> +	ide_tkw = ide_t0 - ide_td - 1;
> +	ide_td -= 1;
> +
> +	if (!dev) {

'!dev' and 'dev' cases may be merged

> +		/* setup master device parameters */
> +		palm_bk3710_base->config.dmastb &= 0xFF00;
> +		palm_bk3710_base->config.dmastb |= ide_td;
> +		palm_bk3710_base->config.dmarcvr &= 0xFF00;
> +		palm_bk3710_base->config.dmarcvr |= ide_tkw;
> +		/* Disable UDMA for Device 0 */
> +		palm_bk3710_base->config.udmactl &= 0xFF02;
> +	} else {
> +		/* setup slave device parameters */
> +		palm_bk3710_base->config.dmastb &= 0xFF;
> +		palm_bk3710_base->config.dmastb |= (ide_td << 8);
> +		palm_bk3710_base->config.dmarcvr &= 0xFF;
> +		palm_bk3710_base->config.dmarcvr |= (ide_tkw << 8);
> +		/* Disable UDMA for Device 1 */
> +		palm_bk3710_base->config.udmactl &= 0xFF01;
> +	}
> +}
> +
> +static void palm_bk3710_setpiomode(ide_drive_t *mate, unsigned int dev,
> +				  unsigned int cycletime, unsigned int mode)
> +{
> +	char ide_t2, ide_t2i, ide_t0;

- char -> u8
- "ide_" prefix may as well be dropped

> +	/* PIO Data Setup */
> +	ide_t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	ide_t2 = (ide_timing[19 - mode].active + ide_palm_clk - 1)

ide_timing_find_mode()

> +			/ ide_palm_clk;
> +
> +	ide_t2i = ide_t0 - ide_t2 - 1;
> +	ide_t2 -= 1;
> +
> +	if (!dev) {

'!dev' and 'dev' cases may be merged

> +		/* setup master device parameters */
> +		palm_bk3710_base->config.datstb &= 0xFF00;
> +		palm_bk3710_base->config.datstb |= ide_t2;
> +		palm_bk3710_base->config.datrcvr &= 0xFF00;
> +		palm_bk3710_base->config.datrcvr |= ide_t2i;
> +	} else {
> +		/* setup slave device parameters */
> +		palm_bk3710_base->config.datstb &= 0xFF;
> +		palm_bk3710_base->config.datstb |= (ide_t2 << 8);
> +		palm_bk3710_base->config.datrcvr &= 0xFF;
> +		palm_bk3710_base->config.datrcvr |= (ide_t2i << 8);
> +	}
> +
> +	if (mate && mate->present) {
> +		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
> +
> +		if (mode2 < mode)
> +			mode = mode2;
> +	}
> +
> +	/* TASKFILE Setup */
> +	ide_t0 = (ide_timing[19 - mode].cyc8b + ide_palm_clk - 1)
> +			/ ide_palm_clk;
> +	ide_t2 = (ide_timing[19 - mode].act8b + ide_palm_clk - 1)
> +			/ ide_palm_clk;

ide_timing_find_mode()

> +	ide_t2i = ide_t0 - ide_t2 - 1;
> +	ide_t2 -= 1;
> +
> +	if (!dev) {

'!dev' and 'dev' cases may be merged

> +		/* setup master device parameters */
> +		palm_bk3710_base->config.regstb &= 0xFF00;
> +		palm_bk3710_base->config.regstb |= ide_t2;
> +		palm_bk3710_base->config.regrcvr &= 0xFF00;
> +		palm_bk3710_base->config.regrcvr |= ide_t2i;
> +	} else {
> +		/* setup slave device parameters */
> +		palm_bk3710_base->config.regstb &= 0xFF;
> +		palm_bk3710_base->config.regstb |= (ide_t2 << 8);
> +		palm_bk3710_base->config.regrcvr &= 0xFF;
> +		palm_bk3710_base->config.regrcvr |= (ide_t2i << 8);
> +	}
> +}
> +
> +static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
> +{
> +	int is_slave = drive->dn & 1;
> +
> +	switch (xferspeed) {

it could be simplified to:

	if (xferspeed > XFER_UDMA_0)
		palm_bk3710_setudmamode(...);
	else {
		...
	}

[ upper layers take care of mode filtering ]

> +	case XFER_UDMA_4:
> +	case XFER_UDMA_3:
> +	case XFER_UDMA_2:
> +	case XFER_UDMA_1:
> +	case XFER_UDMA_0:
> +		palm_bk3710_setudmamode(is_slave, xferspeed - XFER_UDMA_0);
> +		break;
> +	case XFER_MW_DMA_2:
> +	case XFER_MW_DMA_1:
> +	case XFER_MW_DMA_0:
> +		{
> +			int nspeed = 10 - xferspeed + XFER_MW_DMA_0;
> +			unsigned ide_cycle = max(ide_timing[nspeed].cycle,
> +					     drive->id->eide_dma_min);

The above line causes following warning (at least when compiling on x86):

drivers/ide/arm/palm_bk3710.c: In function ‘palm_bk3710_set_dma_mode’:
drivers/ide/arm/palm_bk3710.c:274: warning: comparison of distinct pointer types lacks a cast

> +			palm_bk3710_setdmamode(is_slave, ide_cycle, nspeed);
> +		}
> +		break;
> +	}
> +}
> +
> +static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
> +{
> +	unsigned int cycle_time;
> +	int is_slave = drive->dn & 1;
> +	ide_drive_t *mate;
> +
> +	/*
> +	 * Get the best PIO Mode supported by the drive

but it doesn't

[ upper layers take care of it ]

> +	 * Obtain the drive PIO data for tuning the Palm Chip registers
> +	 */
> +	cycle_time = ide_pio_cycle_time(drive, pio);
> +	mate = ide_get_paired_drive(drive);
> +	palm_bk3710_setpiomode(mate, is_slave, cycle_time, pio);
> +}
> +
> +static void palm_bk3710_chipinit(void)

should be __devinit (or __init)

[...]

> +	palm_bk3710_setpiomode(NULL, 0, 0, 0);
> +	palm_bk3710_setpiomode(NULL, 1, 0, 0);

0 is passed as cycle_time so ide_t2i (PIO recovery timing) in
palm_bk3710_setpiomode() becomes negative, this may work well with
a bit of luck but needs fixing

> +}
> +
> +int palm_bk3710_probe(struct platform_device *pdev)

should be static and __devinit (or __init)

[...]

> +	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
> +	for (index = 0; index < IDE_NR_PORTS - 2; index++)
> +		ide_ctlr_info.io_ports[index] = pribase + index;
> +	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
> +			IDE_PALM_ATA_PRI_CTL_OFFSET;
> +	ide_ctlr_info.irq = irq->start;
> +	ide_ctlr_info.chipset = ide_palm3710;
> +	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &palm_bk3710_hwif) < 0) {
> +		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
> +		return -ENODEV;
> +	}
> +
> +	palm_bk3710_hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
> +	palm_bk3710_hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
> +
> +	palm_bk3710_hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
> +						(input clk 99MHz) */
> +	palm_bk3710_hwif->mwdma_mask = 0x7;
> +	palm_bk3710_hwif->drives[0].autotune = 1;
> +	palm_bk3710_hwif->drives[1].autotune = 1;
> +
> +	if (!request_region(mem->start, 8, palm_bk3710_hwif->name)) {
> +		printk(KERN_ERR "Error, ports in use.\n");
> +		return -EBUSY;
> +	}

resource allocation should be done _before_ ide_register_hw() call

[ while at it please use the driver name instead of palm_bk3710_hwif->name ]

> +	palm_bk3710_hwif->dmatable_cpu = dma_alloc_coherent(
> +				NULL,
> +				PRD_ENTRIES * PRD_BYTES,
> +				&palm_bk3710_hwif->dmatable_dma,
> +				GFP_ATOMIC);
> +
> +	if (!palm_bk3710_hwif->dmatable_cpu) {
> +		printk(KERN_ERR "Error, unable to allocate DMA table.\n");
> +		return -ENOMEM;

no need to fail the driver completely - we may still operate in PIO mode just
fine given that ->{ultra,mwdma}_mask are cleared and we return 0 here

> +int palm_bk3710_init(void)

static + __devinit/__init

[...]

Please recast and resubmit.

Thanks,
Bart

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-18 18:03       ` Sergei Shtylyov
@ 2008-01-18 22:20         ` Bartlomiej Zolnierkiewicz
  0 siblings, 0 replies; 27+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-01-18 22:20 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Alan Cox, Anton Salnikov, linux-ide


On Friday 18 January 2008, Sergei Shtylyov wrote:
> Alan Cox wrote:
> 
> >>    It won't -- we can *not* call ide_setup_dma() which fills them out as this 
> >>is not a PCI chip.
> 
> > Gak.
> 
>     Or maybe we still can -- with hwif->mmio set?
>     AFAIR (from the 2006 discussion) Bart said it's *only* for PCI devices...

Well, since BLK_DEV_PALMCHIP_BK3710 selects BLK_DEV_IDEDMA_PCI it should be
possible to call ide_setup_dma() in this driver...

Bart

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] Palmchip BK3710 IDE driver
@ 2008-01-21 18:44 Anton Salnikov
  2008-01-21 19:51 ` Alan Cox
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Anton Salnikov @ 2008-01-21 18:44 UTC (permalink / raw)
  To: linux-ide; +Cc: bzolnier

This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
Supports interface to compact Flash (CF) configured in True-IDE mode.

Use ide_setup_dma() since BLK_DEV_PALMCHIP_BK3710 selects BLK_DEV_IDEDMA_PCI
So I deleted exports from ide-dma.c

Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
---

 drivers/ide/Kconfig           |    8 
 drivers/ide/arm/Makefile      |    1 
 drivers/ide/arm/palm_bk3710.c |  434 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ide/ide-proc.c        |    1 
 include/linux/ide.h           |    2 
 5 files changed, 445 insertions(+), 1 deletion(-)

Index: 2.6.24-rc8.ide/drivers/ide/Kconfig
===================================================================
--- 2.6.24-rc8.ide.orig/drivers/ide/Kconfig
+++ 2.6.24-rc8.ide/drivers/ide/Kconfig
@@ -1008,6 +1008,14 @@ config BLK_DEV_Q40IDE
 	  normally be on; disable it only if you are running a custom hard
 	  drive subsystem through an expansion card.
 
+config BLK_DEV_PALMCHIP_BK3710
+	bool "Palmchip bk3710 IDE controller support"
+	depends on ARCH_DAVINCI
+	select BLK_DEV_IDEDMA_PCI
+	help
+	  Say Y here if you want to support the onchip IDE controller on the
+	  TI DaVinci SoC
+
 config BLK_DEV_MPC8xx_IDE
 	bool "MPC8xx IDE support"
 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
BLK_DEV_IDE=y && !PPC_MERGE
Index: 2.6.24-rc8.ide/drivers/ide/arm/Makefile
===================================================================
--- 2.6.24-rc8.ide.orig/drivers/ide/arm/Makefile
+++ 2.6.24-rc8.ide/drivers/ide/arm/Makefile
@@ -2,5 +2,6 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
Index: 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
===================================================================
--- /dev/null
+++ 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
@@ -0,0 +1,434 @@
+/*
+ * Palmchip bk3710 IDE controller
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Offset of the primary interface registers */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
+
+/* Primary Control Offset */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
+
+/*
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+struct palm_bk3710_udmatiming {
+	unsigned int rptime;	/* Ready to pause time  */
+	unsigned int cycletime;	/* Cycle Time           */
+};
+
+#define BK3710_BMICP		0x00
+#define BK3710_BMISP		0x02
+#define BK3710_BMIDTP		0x04
+#define BK3710_BMICS		0x08
+#define BK3710_BMISS		0x0A
+#define BK3710_BMIDTS		0x0C
+#define BK3710_IDETIMP		0x40
+#define BK3710_IDETIMS		0x42
+#define BK3710_SIDETIM		0x44
+#define BK3710_SLEWCTL		0x45
+#define BK3710_IDESTATUS	0x47
+#define BK3710_UDMACTL		0x48
+#define BK3710_UDMATIM		0x4A
+#define BK3710_MISCCTL		0x50
+#define BK3710_REGSTB		0x54
+#define BK3710_REGRCVR		0x58
+#define BK3710_DATSTB		0x5C
+#define BK3710_DATRCVR		0x60
+#define BK3710_DMASTB		0x64
+#define BK3710_DMARCVR		0x68
+#define BK3710_UDMASTB		0x6C
+#define BK3710_UDMATRP		0x70
+#define BK3710_UDMAENV		0x74
+#define BK3710_IORDYTMP		0x78
+#define BK3710_IORDYTMS		0x7C
+
+#include "../ide-timing.h"
+
+static long ide_palm_clk;
+static u32 base;
+
+static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
+	{160, 240},		/* UDMA Mode 0 */
+	{125, 160},		/* UDMA Mode 1 */
+	{100, 120},		/* UDMA Mode 2 */
+	{100, 90},		/* UDMA Mode 3 */
+	{85,  60},		/* UDMA Mode 4 */
+};
+
+static struct clk *ideclkp;
+
+static inline u32 ioread(u32 reg)
+{
+	return ioread32(base + reg);
+}
+
+static inline void iowrite(u32 val, u32 reg)
+{
+	iowrite32(val, base + reg);
+}
+
+static void palm_bk3710_setudmamode(unsigned int dev, unsigned int mode)
+{
+	u8 tenv, trp, t0;
+	u32 val;
+
+	/* DMA Data Setup */
+	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+
+	/* udmatim Register */
+	val = ioread(BK3710_UDMATIM) & ((!dev) ? 0xFFF0 : 0xFF0F);
+	iowrite(val, BK3710_UDMATIM);
+	val = ioread(BK3710_UDMATIM) | (mode << ((!dev) ? 0 : 4));
+	iowrite(val, BK3710_UDMATIM);
+
+	/* udmastb Ultra DMA Access Strobe Width */
+	val = ioread(BK3710_UDMASTB) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_UDMASTB);
+	val = ioread(BK3710_UDMASTB) | (t0 << (dev << 4));
+	iowrite(val, BK3710_UDMASTB);
+
+	/* udmatrp Ultra DMA Ready to Pause Time */
+	val = ioread(BK3710_UDMATRP) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_UDMATRP);
+	val = ioread(BK3710_UDMATRP) | (trp << (dev << 4));
+	iowrite(val, BK3710_UDMATRP);
+
+	/* udmaenv Ultra DMA envelop Time */
+	val = ioread(BK3710_UDMAENV) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_UDMAENV);
+	val = ioread(BK3710_UDMAENV) | (tenv << (dev << 4));
+	iowrite(val, BK3710_UDMAENV);
+
+	/* Enable UDMA for Device */
+	val = ioread(BK3710_UDMACTL) | (1 << dev);
+	iowrite(val, BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setdmamode(unsigned int dev, unsigned int cycletime,
+				  unsigned int mode)
+{
+	u8 td, tkw, t0;
+	u32 val;
+
+	if (cycletime < ide_timing[mode].cycle)
+		cycletime = ide_timing[mode].cycle;
+
+	/* DMA Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	td = (ide_timing_find_mode(mode)->active + ide_palm_clk - 1)
+			/ ide_palm_clk;
+	tkw = t0 - td - 1;
+	td -= 1;
+
+	val = ioread(BK3710_DMASTB) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_DMASTB);
+	val = ioread(BK3710_DMASTB) | (td << (dev << 4));
+	iowrite(val, BK3710_DMASTB);
+
+	val = ioread(BK3710_DMARCVR) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_DMARCVR);
+	val = ioread(BK3710_DMARCVR) | (tkw << (dev << 4));
+	iowrite(val, BK3710_DMARCVR);
+
+	/* Disable UDMA for Device */
+	val = ioread(BK3710_UDMACTL) & (0xFF00 | (1 << (!dev)));
+	iowrite(val, BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setpiomode(ide_drive_t *mate, unsigned int dev,
+				  unsigned int cycletime, unsigned int mode)
+{
+	u8 t2, t2i, t0;
+	u32 val;
+	struct ide_timing *t;
+
+	/* PIO Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active + ide_palm_clk - 1)
+			/ ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val = ioread(BK3710_DATSTB) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_DATSTB);
+	val = ioread(BK3710_DATSTB) | (t2 << (dev << 4));
+	iowrite(val, BK3710_DATSTB);
+
+	val = ioread(BK3710_DATRCVR) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_DATRCVR);
+	val = ioread(BK3710_DATRCVR) | (t2i << (dev << 4));
+	iowrite(val, BK3710_DATRCVR);
+
+	if (mate && mate->present) {
+		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+
+		if (mode2 < mode)
+			mode = mode2;
+	}
+
+	/* TASKFILE Setup */
+	t = ide_timing_find_mode(XFER_PIO_0 + mode);
+	t0 = (t->cyc8b + ide_palm_clk - 1)
+			/ ide_palm_clk;
+	t2 = (t->act8b + ide_palm_clk - 1)
+			/ ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val = ioread(BK3710_REGSTB) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_REGSTB);
+	val = ioread(BK3710_REGSTB) | (t2 << (dev << 4));
+	iowrite(val, BK3710_REGSTB);
+
+	val = ioread(BK3710_REGRCVR) & (0xFF << ((!dev) << 4));
+	iowrite(val, BK3710_REGRCVR);
+	val = ioread(BK3710_REGRCVR) | (t2i << (dev << 4));
+	iowrite(val, BK3710_REGRCVR);
+}
+
+static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+{
+	int is_slave = drive->dn & 1;
+
+	if (xferspeed >= XFER_UDMA_0) {
+		palm_bk3710_setudmamode(is_slave, xferspeed - XFER_UDMA_0);
+	} else {
+		int nspeed = 10 - xferspeed + XFER_MW_DMA_0;
+		unsigned ide_cycle = max_t(int, ide_timing[nspeed].cycle,
+					   drive->id->eide_dma_min);
+
+		palm_bk3710_setdmamode(is_slave, ide_cycle, nspeed);
+	}
+}
+
+static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+	unsigned int cycle_time;
+	int is_slave = drive->dn & 1;
+	ide_drive_t *mate;
+
+	/*
+	 * Obtain the drive PIO data for tuning the Palm Chip registers
+	 */
+	cycle_time = ide_pio_cycle_time(drive, pio);
+	mate = ide_get_paired_drive(drive);
+	palm_bk3710_setpiomode(mate, is_slave, cycle_time, pio);
+}
+
+static void __devinit palm_bk3710_chipinit(void)
+{
+	/*
+	 * enable the reset_en of ATA controller so that when ata signals
+	 * are brought out, by writing into device config. at that
+	 * time por_n signal should not be 'Z' and have a stable value.
+	 */
+	iowrite(0x0300, BK3710_MISCCTL);
+
+	/* wait for some time and deassert the reset of ATA Device. */
+	mdelay(100);
+
+	/* Deassert the Reset */
+	iowrite(0x0200, BK3710_MISCCTL);
+
+	/*
+	 * Program the IDETIMP Register Value based on the following assumptions
+	 *
+	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
+	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
+	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
+	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
+	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
+	 */
+	iowrite(0xB388, BK3710_IDETIMP);
+
+	/*
+	 * Configure  SIDETIM  Register
+	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
+	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
+	 */
+	iowrite(0, BK3710_SIDETIM);
+
+	/*
+	 * UDMACTL Ultra-ATA DMA Control
+	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
+	 * (ATA_UDMACTL_UDMAP0	, 0 )
+	 *
+	 */
+	iowrite(0, BK3710_UDMACTL);
+
+	/*
+	 * MISCCTL Miscellaneous Conrol Register
+	 * (ATA_MISCCTL_RSTMODEP	, 1) |
+	 * (ATA_MISCCTL_RESETP		, 0) |
+	 * (ATA_MISCCTL_TIMORIDE	, 1)
+	 */
+	iowrite(0x201, BK3710_MISCCTL);
+
+	/*
+	 * IORDYTMP IORDY Timer for Primary Register
+	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+	 */
+	iowrite(0xFFFF, BK3710_IORDYTMP);
+
+	/*
+	 * Configure BMISP Register
+	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
+	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
+	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
+	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
+	 * (ATA_BMISP_DMAERROR	, CLEAR)
+	 */
+	iowrite(0, BK3710_BMISP);
+
+	palm_bk3710_setpiomode(NULL, 0, 600, 0);
+	palm_bk3710_setpiomode(NULL, 1, 600, 0);
+}
+
+static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+{
+	hw_regs_t ide_ctlr_info;
+	int index = 0;
+	int pribase;
+	struct clk *clkp;
+	struct resource *mem, *irq;
+	ide_hwif_t *hwif;
+
+	clkp = clk_get(NULL, "IDECLK");
+	if (IS_ERR(clkp))
+		return -ENODEV;
+
+	ideclkp = clkp;
+	clk_enable(ideclkp);
+	ide_palm_clk = clk_get_rate(ideclkp)/100000;
+	ide_palm_clk = (10000/ide_palm_clk) + 1;
+	/* Register the IDE interface with Linux ATA Interface */
+	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem == NULL) {
+		printk(KERN_INFO "failed to get memory region resource\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq == NULL) {
+		printk(KERN_INFO "failed to get IRQ resource\n");
+		return -ENODEV;
+	}
+
+	base = mem->start;
+	/* Configure the Palm Chip controller */
+	palm_bk3710_chipinit();
+
+	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
+	for (index = 0; index < IDE_NR_PORTS - 2; index++)
+		ide_ctlr_info.io_ports[index] = pribase + index;
+	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
+			IDE_PALM_ATA_PRI_CTL_OFFSET;
+	ide_ctlr_info.irq = irq->start;
+	ide_ctlr_info.chipset = ide_palm3710;
+
+	if (!request_region(mem->start, 8, "palm_bk3710")) {
+		printk(KERN_ERR "Error, ports in use.\n");
+		return -EBUSY;
+	}
+
+	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &hwif) < 0) {
+		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
+		return -ENODEV;
+	}
+
+	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
+	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
+	hwif->mmio = 1;
+	hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
+						(input clk 99MHz) */
+	hwif->mwdma_mask = 0x7;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	hwif->dmatable_cpu = dma_alloc_coherent(
+				NULL,
+				PRD_ENTRIES * PRD_BYTES,
+				&hwif->dmatable_dma,
+				GFP_ATOMIC);
+
+	if (!hwif->dmatable_cpu) {
+		printk(KERN_ERR "Error, unable to allocate DMA table.\n");
+		hwif->ultra_mask = 0;
+		hwif->mwdma_mask = 0;
+		return 0;
+	}
+
+	hwif->dma_base = mem->start;
+
+	hwif->dma_master = mem->start;
+
+	hwif->dma_command = mem->start;
+	hwif->dma_status = mem->start + 2;
+	hwif->dma_prdtable = mem->start + 4;
+	ide_setup_dma(hwif, mem->start, 8);
+
+	return 0;
+}
+
+static struct platform_driver platform_bk_driver = {
+	.driver = {
+		.name = "palm_bk3710",
+	},
+	.probe = palm_bk3710_probe,
+	.remove = NULL,
+};
+
+static int __init palm_bk3710_init(void)
+{
+	return platform_driver_register(&platform_bk_driver);
+}
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
+
Index: 2.6.24-rc8.ide/drivers/ide/ide-proc.c
===================================================================
--- 2.6.24-rc8.ide.orig/drivers/ide/ide-proc.c
+++ 2.6.24-rc8.ide/drivers/ide/ide-proc.c
@@ -67,6 +67,7 @@ static int proc_ide_read_imodel
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
 		case ide_au1xxx:	name = "au1xxx";	break;
+		case ide_palm3710:      name = "palm3710";      break;
 		case ide_etrax100:	name = "etrax100";	break;
 		case ide_acorn:		name = "acorn";		break;
 		default:		name = "(unknown)";	break;
Index: 2.6.24-rc8.ide/include/linux/ide.h
===================================================================
--- 2.6.24-rc8.ide.orig/include/linux/ide.h
+++ 2.6.24-rc8.ide/include/linux/ide.h
@@ -202,7 +202,7 @@ enum {		ide_unknown,	ide_generic,	ide_pc
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_au1xxx, ide_forced
+		ide_au1xxx,	ide_palm3710,	ide_forced
 };
 
 typedef u8 hwif_chipset_t;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-21 18:44 Anton Salnikov
@ 2008-01-21 19:51 ` Alan Cox
  2008-01-22 12:11   ` Anton Salnikov
  2008-01-22 20:30 ` Sergei Shtylyov
  2008-01-23 14:32 ` Sergei Shtylyov
  2 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2008-01-21 19:51 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

> +static inline u32 ioread(u32 reg)
> +{
> +	return ioread32(base + reg);
> +}
> +
> +static inline void iowrite(u32 val, u32 reg)
> +{
> +	iowrite32(val, base + reg);
> +}

Why not just use ioread32/iowrite32 directly ?


Otherwise this looks way way better.

Alan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-21 19:51 ` Alan Cox
@ 2008-01-22 12:11   ` Anton Salnikov
  2008-01-22 14:37     ` Alan Cox
  2008-01-22 19:31     ` Jeff Garzik
  0 siblings, 2 replies; 27+ messages in thread
From: Anton Salnikov @ 2008-01-22 12:11 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-ide, bzolnier

> > +static inline u32 ioread(u32 reg)
> > +{
> > +	return ioread32(base + reg);
> > +}
> > +
> > +static inline void iowrite(u32 val, u32 reg)
> > +{
> > +	iowrite32(val, base + reg);
> > +}
> 
> Why not just use ioread32/iowrite32 directly ?

Because this increases readability and does not affect functionality at all

> Otherwise this looks way way better.
> 
> Alan
> 

Anton

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-22 12:11   ` Anton Salnikov
@ 2008-01-22 14:37     ` Alan Cox
  2008-01-22 19:31     ` Jeff Garzik
  1 sibling, 0 replies; 27+ messages in thread
From: Alan Cox @ 2008-01-22 14:37 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

On Tue, 22 Jan 2008 15:11:37 +0300
Anton Salnikov <asalnikov@ru.mvista.com> wrote:

> > > +static inline u32 ioread(u32 reg)
> > > +{
> > > +	return ioread32(base + reg);
> > > +}
> > > +
> > > +static inline void iowrite(u32 val, u32 reg)
> > > +{
> > > +	iowrite32(val, base + reg);
> > > +}
> > 
> > Why not just use ioread32/iowrite32 directly ?
> 
> Because this increases readability and does not affect functionality at all

There I would disagree. It means that if you ever have a system with two
of these controllers in future it will break as base is a static for the
entire driver.

Easy enough to fix with a simple
	
	static inline u32 hwif_ioread32(hwif, u32 reg) { ...
hwif->dma_base ...}

version ?

Alan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-22 12:11   ` Anton Salnikov
  2008-01-22 14:37     ` Alan Cox
@ 2008-01-22 19:31     ` Jeff Garzik
  1 sibling, 0 replies; 27+ messages in thread
From: Jeff Garzik @ 2008-01-22 19:31 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: Alan Cox, linux-ide, bzolnier

Anton Salnikov wrote:
>>> +static inline u32 ioread(u32 reg)
>>> +{
>>> +	return ioread32(base + reg);
>>> +}
>>> +
>>> +static inline void iowrite(u32 val, u32 reg)
>>> +{
>>> +	iowrite32(val, base + reg);
>>> +}
>> Why not just use ioread32/iowrite32 directly ?
> 
> Because this increases readability and does not affect functionality at all

Disagree.

It confuses the namespace, /decreasing/ readability.  Anyone _but_ you 
reading this code will be confused by a non-standard API named similarly 
to an existing kernel API.

	Jeff




^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-21 18:44 Anton Salnikov
  2008-01-21 19:51 ` Alan Cox
@ 2008-01-22 20:30 ` Sergei Shtylyov
  2008-01-22 22:22   ` Alan Cox
  2008-01-23 14:32 ` Sergei Shtylyov
  2 siblings, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-22 20:30 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

Hello.

Anton Salnikov wrote:

> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

> Use ide_setup_dma() since BLK_DEV_PALMCHIP_BK3710 selects BLK_DEV_IDEDMA_PCI
> So I deleted exports from ide-dma.c

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>

> Index: 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
> @@ -0,0 +1,434 @@

> +static long ide_palm_clk;
> +static u32 base;

    This base will be in hwif->dma_master, so you can aslo use it this way if 
you make your 'hwif' pointer static instead. Although as this

> +
> +static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
> +	{160, 240},		/* UDMA Mode 0 */
> +	{125, 160},		/* UDMA Mode 1 */
> +	{100, 120},		/* UDMA Mode 2 */
> +	{100, 90},		/* UDMA Mode 3 */
> +	{85,  60},		/* UDMA Mode 4 */
> +};
> +
> +static struct clk *ideclkp;
> +
> +static inline u32 ioread(u32 reg)
> +{
> +	return ioread32(base + reg);
> +}
> +
> +static inline void iowrite(u32 val, u32 reg)
> +{
> +	iowrite32(val, base + reg);
> +}

    Why you chose to use ioread32() and iowrite32() if your device is strictly 
memory mapped? Those functions add some overhead, and boil down to readl() and 
writel() anyway.  IIRC, they should only be used if you have a hardware 
registers accessible from both I/O and memory space and driver supports both 
types of mapping (e.g., I/O mapped for the older hardware, memory mapped for 
the newer one)...

> +static void palm_bk3710_setudmamode(unsigned int dev, unsigned int mode)
> +{
> +	u8 tenv, trp, t0;
> +	u32 val;
> +
> +	/* DMA Data Setup */
> +	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
> +	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +
> +	/* udmatim Register */
> +	val = ioread(BK3710_UDMATIM) & ((!dev) ? 0xFFF0 : 0xFF0F);

    Hm, isn't it shorter:

	val = ioread(BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);

> +	iowrite(val, BK3710_UDMATIM);

    Why not skip intermediate write and re-read?  Does hardware require 
clearing the fields before setting new values by some weird chance?

> +	val = ioread(BK3710_UDMATIM) | (mode << ((!dev) ? 0 : 4));

    You actually need to shift left by 0 or 8, so shift count should be 3, not 
4 since 1 << 4 == 16!  I'm suggesting:

	val = ioread(BK3710_UDMATIM) | (mode << (dev ? 3 : 0));

> +	iowrite(val, BK3710_UDMATIM);
> +
> +	/* udmastb Ultra DMA Access Strobe Width */
> +	val = ioread(BK3710_UDMASTB) & (0xFF << ((!dev) << 4));

    I'm suggesting:

	val = ioread(BK3710_UDMASTB) & (0xFF00 >> (dev << 3));

> +	iowrite(val, BK3710_UDMASTB);
> +	val = ioread(BK3710_UDMASTB) | (t0 << (dev << 4));
> +	iowrite(val, BK3710_UDMASTB);
> +
> +	/* udmatrp Ultra DMA Ready to Pause Time */
> +	val = ioread(BK3710_UDMATRP) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_UDMATRP);
> +	val = ioread(BK3710_UDMATRP) | (trp << (dev << 4));
> +	iowrite(val, BK3710_UDMATRP);
> +
> +	/* udmaenv Ultra DMA envelop Time */
> +	val = ioread(BK3710_UDMAENV) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_UDMAENV);
> +	val = ioread(BK3710_UDMAENV) | (tenv << (dev << 4));
> +	iowrite(val, BK3710_UDMAENV);

    << 3 ISO << 4 everywhere...

> +
> +	/* Enable UDMA for Device */
> +	val = ioread(BK3710_UDMACTL) | (1 << dev);
> +	iowrite(val, BK3710_UDMACTL);
> +}
> +
> +static void palm_bk3710_setdmamode(unsigned int dev, unsigned int cycletime,
> +				  unsigned int mode)
> +{
> +	u8 td, tkw, t0;
> +	u32 val;
> +
> +	if (cycletime < ide_timing[mode].cycle)
> +		cycletime = ide_timing[mode].cycle;

    I don't think this check is necessary as you're passing either 
ide_timing[mode].cycle or drive->id->eide_dma_min -- whichever is greater...

> +
> +	/* DMA Data Setup */
> +	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	td = (ide_timing_find_mode(mode)->active + ide_palm_clk - 1)

    You're not passing a mode suitable to ide_timing_find_mode() here, but 
index into ide_timing[] table -- almost the same thing that this call is 
supposed to yield... :-/

> +			/ ide_palm_clk;
> +	tkw = t0 - td - 1;
> +	td -= 1;
> +
> +	val = ioread(BK3710_DMASTB) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_DMASTB);
> +	val = ioread(BK3710_DMASTB) | (td << (dev << 4));
> +	iowrite(val, BK3710_DMASTB);
> +
> +	val = ioread(BK3710_DMARCVR) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_DMARCVR);
> +	val = ioread(BK3710_DMARCVR) | (tkw << (dev << 4));
> +	iowrite(val, BK3710_DMARCVR);
> +
> +	/* Disable UDMA for Device */
> +	val = ioread(BK3710_UDMACTL) & (0xFF00 | (1 << (!dev)));

    I think it should be just like above:

	val = ioread(BK3710_UDMACTL) & ~(1 << dev);

> +	iowrite(val, BK3710_UDMACTL);
> +}

    Same comments as above...

> +static void palm_bk3710_setpiomode(ide_drive_t *mate, unsigned int dev,
> +				  unsigned int cycletime, unsigned int mode)
> +{
> +	u8 t2, t2i, t0;
> +	u32 val;
> +	struct ide_timing *t;
> +
> +	/* PIO Data Setup */
> +	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active + ide_palm_clk - 1)
> +			/ ide_palm_clk;
> +
> +	t2i = t0 - t2 - 1;
> +	t2 -= 1;
> +
> +	val = ioread(BK3710_DATSTB) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_DATSTB);
> +	val = ioread(BK3710_DATSTB) | (t2 << (dev << 4));
> +	iowrite(val, BK3710_DATSTB);
> +
> +	val = ioread(BK3710_DATRCVR) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_DATRCVR);
> +	val = ioread(BK3710_DATRCVR) | (t2i << (dev << 4));
> +	iowrite(val, BK3710_DATRCVR);
> +
> +	if (mate && mate->present) {
> +		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
> +
> +		if (mode2 < mode)
> +			mode = mode2;
> +	}
> +
> +	/* TASKFILE Setup */
> +	t = ide_timing_find_mode(XFER_PIO_0 + mode);
> +	t0 = (t->cyc8b + ide_palm_clk - 1)
> +			/ ide_palm_clk;
> +	t2 = (t->act8b + ide_palm_clk - 1)
> +			/ ide_palm_clk;

    Please make the two above assignments take 2 lines ISO 4...

> +
> +	t2i = t0 - t2 - 1;
> +	t2 -= 1;
> +
> +	val = ioread(BK3710_REGSTB) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_REGSTB);
> +	val = ioread(BK3710_REGSTB) | (t2 << (dev << 4));
> +	iowrite(val, BK3710_REGSTB);
> +
> +	val = ioread(BK3710_REGRCVR) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_REGRCVR);
> +	val = ioread(BK3710_REGRCVR) | (t2i << (dev << 4));
> +	iowrite(val, BK3710_REGRCVR);

    Same mistakes as the above functions...

> +}
> +
> +static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
> +{
> +	int is_slave = drive->dn & 1;
> +
> +	if (xferspeed >= XFER_UDMA_0) {
> +		palm_bk3710_setudmamode(is_slave, xferspeed - XFER_UDMA_0);
> +	} else {
> +		int nspeed = 10 - xferspeed + XFER_MW_DMA_0;
> +		unsigned ide_cycle = max_t(int, ide_timing[nspeed].cycle,
> +					   drive->id->eide_dma_min);

    It's probably better to move this part into palm_bk3710_setdmamode()...

> +
> +		palm_bk3710_setdmamode(is_slave, ide_cycle, nspeed);

    You should pass xferspeed here, not nspeed...

> +static int __devinit palm_bk3710_probe(struct platform_device *pdev)
> +{
> +	hw_regs_t ide_ctlr_info;
> +	int index = 0;
> +	int pribase;
> +	struct clk *clkp;
> +	struct resource *mem, *irq;
> +	ide_hwif_t *hwif;
> +
> +	clkp = clk_get(NULL, "IDECLK");
> +	if (IS_ERR(clkp))
> +		return -ENODEV;
> +
> +	ideclkp = clkp;
> +	clk_enable(ideclkp);
> +	ide_palm_clk = clk_get_rate(ideclkp)/100000;
> +	ide_palm_clk = (10000/ide_palm_clk) + 1;
> +	/* Register the IDE interface with Linux ATA Interface */
> +	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (mem == NULL) {
> +		printk(KERN_INFO "failed to get memory region resource\n");
> +		return -ENODEV;
> +	}
> +	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (irq == NULL) {
> +		printk(KERN_INFO "failed to get IRQ resource\n");
> +		return -ENODEV;
> +	}
> +
> +	base = mem->start;
> +	/* Configure the Palm Chip controller */
> +	palm_bk3710_chipinit();
> +
> +	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
> +	for (index = 0; index < IDE_NR_PORTS - 2; index++)
> +		ide_ctlr_info.io_ports[index] = pribase + index;
> +	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
> +			IDE_PALM_ATA_PRI_CTL_OFFSET;
> +	ide_ctlr_info.irq = irq->start;
> +	ide_ctlr_info.chipset = ide_palm3710;
> +
> +	if (!request_region(mem->start, 8, "palm_bk3710")) {

    It should be request_mem_region() since the chip is memory mapped. I've 
managed to overlook this so far. :-<
    BTW, shouldn't you call request_mem_region() for the entire controller 
register region (0x400 in size if I don't mistake)?

> +		printk(KERN_ERR "Error, ports in use.\n");
> +		return -EBUSY;
> +	}
> +
> +	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &hwif) < 0) {
> +		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
> +		return -ENODEV;
> +	}
> +
> +	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
> +	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
> +	hwif->mmio = 1;
> +	hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
> +						(input clk 99MHz) */
> +	hwif->mwdma_mask = 0x7;
> +	hwif->drives[0].autotune = 1;
> +	hwif->drives[1].autotune = 1;
> +
> +	hwif->dmatable_cpu = dma_alloc_coherent(
> +				NULL,
> +				PRD_ENTRIES * PRD_BYTES,
> +				&hwif->dmatable_dma,
> +				GFP_ATOMIC);
> +
> +	if (!hwif->dmatable_cpu) {
> +		printk(KERN_ERR "Error, unable to allocate DMA table.\n");
> +		hwif->ultra_mask = 0;
> +		hwif->mwdma_mask = 0;
> +		return 0;
> +	}
> +

    You don't need to allocate PRD table -- ide_setup_dma() will do it for you 
anyway, although using pci_alloc_consistent().

> +	hwif->dma_base = mem->start;
> +
> +	hwif->dma_master = mem->start;
> +
> +	hwif->dma_command = mem->start;
> +	hwif->dma_status = mem->start + 2;
> +	hwif->dma_prdtable = mem->start + 4;

    You don't need 5 above assignments - ide_setup_dma() will do this for you.

> +	ide_setup_dma(hwif, mem->start, 8);
> +
> +	return 0;
> +}

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-22 20:30 ` Sergei Shtylyov
@ 2008-01-22 22:22   ` Alan Cox
  2008-01-23 13:38     ` Sergei Shtylyov
  0 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2008-01-22 22:22 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Anton Salnikov, linux-ide, bzolnier

>     Why you chose to use ioread32() and iowrite32() if your device is strictly 
> memory mapped? Those functions add some overhead, and boil down to readl() and 

There are distinct portability advantages but you shouldn't mix
ioread32/iowrite32 with ioremap as that isn't guaranteed to work.
readl/writel does fine and fixes up the driver.


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-22 22:22   ` Alan Cox
@ 2008-01-23 13:38     ` Sergei Shtylyov
  2008-01-23 14:59       ` Alan Cox
  0 siblings, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-23 13:38 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: Alan Cox, linux-ide, bzolnier

Hello.

Alan Cox wrote:

>>    Why you chose to use ioread32() and iowrite32() if your device is strictly 
>>memory mapped? Those functions add some overhead, and boil down to readl() and 

> There are distinct portability advantages but you shouldn't mix
> ioread32/iowrite32 with ioremap as that isn't guaranteed to work.

    Hm, pci_iomap() boils down to ioremap(), so

> readl/writel does fine and fixes up the driver.

    Which brings up another issue with the latest patch: Anton, where do you 
call ioremap() or something alike to get the virtual address of the registers?

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-21 18:44 Anton Salnikov
  2008-01-21 19:51 ` Alan Cox
  2008-01-22 20:30 ` Sergei Shtylyov
@ 2008-01-23 14:32 ` Sergei Shtylyov
  2 siblings, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-23 14:32 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

Anton Salnikov wrote:

> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

> Use ide_setup_dma() since BLK_DEV_PALMCHIP_BK3710 selects BLK_DEV_IDEDMA_PCI
> So I deleted exports from ide-dma.c

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>

    Looks like I found another issue caused by using iowrite32() for 16-bit 
registers:

> Index: 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
> @@ -0,0 +1,434 @@
[...]
> +#define BK3710_BMICP		0x00
> +#define BK3710_BMISP		0x02
> +#define BK3710_BMIDTP		0x04
> +#define BK3710_BMICS		0x08
> +#define BK3710_BMISS		0x0A
> +#define BK3710_BMIDTS		0x0C
> +#define BK3710_IDETIMP		0x40
> +#define BK3710_IDETIMS		0x42
> +#define BK3710_SIDETIM		0x44
> +#define BK3710_SLEWCTL		0x45
> +#define BK3710_IDESTATUS	0x47
> +#define BK3710_UDMACTL		0x48
> +#define BK3710_UDMATIM		0x4A

    Note that the above two registers are 16-bit...

> +#define BK3710_MISCCTL		0x50
> +#define BK3710_REGSTB		0x54
> +#define BK3710_REGRCVR		0x58
> +#define BK3710_DATSTB		0x5C
> +#define BK3710_DATRCVR		0x60
> +#define BK3710_DMASTB		0x64
> +#define BK3710_DMARCVR		0x68
> +#define BK3710_UDMASTB		0x6C
> +#define BK3710_UDMATRP		0x70
> +#define BK3710_UDMAENV		0x74
> +#define BK3710_IORDYTMP		0x78
> +#define BK3710_IORDYTMS		0x7C
[...]
> +static void palm_bk3710_setudmamode(unsigned int dev, unsigned int mode)
> +{
> +	u8 tenv, trp, t0;
> +	u32 val;
> +
> +	/* DMA Data Setup */
> +	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
> +	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +
> +	/* udmatim Register */
> +	val = ioread(BK3710_UDMATIM) & ((!dev) ? 0xFFF0 : 0xFF0F);
> +	iowrite(val, BK3710_UDMATIM);
> +	val = ioread(BK3710_UDMATIM) | (mode << ((!dev) ? 0 : 4));
> +	iowrite(val, BK3710_UDMATIM);

    This register is 16-bit, so:

1) you're performing unaligned access which would end up emulated in the best
    case;
2) you're clearing MISCCTL reg. inadvertently...

[...]

> +static void palm_bk3710_setdmamode(unsigned int dev, unsigned int cycletime,
> +				  unsigned int mode)
> +{
> +	u8 td, tkw, t0;
> +	u32 val;
> +
> +	if (cycletime < ide_timing[mode].cycle)
> +		cycletime = ide_timing[mode].cycle;
> +
> +	/* DMA Data Setup */
> +	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	td = (ide_timing_find_mode(mode)->active + ide_palm_clk - 1)
> +			/ ide_palm_clk;
> +	tkw = t0 - td - 1;
> +	td -= 1;
> +
> +	val = ioread(BK3710_DMASTB) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_DMASTB);
> +	val = ioread(BK3710_DMASTB) | (td << (dev << 4));
> +	iowrite(val, BK3710_DMASTB);
> +
> +	val = ioread(BK3710_DMARCVR) & (0xFF << ((!dev) << 4));
> +	iowrite(val, BK3710_DMARCVR);
> +	val = ioread(BK3710_DMARCVR) | (tkw << (dev << 4));
> +	iowrite(val, BK3710_DMARCVR);
> +
> +	/* Disable UDMA for Device */
> +	val = ioread(BK3710_UDMACTL) & (0xFF00 | (1 << (!dev)));
> +	iowrite(val, BK3710_UDMACTL);

    This register is also 16-bit, so:

1) you're performing unaligned access which would end up emulated in the best
    case;
2) you're clearing UDMATIM reg. inadvertently (although this seems safe as 
you're disabling UltraDMA anyway...

[...]

> +static void __devinit palm_bk3710_chipinit(void)
> +{
> +	/*
> +	 * enable the reset_en of ATA controller so that when ata signals
> +	 * are brought out, by writing into device config. at that
> +	 * time por_n signal should not be 'Z' and have a stable value.
> +	 */
> +	iowrite(0x0300, BK3710_MISCCTL);
> +
> +	/* wait for some time and deassert the reset of ATA Device. */
> +	mdelay(100);
> +
> +	/* Deassert the Reset */
> +	iowrite(0x0200, BK3710_MISCCTL);
> +
> +	/*
> +	 * Program the IDETIMP Register Value based on the following assumptions
> +	 *
> +	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
> +	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
> +	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
> +	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
> +	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
> +	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
> +	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
> +	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
> +	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
> +	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
> +	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
> +	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
> +	 */
> +	iowrite(0xB388, BK3710_IDETIMP);

    This register is 16-bit, so:

1) you're performing unaligned access which would end up emulated in the best
    case;
2) you're clearing IDETIMS reg. inadvertently (probably safe as your device 
doesn't seem to have a secondary channel...

[...]

> +
> +	/*
> +	 * Configure  SIDETIM  Register
> +	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
> +	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
> +	 */
> +	iowrite(0, BK3710_SIDETIM);

    This register is 8-bit, so:

1) you're performing unaligned access which would end up emulated in the best
    case;
2) you're clearing SLEWCTL/IDESTATUS regs inadvertently...

> +
> +	/*
> +	 * UDMACTL Ultra-ATA DMA Control
> +	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
> +	 * (ATA_UDMACTL_UDMAP0	, 0 )
> +	 *
> +	 */
> +	iowrite(0, BK3710_UDMACTL);

    This register is 16-bit, so:

1) you're performing unaligned access which would end up emulated in the best
    case;
2) you're clearing UDMATIM regs inadvertently...

> +	/*
> +	 * Configure BMISP Register
> +	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
> +	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
> +	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
> +	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
> +	 * (ATA_BMISP_DMAERROR	, CLEAR)
> +	 */
> +	iowrite(0, BK3710_BMISP);

    This register is 8-bit, so:

1) you're performing unaligned access which would end up emulated in the best
    case;
2) you're clearing BMIDTP regs inadvertently...

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-23 13:38     ` Sergei Shtylyov
@ 2008-01-23 14:59       ` Alan Cox
  0 siblings, 0 replies; 27+ messages in thread
From: Alan Cox @ 2008-01-23 14:59 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Anton Salnikov, linux-ide, bzolnier

On Wed, 23 Jan 2008 16:38:06 +0300
Sergei Shtylyov <sshtylyov@ru.mvista.com> wrote:

> Hello.
> 
> Alan Cox wrote:
> 
> >>    Why you chose to use ioread32() and iowrite32() if your device is strictly 
> >>memory mapped? Those functions add some overhead, and boil down to readl() and 
> 
> > There are distinct portability advantages but you shouldn't mix
> > ioread32/iowrite32 with ioremap as that isn't guaranteed to work.
> 
>     Hm, pci_iomap() boils down to ioremap(), so

For most cases on existing hardware. Do not rely on that in future.

Alan

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] Palmchip BK3710 IDE driver
@ 2008-01-24 15:01 Anton Salnikov
  2008-01-24 19:18 ` Sergei Shtylyov
  0 siblings, 1 reply; 27+ messages in thread
From: Anton Salnikov @ 2008-01-24 15:01 UTC (permalink / raw)
  To: linux-ide; +Cc: bzolnier

This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
Supports interface to compact Flash (CF) configured in True-IDE mode.

Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
---

 drivers/ide/Kconfig           |    8 
 drivers/ide/arm/Makefile      |    1 
 drivers/ide/arm/palm_bk3710.c |  428 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ide/ide-proc.c        |    1 
 include/linux/ide.h           |    2 
 5 files changed, 439 insertions(+), 1 deletion(-)

Index: 2.6.24-rc8.ide/drivers/ide/Kconfig
===================================================================
--- 2.6.24-rc8.ide.orig/drivers/ide/Kconfig
+++ 2.6.24-rc8.ide/drivers/ide/Kconfig
@@ -1008,6 +1008,14 @@ config BLK_DEV_Q40IDE
 	  normally be on; disable it only if you are running a custom hard
 	  drive subsystem through an expansion card.
 
+config BLK_DEV_PALMCHIP_BK3710
+	bool "Palmchip bk3710 IDE controller support"
+	depends on ARCH_DAVINCI
+	select BLK_DEV_IDEDMA_PCI
+	help
+	  Say Y here if you want to support the onchip IDE controller on the
+	  TI DaVinci SoC
+
 config BLK_DEV_MPC8xx_IDE
 	bool "MPC8xx IDE support"
 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
BLK_DEV_IDE=y && !PPC_MERGE
Index: 2.6.24-rc8.ide/drivers/ide/arm/Makefile
===================================================================
--- 2.6.24-rc8.ide.orig/drivers/ide/arm/Makefile
+++ 2.6.24-rc8.ide/drivers/ide/arm/Makefile
@@ -2,5 +2,6 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
Index: 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
===================================================================
--- /dev/null
+++ 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
@@ -0,0 +1,428 @@
+/*
+ * Palmchip bk3710 IDE controller
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Offset of the primary interface registers */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
+
+/* Primary Control Offset */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
+
+/*
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+struct palm_bk3710_udmatiming {
+	unsigned int rptime;	/* Ready to pause time  */
+	unsigned int cycletime;	/* Cycle Time           */
+};
+
+#define BK3710_BMICP		0x00
+#define BK3710_BMISP		0x02
+#define BK3710_BMIDTP		0x04
+#define BK3710_BMICS		0x08
+#define BK3710_BMISS		0x0A
+#define BK3710_BMIDTS		0x0C
+#define BK3710_IDETIMP		0x40
+#define BK3710_IDETIMS		0x42
+#define BK3710_SIDETIM		0x44
+#define BK3710_SLEWCTL		0x45
+#define BK3710_IDESTATUS	0x47
+#define BK3710_UDMACTL		0x48
+#define BK3710_UDMATIM		0x4A
+#define BK3710_MISCCTL		0x50
+#define BK3710_REGSTB		0x54
+#define BK3710_REGRCVR		0x58
+#define BK3710_DATSTB		0x5C
+#define BK3710_DATRCVR		0x60
+#define BK3710_DMASTB		0x64
+#define BK3710_DMARCVR		0x68
+#define BK3710_UDMASTB		0x6C
+#define BK3710_UDMATRP		0x70
+#define BK3710_UDMAENV		0x74
+#define BK3710_IORDYTMP		0x78
+#define BK3710_IORDYTMS		0x7C
+
+#include "../ide-timing.h"
+
+static long ide_palm_clk;
+
+static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
+	{160, 240},		/* UDMA Mode 0 */
+	{125, 160},		/* UDMA Mode 1 */
+	{100, 120},		/* UDMA Mode 2 */
+	{100, 90},		/* UDMA Mode 3 */
+	{85,  60},		/* UDMA Mode 4 */
+};
+
+static struct clk *ideclkp;
+
+static inline u8 hwif_read8(u32 base, u32 reg)
+{
+	return readb(base + reg);
+}
+
+static inline void hwif_write8(u32 base, u8 val, u32 reg)
+{
+	writeb(val, base + reg);
+}
+
+static inline u16 hwif_read16(u32 base, u32 reg)
+{
+	return readw(base + reg);
+}
+
+static inline void hwif_write16(u32 base, u16 val, u32 reg)
+{
+	writew(val, base + reg);
+}
+
+static inline u32 hwif_read32(u32 base, u32 reg)
+{
+	return readl(base + reg);
+}
+
+static inline void hwif_write32(u32 base, u32 val, u32 reg)
+{
+	writel(val, base + reg);
+}
+
+static void palm_bk3710_setudmamode(u32 base, unsigned int dev,
+				    unsigned int mode)
+{
+	u8 tenv, trp, t0;
+	u32 val32;
+	u16 val16;
+
+	/* DMA Data Setup */
+	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+
+	/* udmatim Register */
+	val16 = hwif_read16(base, BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
+	val16 |= (mode << ((!dev) ? 0 : 4));
+	hwif_write16(base, val16, BK3710_UDMATIM);
+
+	/* udmastb Ultra DMA Access Strobe Width */
+	val32 = hwif_read32(base, BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t0 << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_UDMASTB);
+
+	/* udmatrp Ultra DMA Ready to Pause Time */
+	val32 = hwif_read32(base, BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+	val32 |= (trp << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_UDMATRP);
+
+	/* udmaenv Ultra DMA envelop Time */
+	val32 = hwif_read32(base, BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+	val32 |= (tenv << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_UDMAENV);
+
+	/* Enable UDMA for Device */
+	val16 = hwif_read16(base, BK3710_UDMACTL) | (1 << dev);
+	hwif_write16(base, val16, BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setdmamode(u32 base, unsigned int dev,
+				   unsigned short min_cycle,
+				   unsigned int mode)
+{
+	u8 td, tkw, t0;
+	u32 val32;
+	u16 val16;
+
+	unsigned cycletime = max_t(int, ide_timing_find_mode(mode)->cycle,
+				   min_cycle);
+
+	/* DMA Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	td = (ide_timing_find_mode(mode)->active + ide_palm_clk - 1)
+			/ ide_palm_clk;
+	tkw = t0 - td - 1;
+	td -= 1;
+
+	val32 = hwif_read32(base, BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (td << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DMASTB);
+
+	val32 = hwif_read32(base, BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (tkw << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DMARCVR);
+
+	/* Disable UDMA for Device */
+	val16 = hwif_read16(base, BK3710_UDMACTL) & ~(1 << dev);
+	hwif_write16(base, val16, BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setpiomode(u32 base, ide_drive_t *mate,
+				   unsigned int dev, unsigned int cycletime,
+				   unsigned int mode)
+{
+	u8 t2, t2i, t0;
+	u32 val32;
+	struct ide_timing *t;
+
+	/* PIO Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
+	      ide_palm_clk - 1)	/ ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val32 = hwif_read32(base, BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2 << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DATSTB);
+
+	val32 = hwif_read32(base, BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2i << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DATRCVR);
+
+	if (mate && mate->present) {
+		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+
+		if (mode2 < mode)
+			mode = mode2;
+	}
+
+	/* TASKFILE Setup */
+	t = ide_timing_find_mode(XFER_PIO_0 + mode);
+	t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val32 = hwif_read32(base, BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2 << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_REGSTB);
+
+	val32 = hwif_read32(base, BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2i << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_REGRCVR);
+}
+
+static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+{
+	int is_slave = drive->dn & 1;
+	u32 base = drive->hwif->dma_master;
+
+	if (xferspeed >= XFER_UDMA_0) {
+		palm_bk3710_setudmamode(base, is_slave,
+					xferspeed - XFER_UDMA_0);
+	} else {
+		palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
+				       xferspeed);
+	}
+}
+
+static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+	unsigned int cycle_time;
+	int is_slave = drive->dn & 1;
+	ide_drive_t *mate;
+	u32 base = drive->hwif->dma_master;
+
+	/*
+	 * Obtain the drive PIO data for tuning the Palm Chip registers
+	 */
+	cycle_time = ide_pio_cycle_time(drive, pio);
+	mate = ide_get_paired_drive(drive);
+	palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
+}
+
+static void __devinit palm_bk3710_chipinit(u32 base)
+{
+	/*
+	 * enable the reset_en of ATA controller so that when ata signals
+	 * are brought out, by writing into device config. at that
+	 * time por_n signal should not be 'Z' and have a stable value.
+	 */
+	hwif_write32(base, 0x0300, BK3710_MISCCTL);
+
+	/* wait for some time and deassert the reset of ATA Device. */
+	mdelay(100);
+
+	/* Deassert the Reset */
+	hwif_write32(base, 0x0200, BK3710_MISCCTL);
+
+	/*
+	 * Program the IDETIMP Register Value based on the following assumptions
+	 *
+	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
+	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
+	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
+	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
+	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
+	 */
+	hwif_write16(base, 0xB388, BK3710_IDETIMP);
+
+	/*
+	 * Configure  SIDETIM  Register
+	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
+	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
+	 */
+	hwif_write8(base, 0, BK3710_SIDETIM);
+
+	/*
+	 * UDMACTL Ultra-ATA DMA Control
+	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
+	 * (ATA_UDMACTL_UDMAP0	, 0 )
+	 *
+	 */
+	hwif_write16(base, 0, BK3710_UDMACTL);
+
+	/*
+	 * MISCCTL Miscellaneous Conrol Register
+	 * (ATA_MISCCTL_RSTMODEP	, 1) |
+	 * (ATA_MISCCTL_RESETP		, 0) |
+	 * (ATA_MISCCTL_TIMORIDE	, 1)
+	 */
+	hwif_write32(base, 0x201, BK3710_MISCCTL);
+
+	/*
+	 * IORDYTMP IORDY Timer for Primary Register
+	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+	 */
+	hwif_write32(base, 0xFFFF, BK3710_IORDYTMP);
+
+	/*
+	 * Configure BMISP Register
+	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
+	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
+	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
+	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
+	 * (ATA_BMISP_DMAERROR	, CLEAR)
+	 */
+	hwif_write16(base, 0, BK3710_BMISP);
+
+	palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
+	palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+{
+	hw_regs_t ide_ctlr_info;
+	int index = 0;
+	int pribase;
+	struct clk *clkp;
+	struct resource *mem, *irq;
+	ide_hwif_t *hwif;
+	u32 base;
+	int ret;
+
+	clkp = clk_get(NULL, "IDECLK");
+	if (IS_ERR(clkp))
+		return -ENODEV;
+
+	ideclkp = clkp;
+	clk_enable(ideclkp);
+	ide_palm_clk = clk_get_rate(ideclkp)/100000;
+	ide_palm_clk = (10000/ide_palm_clk) + 1;
+	/* Register the IDE interface with Linux ATA Interface */
+	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem == NULL) {
+		printk(KERN_INFO "failed to get memory region resource\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq == NULL) {
+		printk(KERN_INFO "failed to get IRQ resource\n");
+		return -ENODEV;
+	}
+
+	base = mem->start;
+
+	/* Configure the Palm Chip controller */
+	palm_bk3710_chipinit(base);
+
+	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
+	for (index = 0; index < IDE_NR_PORTS - 2; index++)
+		ide_ctlr_info.io_ports[index] = pribase + index;
+	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
+			IDE_PALM_ATA_PRI_CTL_OFFSET;
+	ide_ctlr_info.irq = irq->start;
+	ide_ctlr_info.chipset = ide_palm3710;
+
+	if (!request_mem_region(mem->start, 8, "palm_bk3710")) {
+		printk(KERN_ERR "Error, memory region in use.\n");
+		return -EBUSY;
+	}
+
+	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &hwif) < 0) {
+		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
+		return -ENODEV;
+	}
+
+	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
+	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
+	hwif->mmio = 1;
+	hwif->ultra_mask = 0x1f;		/* Ultra DMA Mode 4 Max
+						(input clk 99MHz) */
+	hwif->mwdma_mask = 0x7;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	ide_setup_dma(hwif, mem->start, 8);
+
+	return 0;
+}
+
+static struct platform_driver platform_bk_driver = {
+	.driver = {
+		.name = "palm_bk3710",
+	},
+	.probe = palm_bk3710_probe,
+	.remove = NULL,
+};
+
+static int __init palm_bk3710_init(void)
+{
+	return platform_driver_register(&platform_bk_driver);
+}
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
+
Index: 2.6.24-rc8.ide/drivers/ide/ide-proc.c
===================================================================
--- 2.6.24-rc8.ide.orig/drivers/ide/ide-proc.c
+++ 2.6.24-rc8.ide/drivers/ide/ide-proc.c
@@ -67,6 +67,7 @@ static int proc_ide_read_imodel
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
 		case ide_au1xxx:	name = "au1xxx";	break;
+		case ide_palm3710:      name = "palm3710";      break;
 		case ide_etrax100:	name = "etrax100";	break;
 		case ide_acorn:		name = "acorn";		break;
 		default:		name = "(unknown)";	break;
Index: 2.6.24-rc8.ide/include/linux/ide.h
===================================================================
--- 2.6.24-rc8.ide.orig/include/linux/ide.h
+++ 2.6.24-rc8.ide/include/linux/ide.h
@@ -202,7 +202,7 @@ enum {		ide_unknown,	ide_generic,	ide_pc
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_au1xxx, ide_forced
+		ide_au1xxx,	ide_palm3710,	ide_forced
 };
 
 typedef u8 hwif_chipset_t;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-24 15:01 Anton Salnikov
@ 2008-01-24 19:18 ` Sergei Shtylyov
  0 siblings, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-24 19:18 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

Anton Salnikov wrote:

> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24-rc8.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
> ---

> Index: 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.24-rc8.ide/drivers/ide/arm/palm_bk3710.c
> @@ -0,0 +1,428 @@
> +static inline u8 hwif_read8(u32 base, u32 reg)
> +{
> +	return readb(base + reg);
> +}
> +
> +static inline void hwif_write8(u32 base, u8 val, u32 reg)
> +{
> +	writeb(val, base + reg);
> +}
> +
> +static inline u16 hwif_read16(u32 base, u32 reg)
> +{
> +	return readw(base + reg);
> +}
> +
> +static inline void hwif_write16(u32 base, u16 val, u32 reg)
> +{
> +	writew(val, base + reg);
> +}
> +
> +static inline u32 hwif_read32(u32 base, u32 reg)
> +{
> +	return readl(base + reg);
> +}
> +
> +static inline void hwif_write32(u32 base, u32 val, u32 reg)
> +{
> +	writel(val, base + reg);
> +}

    Hm, I don't see why you need those accessors but well...

> +static void palm_bk3710_setudmamode(u32 base, unsigned int dev,
> +				    unsigned int mode)
> +{
> +	u8 tenv, trp, t0;
> +	u32 val32;
> +	u16 val16;
> +
> +	/* DMA Data Setup */
> +	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
> +	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +
> +	/* udmatim Register */
> +	val16 = hwif_read16(base, BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
> +	val16 |= (mode << ((!dev) ? 0 : 4));

    Why not (dev ? 4 : 0) like the rest?

> +	hwif_write16(base, val16, BK3710_UDMATIM);
> +
> +	/* udmastb Ultra DMA Access Strobe Width */
> +	val32 = hwif_read32(base, BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (t0 << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_UDMASTB);
> +
> +	/* udmatrp Ultra DMA Ready to Pause Time */
> +	val32 = hwif_read32(base, BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (trp << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_UDMATRP);
> +
> +	/* udmaenv Ultra DMA envelop Time */
> +	val32 = hwif_read32(base, BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (tenv << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_UDMAENV);
> +
> +	/* Enable UDMA for Device */
> +	val16 = hwif_read16(base, BK3710_UDMACTL) | (1 << dev);
> +	hwif_write16(base, val16, BK3710_UDMACTL);
> +}
> +
> +static void palm_bk3710_setdmamode(u32 base, unsigned int dev,
> +				   unsigned short min_cycle,
> +				   unsigned int mode)
> +{
> +	u8 td, tkw, t0;
> +	u32 val32;
> +	u16 val16;
> +
> +	unsigned cycletime = max_t(int, ide_timing_find_mode(mode)->cycle,
> +				   min_cycle);

    Hm, why integer comparison and then unsigned maximum?

> +
> +	/* DMA Data Setup */
> +	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	td = (ide_timing_find_mode(mode)->active + ide_palm_clk - 1)
> +			/ ide_palm_clk;

    Couldn't you call ide_timing_find_mode() only once?

[...]

> +static int __devinit palm_bk3710_probe(struct platform_device *pdev)
> +{
> +	hw_regs_t ide_ctlr_info;
> +	int index = 0;
> +	int pribase;
> +	struct clk *clkp;
> +	struct resource *mem, *irq;
> +	ide_hwif_t *hwif;
> +	u32 base;
> +	int ret;
> +
> +	clkp = clk_get(NULL, "IDECLK");
> +	if (IS_ERR(clkp))
> +		return -ENODEV;
> +
> +	ideclkp = clkp;
> +	clk_enable(ideclkp);
> +	ide_palm_clk = clk_get_rate(ideclkp)/100000;
> +	ide_palm_clk = (10000/ide_palm_clk) + 1;
> +	/* Register the IDE interface with Linux ATA Interface */
> +	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (mem == NULL) {
> +		printk(KERN_INFO "failed to get memory region resource\n");

    This deserves KERN_ERR, not KERN_INFO.

> +		return -ENODEV;
> +	}
> +	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (irq == NULL) {
> +		printk(KERN_INFO "failed to get IRQ resource\n");

    This too...

> +		return -ENODEV;
> +	}
> +
> +	base = mem->start;
> +
> +	/* Configure the Palm Chip controller */
> +	palm_bk3710_chipinit(base);
> +
> +	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
> +	for (index = 0; index < IDE_NR_PORTS - 2; index++)
> +		ide_ctlr_info.io_ports[index] = pribase + index;
> +	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
> +			IDE_PALM_ATA_PRI_CTL_OFFSET;
> +	ide_ctlr_info.irq = irq->start;
> +	ide_ctlr_info.chipset = ide_palm3710;
> +
> +	if (!request_mem_region(mem->start, 8, "palm_bk3710")) {
> +		printk(KERN_ERR "Error, memory region in use.\n");
> +		return -EBUSY;
> +	}

    Well, you either have to also register sub-resources for the IDE 
command/control register blocks since with hwif->mmiops == 1 the IDE core 
won't do this for you, or don't register any sub-resources at all, being 
content with what platform_device_add() did for us. BTW, don't forget extend 
the platform resource to account for IDE command/control register blocks.

> +	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &hwif) < 0) {
> +		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
> +		return -ENODEV;
> +	}
> +
> +	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
> +	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
> +	hwif->mmio = 1;

    Well, dealing with a memory-mapped IDE device, the driver lack 
default_hwif_mmiops() call...

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] Palmchip BK3710 IDE driver
@ 2008-01-25 12:12 Anton Salnikov
  2008-01-29 18:36 ` Sergei Shtylyov
  2008-02-02  0:29 ` Bartlomiej Zolnierkiewicz
  0 siblings, 2 replies; 27+ messages in thread
From: Anton Salnikov @ 2008-01-25 12:12 UTC (permalink / raw)
  To: linux-ide; +Cc: bzolnier

This is Palmchip BK3710 IDE controller support for kernel version 2.6.24.
The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
Supports interface to compact Flash (CF) configured in True-IDE mode.

Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
---

 drivers/ide/Kconfig           |    8 
 drivers/ide/arm/Makefile      |    1 
 drivers/ide/arm/palm_bk3710.c |  424 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ide/ide-proc.c        |    1 
 include/linux/ide.h           |    2 
 5 files changed, 435 insertions(+), 1 deletion(-)

Index: 2.6.24.ide/drivers/ide/Kconfig
===================================================================
--- 2.6.24.ide.orig/drivers/ide/Kconfig
+++ 2.6.24.ide/drivers/ide/Kconfig
@@ -1008,6 +1008,14 @@ config BLK_DEV_Q40IDE
 	  normally be on; disable it only if you are running a custom hard
 	  drive subsystem through an expansion card.
 
+config BLK_DEV_PALMCHIP_BK3710
+	bool "Palmchip bk3710 IDE controller support"
+	depends on ARCH_DAVINCI
+	select BLK_DEV_IDEDMA_PCI
+	help
+	  Say Y here if you want to support the onchip IDE controller on the
+	  TI DaVinci SoC
+
 config BLK_DEV_MPC8xx_IDE
 	bool "MPC8xx IDE support"
 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
BLK_DEV_IDE=y && !PPC_MERGE
Index: 2.6.24.ide/drivers/ide/arm/Makefile
===================================================================
--- 2.6.24.ide.orig/drivers/ide/arm/Makefile
+++ 2.6.24.ide/drivers/ide/arm/Makefile
@@ -2,5 +2,6 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
Index: 2.6.24.ide/drivers/ide/arm/palm_bk3710.c
===================================================================
--- /dev/null
+++ 2.6.24.ide/drivers/ide/arm/palm_bk3710.c
@@ -0,0 +1,424 @@
+/*
+ * Palmchip bk3710 IDE controller
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Offset of the primary interface registers */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
+
+/* Primary Control Offset */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
+
+/*
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+struct palm_bk3710_udmatiming {
+	unsigned int rptime;	/* Ready to pause time  */
+	unsigned int cycletime;	/* Cycle Time           */
+};
+
+#define BK3710_BMICP		0x00
+#define BK3710_BMISP		0x02
+#define BK3710_BMIDTP		0x04
+#define BK3710_BMICS		0x08
+#define BK3710_BMISS		0x0A
+#define BK3710_BMIDTS		0x0C
+#define BK3710_IDETIMP		0x40
+#define BK3710_IDETIMS		0x42
+#define BK3710_SIDETIM		0x44
+#define BK3710_SLEWCTL		0x45
+#define BK3710_IDESTATUS	0x47
+#define BK3710_UDMACTL		0x48
+#define BK3710_UDMATIM		0x4A
+#define BK3710_MISCCTL		0x50
+#define BK3710_REGSTB		0x54
+#define BK3710_REGRCVR		0x58
+#define BK3710_DATSTB		0x5C
+#define BK3710_DATRCVR		0x60
+#define BK3710_DMASTB		0x64
+#define BK3710_DMARCVR		0x68
+#define BK3710_UDMASTB		0x6C
+#define BK3710_UDMATRP		0x70
+#define BK3710_UDMAENV		0x74
+#define BK3710_IORDYTMP		0x78
+#define BK3710_IORDYTMS		0x7C
+
+#include "../ide-timing.h"
+
+static long ide_palm_clk;
+
+static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
+	{160, 240},		/* UDMA Mode 0 */
+	{125, 160},		/* UDMA Mode 1 */
+	{100, 120},		/* UDMA Mode 2 */
+	{100, 90},		/* UDMA Mode 3 */
+	{85,  60},		/* UDMA Mode 4 */
+};
+
+static struct clk *ideclkp;
+
+static inline u8 hwif_read8(u32 base, u32 reg)
+{
+	return readb(base + reg);
+}
+
+static inline void hwif_write8(u32 base, u8 val, u32 reg)
+{
+	writeb(val, base + reg);
+}
+
+static inline u16 hwif_read16(u32 base, u32 reg)
+{
+	return readw(base + reg);
+}
+
+static inline void hwif_write16(u32 base, u16 val, u32 reg)
+{
+	writew(val, base + reg);
+}
+
+static inline u32 hwif_read32(u32 base, u32 reg)
+{
+	return readl(base + reg);
+}
+
+static inline void hwif_write32(u32 base, u32 val, u32 reg)
+{
+	writel(val, base + reg);
+}
+
+static void palm_bk3710_setudmamode(u32 base, unsigned int dev,
+				    unsigned int mode)
+{
+	u8 tenv, trp, t0;
+	u32 val32;
+	u16 val16;
+
+	/* DMA Data Setup */
+	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+
+	/* udmatim Register */
+	val16 = hwif_read16(base, BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
+	val16 |= (mode << (dev ? 4 : 0));
+	hwif_write16(base, val16, BK3710_UDMATIM);
+
+	/* udmastb Ultra DMA Access Strobe Width */
+	val32 = hwif_read32(base, BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t0 << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_UDMASTB);
+
+	/* udmatrp Ultra DMA Ready to Pause Time */
+	val32 = hwif_read32(base, BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+	val32 |= (trp << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_UDMATRP);
+
+	/* udmaenv Ultra DMA envelop Time */
+	val32 = hwif_read32(base, BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+	val32 |= (tenv << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_UDMAENV);
+
+	/* Enable UDMA for Device */
+	val16 = hwif_read16(base, BK3710_UDMACTL) | (1 << dev);
+	hwif_write16(base, val16, BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setdmamode(u32 base, unsigned int dev,
+				   unsigned short min_cycle,
+				   unsigned int mode)
+{
+	u8 td, tkw, t0;
+	u32 val32;
+	u16 val16;
+	struct ide_timing *t;
+	int cycletime;
+
+	t = ide_timing_find_mode(mode);
+	cycletime = max_t(int, t->cycle, min_cycle);
+
+	/* DMA Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
+	tkw = t0 - td - 1;
+	td -= 1;
+
+	val32 = hwif_read32(base, BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (td << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DMASTB);
+
+	val32 = hwif_read32(base, BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (tkw << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DMARCVR);
+
+	/* Disable UDMA for Device */
+	val16 = hwif_read16(base, BK3710_UDMACTL) & ~(1 << dev);
+	hwif_write16(base, val16, BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setpiomode(u32 base, ide_drive_t *mate,
+				   unsigned int dev, unsigned int cycletime,
+				   unsigned int mode)
+{
+	u8 t2, t2i, t0;
+	u32 val32;
+	struct ide_timing *t;
+
+	/* PIO Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
+	      ide_palm_clk - 1)	/ ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val32 = hwif_read32(base, BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2 << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DATSTB);
+
+	val32 = hwif_read32(base, BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2i << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_DATRCVR);
+
+	if (mate && mate->present) {
+		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+
+		if (mode2 < mode)
+			mode = mode2;
+	}
+
+	/* TASKFILE Setup */
+	t = ide_timing_find_mode(XFER_PIO_0 + mode);
+	t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val32 = hwif_read32(base, BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2 << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_REGSTB);
+
+	val32 = hwif_read32(base, BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2i << (dev ? 8 : 0));
+	hwif_write32(base, val32, BK3710_REGRCVR);
+}
+
+static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+{
+	int is_slave = drive->dn & 1;
+	u32 base = drive->hwif->dma_master;
+
+	if (xferspeed >= XFER_UDMA_0) {
+		palm_bk3710_setudmamode(base, is_slave,
+					xferspeed - XFER_UDMA_0);
+	} else {
+		palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
+				       xferspeed);
+	}
+}
+
+static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+	unsigned int cycle_time;
+	int is_slave = drive->dn & 1;
+	ide_drive_t *mate;
+	u32 base = drive->hwif->dma_master;
+
+	/*
+	 * Obtain the drive PIO data for tuning the Palm Chip registers
+	 */
+	cycle_time = ide_pio_cycle_time(drive, pio);
+	mate = ide_get_paired_drive(drive);
+	palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
+}
+
+static void __devinit palm_bk3710_chipinit(u32 base)
+{
+	/*
+	 * enable the reset_en of ATA controller so that when ata signals
+	 * are brought out, by writing into device config. at that
+	 * time por_n signal should not be 'Z' and have a stable value.
+	 */
+	hwif_write32(base, 0x0300, BK3710_MISCCTL);
+
+	/* wait for some time and deassert the reset of ATA Device. */
+	mdelay(100);
+
+	/* Deassert the Reset */
+	hwif_write32(base, 0x0200, BK3710_MISCCTL);
+
+	/*
+	 * Program the IDETIMP Register Value based on the following assumptions
+	 *
+	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
+	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
+	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
+	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
+	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
+	 */
+	hwif_write16(base, 0xB388, BK3710_IDETIMP);
+
+	/*
+	 * Configure  SIDETIM  Register
+	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
+	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
+	 */
+	hwif_write8(base, 0, BK3710_SIDETIM);
+
+	/*
+	 * UDMACTL Ultra-ATA DMA Control
+	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
+	 * (ATA_UDMACTL_UDMAP0	, 0 )
+	 *
+	 */
+	hwif_write16(base, 0, BK3710_UDMACTL);
+
+	/*
+	 * MISCCTL Miscellaneous Conrol Register
+	 * (ATA_MISCCTL_RSTMODEP	, 1) |
+	 * (ATA_MISCCTL_RESETP		, 0) |
+	 * (ATA_MISCCTL_TIMORIDE	, 1)
+	 */
+	hwif_write32(base, 0x201, BK3710_MISCCTL);
+
+	/*
+	 * IORDYTMP IORDY Timer for Primary Register
+	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+	 */
+	hwif_write32(base, 0xFFFF, BK3710_IORDYTMP);
+
+	/*
+	 * Configure BMISP Register
+	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
+	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
+	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
+	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
+	 * (ATA_BMISP_DMAERROR	, CLEAR)
+	 */
+	hwif_write16(base, 0, BK3710_BMISP);
+
+	palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
+	palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+{
+	hw_regs_t ide_ctlr_info;
+	int index = 0;
+	int pribase;
+	struct clk *clkp;
+	struct resource *mem, *irq;
+	ide_hwif_t *hwif;
+	u32 base;
+
+	clkp = clk_get(NULL, "IDECLK");
+	if (IS_ERR(clkp))
+		return -ENODEV;
+
+	ideclkp = clkp;
+	clk_enable(ideclkp);
+	ide_palm_clk = clk_get_rate(ideclkp)/100000;
+	ide_palm_clk = (10000/ide_palm_clk) + 1;
+	/* Register the IDE interface with Linux ATA Interface */
+	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem == NULL) {
+		printk(KERN_ERR "failed to get memory region resource\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq == NULL) {
+		printk(KERN_ERR "failed to get IRQ resource\n");
+		return -ENODEV;
+	}
+
+	base = mem->start;
+
+	/* Configure the Palm Chip controller */
+	palm_bk3710_chipinit(base);
+
+	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
+	for (index = 0; index < IDE_NR_PORTS - 2; index++)
+		ide_ctlr_info.io_ports[index] = pribase + index;
+	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
+			IDE_PALM_ATA_PRI_CTL_OFFSET;
+	ide_ctlr_info.irq = irq->start;
+	ide_ctlr_info.chipset = ide_palm3710;
+
+	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &hwif) < 0) {
+		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
+		return -ENODEV;
+	}
+
+	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
+	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
+	hwif->mmio = 1;
+	default_hwif_mmiops(hwif);
+	hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
+						(input clk 99MHz) */
+	hwif->mwdma_mask = 0x7;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	ide_setup_dma(hwif, mem->start, 8);
+
+	return 0;
+}
+
+static struct platform_driver platform_bk_driver = {
+	.driver = {
+		.name = "palm_bk3710",
+	},
+	.probe = palm_bk3710_probe,
+	.remove = NULL,
+};
+
+static int __init palm_bk3710_init(void)
+{
+	return platform_driver_register(&platform_bk_driver);
+}
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
+
Index: 2.6.24.ide/drivers/ide/ide-proc.c
===================================================================
--- 2.6.24.ide.orig/drivers/ide/ide-proc.c
+++ 2.6.24.ide/drivers/ide/ide-proc.c
@@ -67,6 +67,7 @@ static int proc_ide_read_imodel
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
 		case ide_au1xxx:	name = "au1xxx";	break;
+		case ide_palm3710:      name = "palm3710";      break;
 		case ide_etrax100:	name = "etrax100";	break;
 		case ide_acorn:		name = "acorn";		break;
 		default:		name = "(unknown)";	break;
Index: 2.6.24.ide/include/linux/ide.h
===================================================================
--- 2.6.24.ide.orig/include/linux/ide.h
+++ 2.6.24.ide/include/linux/ide.h
@@ -202,7 +202,7 @@ enum {		ide_unknown,	ide_generic,	ide_pc
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_au1xxx, ide_forced
+		ide_au1xxx,	ide_palm3710,	ide_forced
 };
 
 typedef u8 hwif_chipset_t;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-25 12:12 Anton Salnikov
@ 2008-01-29 18:36 ` Sergei Shtylyov
  2008-01-29 18:38   ` Alan Cox
  2008-02-02  0:29 ` Bartlomiej Zolnierkiewicz
  1 sibling, 1 reply; 27+ messages in thread
From: Sergei Shtylyov @ 2008-01-29 18:36 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

Hello.

Anton Salnikov wrote:

> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>

Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>

> Index: 2.6.24.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.24.ide/drivers/ide/arm/palm_bk3710.c

> +static void palm_bk3710_setudmamode(u32 base, unsigned int dev,
> +				    unsigned int mode)
> +{
> +	u8 tenv, trp, t0;
> +	u32 val32;
> +	u16 val16;
> +
> +	/* DMA Data Setup */
> +	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
> +	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +
> +	/* udmatim Register */
> +	val16 = hwif_read16(base, BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
> +	val16 |= (mode << (dev ? 4 : 0));

    Needless parens all over the code like this...
    Also, you could have made it either 2 (getting rid of |= operator) or 4 
lines (read/write, &=, and |=).

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-29 18:36 ` Sergei Shtylyov
@ 2008-01-29 18:38   ` Alan Cox
  0 siblings, 0 replies; 27+ messages in thread
From: Alan Cox @ 2008-01-29 18:38 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Anton Salnikov, linux-ide, bzolnier


>     Needless parens all over the code like this...
>     Also, you could have made it either 2 (getting rid of |= operator) or 4 
> lines (read/write, &=, and |=).

	mode |= dev << 4;


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-01-25 12:12 Anton Salnikov
  2008-01-29 18:36 ` Sergei Shtylyov
@ 2008-02-02  0:29 ` Bartlomiej Zolnierkiewicz
  1 sibling, 0 replies; 27+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-02-02  0:29 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, Sergei Shtylyov, Alan Cox


Hi,

On Friday 25 January 2008, Anton Salnikov wrote:
> This is Palmchip BK3710 IDE controller support for kernel version 2.6.24.
> The IDE controller logic supports PIO, multiword DMA and ultra-DMA modes.
> Supports interface to compact Flash (CF) configured in True-IDE mode.

Unfortunately some changes merged after 2.6.24 broke the build:

drivers/ide/arm/palm_bk3710.c: In function ‘palm_bk3710_set_dma_mode’:
drivers/ide/arm/palm_bk3710.c:243: error: ‘struct hwif_s’ has no member named ‘dma_master’
drivers/ide/arm/palm_bk3710.c: In function ‘palm_bk3710_set_pio_mode’:
drivers/ide/arm/palm_bk3710.c:259: error: ‘struct hwif_s’ has no member named ‘dma_master’

[ ->dma_master is gone, ->dma_base should be used instead ]

drivers/ide/arm/palm_bk3710.c: In function ‘palm_bk3710_probe’:
drivers/ide/arm/palm_bk3710.c:389: error: too many arguments to function ‘ide_register_hw’

[ 'initializing' argument is gone, just removing it is OK ]

drivers/ide/arm/palm_bk3710.c:404: error: too many arguments to function ‘ide_setup_dma’

[ 'num_ports' argument is gone, just removing it is OK ]


Please re-sync the patch with the current Linus' git tree.


There are also few less critical issues left...

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
> ---
> 
>  drivers/ide/Kconfig           |    8 
>  drivers/ide/arm/Makefile      |    1 
>  drivers/ide/arm/palm_bk3710.c |  424 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/ide/ide-proc.c        |    1 
>  include/linux/ide.h           |    2 
>  5 files changed, 435 insertions(+), 1 deletion(-)
> 
> Index: 2.6.24.ide/drivers/ide/Kconfig
> ===================================================================
> --- 2.6.24.ide.orig/drivers/ide/Kconfig
> +++ 2.6.24.ide/drivers/ide/Kconfig
> @@ -1008,6 +1008,14 @@ config BLK_DEV_Q40IDE
>  	  normally be on; disable it only if you are running a custom hard
>  	  drive subsystem through an expansion card.
>  
> +config BLK_DEV_PALMCHIP_BK3710
> +	bool "Palmchip bk3710 IDE controller support"

'tristate'

> +	depends on ARCH_DAVINCI
> +	select BLK_DEV_IDEDMA_PCI
> +	help
> +	  Say Y here if you want to support the onchip IDE controller on the
> +	  TI DaVinci SoC
> +
>  config BLK_DEV_MPC8xx_IDE
>  	bool "MPC8xx IDE support"
>  	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
> BLK_DEV_IDE=y && !PPC_MERGE
> Index: 2.6.24.ide/drivers/ide/arm/Makefile
> ===================================================================
> --- 2.6.24.ide.orig/drivers/ide/arm/Makefile
> +++ 2.6.24.ide/drivers/ide/arm/Makefile

[...]

> +static inline u8 hwif_read8(u32 base, u32 reg)
> +{
> +	return readb(base + reg);
> +}
> +
> +static inline void hwif_write8(u32 base, u8 val, u32 reg)
> +{
> +	writeb(val, base + reg);
> +}
> +
> +static inline u16 hwif_read16(u32 base, u32 reg)
> +{
> +	return readw(base + reg);
> +}
> +
> +static inline void hwif_write16(u32 base, u16 val, u32 reg)
> +{
> +	writew(val, base + reg);
> +}
> +
> +static inline u32 hwif_read32(u32 base, u32 reg)
> +{
> +	return readl(base + reg);
> +}
> +
> +static inline void hwif_write32(u32 base, u32 val, u32 reg)
> +{
> +	writel(val, base + reg);
> +}

drivers/ide/arm/palm_bk3710.c: In function ‘hwif_read8’:
drivers/ide/arm/palm_bk3710.c:93: warning: passing argument 1 of ‘readb’ makes pointer from integer without a cast
drivers/ide/arm/palm_bk3710.c: In function ‘hwif_write8’:
drivers/ide/arm/palm_bk3710.c:98: warning: passing argument 2 of ‘writeb’ makes pointer from integer without a cast
drivers/ide/arm/palm_bk3710.c: In function ‘hwif_read16’:
drivers/ide/arm/palm_bk3710.c:103: warning: passing argument 1 of ‘readw’ makes pointer from integer without a cast
drivers/ide/arm/palm_bk3710.c: In function ‘hwif_write16’:
drivers/ide/arm/palm_bk3710.c:108: warning: passing argument 2 of ‘writew’ makes pointer from integer without a cast
drivers/ide/arm/palm_bk3710.c: In function ‘hwif_read32’:
drivers/ide/arm/palm_bk3710.c:113: warning: passing argument 1 of ‘readl’ makes pointer from integer without a cast
drivers/ide/arm/palm_bk3710.c: In function ‘hwif_write32’:
drivers/ide/arm/palm_bk3710.c:118: warning: passing argument 2 of ‘writel’ makes pointer from integer without a cast

'base' should be of 'void __iomem *' type for read*/write* ops

Besides: because the driver supports multiple controllers now these wrappers
doesn't provide any value and just obfuscate the code (as noticed by Alan).

Please remove them.

> +static void palm_bk3710_setudmamode(u32 base, unsigned int dev,

'base' should be of 'void __iomem *' type for read*/*write ops

[ casting from u32 can be done in the caller ]

> +				    unsigned int mode)
> +{
> +	u8 tenv, trp, t0;
> +	u32 val32;
> +	u16 val16;
> +
> +	/* DMA Data Setup */
> +	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
> +	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
> +			/ ide_palm_clk - 1;
> +
> +	/* udmatim Register */
> +	val16 = hwif_read16(base, BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
> +	val16 |= (mode << (dev ? 4 : 0));
> +	hwif_write16(base, val16, BK3710_UDMATIM);
> +
> +	/* udmastb Ultra DMA Access Strobe Width */
> +	val32 = hwif_read32(base, BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (t0 << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_UDMASTB);
> +
> +	/* udmatrp Ultra DMA Ready to Pause Time */
> +	val32 = hwif_read32(base, BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (trp << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_UDMATRP);
> +
> +	/* udmaenv Ultra DMA envelop Time */
> +	val32 = hwif_read32(base, BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (tenv << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_UDMAENV);
> +
> +	/* Enable UDMA for Device */
> +	val16 = hwif_read16(base, BK3710_UDMACTL) | (1 << dev);
> +	hwif_write16(base, val16, BK3710_UDMACTL);
> +}
> +
> +static void palm_bk3710_setdmamode(u32 base, unsigned int dev,

ditto

> +				   unsigned short min_cycle,
> +				   unsigned int mode)
> +{
> +	u8 td, tkw, t0;
> +	u32 val32;
> +	u16 val16;
> +	struct ide_timing *t;
> +	int cycletime;
> +
> +	t = ide_timing_find_mode(mode);
> +	cycletime = max_t(int, t->cycle, min_cycle);
> +
> +	/* DMA Data Setup */
> +	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
> +	tkw = t0 - td - 1;
> +	td -= 1;
> +
> +	val32 = hwif_read32(base, BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (td << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_DMASTB);
> +
> +	val32 = hwif_read32(base, BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (tkw << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_DMARCVR);
> +
> +	/* Disable UDMA for Device */
> +	val16 = hwif_read16(base, BK3710_UDMACTL) & ~(1 << dev);
> +	hwif_write16(base, val16, BK3710_UDMACTL);
> +}
> +
> +static void palm_bk3710_setpiomode(u32 base, ide_drive_t *mate,

ditto

> +				   unsigned int dev, unsigned int cycletime,
> +				   unsigned int mode)
> +{
> +	u8 t2, t2i, t0;
> +	u32 val32;
> +	struct ide_timing *t;
> +
> +	/* PIO Data Setup */
> +	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
> +	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
> +	      ide_palm_clk - 1)	/ ide_palm_clk;
> +
> +	t2i = t0 - t2 - 1;
> +	t2 -= 1;
> +
> +	val32 = hwif_read32(base, BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (t2 << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_DATSTB);
> +
> +	val32 = hwif_read32(base, BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (t2i << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_DATRCVR);
> +
> +	if (mate && mate->present) {
> +		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
> +
> +		if (mode2 < mode)
> +			mode = mode2;
> +	}
> +
> +	/* TASKFILE Setup */
> +	t = ide_timing_find_mode(XFER_PIO_0 + mode);
> +	t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
> +	t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
> +
> +	t2i = t0 - t2 - 1;
> +	t2 -= 1;
> +
> +	val32 = hwif_read32(base, BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (t2 << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_REGSTB);
> +
> +	val32 = hwif_read32(base, BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
> +	val32 |= (t2i << (dev ? 8 : 0));
> +	hwif_write32(base, val32, BK3710_REGRCVR);
> +}
> +
> +static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
> +{
> +	int is_slave = drive->dn & 1;
> +	u32 base = drive->hwif->dma_master;
> +
> +	if (xferspeed >= XFER_UDMA_0) {
> +		palm_bk3710_setudmamode(base, is_slave,
> +					xferspeed - XFER_UDMA_0);
> +	} else {
> +		palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
> +				       xferspeed);
> +	}
> +}
> +
> +static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
> +{
> +	unsigned int cycle_time;
> +	int is_slave = drive->dn & 1;
> +	ide_drive_t *mate;
> +	u32 base = drive->hwif->dma_master;
> +
> +	/*
> +	 * Obtain the drive PIO data for tuning the Palm Chip registers
> +	 */
> +	cycle_time = ide_pio_cycle_time(drive, pio);
> +	mate = ide_get_paired_drive(drive);
> +	palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
> +}
> +
> +static void __devinit palm_bk3710_chipinit(u32 base)

'u32' -> 'void __iomem *'

> +{
> +	/*
> +	 * enable the reset_en of ATA controller so that when ata signals
> +	 * are brought out, by writing into device config. at that
> +	 * time por_n signal should not be 'Z' and have a stable value.
> +	 */
> +	hwif_write32(base, 0x0300, BK3710_MISCCTL);
> +
> +	/* wait for some time and deassert the reset of ATA Device. */
> +	mdelay(100);
> +
> +	/* Deassert the Reset */
> +	hwif_write32(base, 0x0200, BK3710_MISCCTL);
> +
> +	/*
> +	 * Program the IDETIMP Register Value based on the following assumptions
> +	 *
> +	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
> +	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
> +	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
> +	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
> +	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
> +	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
> +	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
> +	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
> +	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
> +	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
> +	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
> +	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
> +	 */
> +	hwif_write16(base, 0xB388, BK3710_IDETIMP);
> +
> +	/*
> +	 * Configure  SIDETIM  Register
> +	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
> +	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
> +	 */
> +	hwif_write8(base, 0, BK3710_SIDETIM);
> +
> +	/*
> +	 * UDMACTL Ultra-ATA DMA Control
> +	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
> +	 * (ATA_UDMACTL_UDMAP0	, 0 )
> +	 *
> +	 */
> +	hwif_write16(base, 0, BK3710_UDMACTL);
> +
> +	/*
> +	 * MISCCTL Miscellaneous Conrol Register
> +	 * (ATA_MISCCTL_RSTMODEP	, 1) |
> +	 * (ATA_MISCCTL_RESETP		, 0) |
> +	 * (ATA_MISCCTL_TIMORIDE	, 1)
> +	 */
> +	hwif_write32(base, 0x201, BK3710_MISCCTL);
> +
> +	/*
> +	 * IORDYTMP IORDY Timer for Primary Register
> +	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
> +	 */
> +	hwif_write32(base, 0xFFFF, BK3710_IORDYTMP);
> +
> +	/*
> +	 * Configure BMISP Register
> +	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
> +	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
> +	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
> +	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
> +	 * (ATA_BMISP_DMAERROR	, CLEAR)
> +	 */
> +	hwif_write16(base, 0, BK3710_BMISP);
> +
> +	palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
> +	palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
> +}
> +static int __devinit palm_bk3710_probe(struct platform_device *pdev)
> +{
> +	hw_regs_t ide_ctlr_info;
> +	int index = 0;
> +	int pribase;
> +	struct clk *clkp;
> +	struct resource *mem, *irq;
> +	ide_hwif_t *hwif;
> +	u32 base;

ditto

> +	clkp = clk_get(NULL, "IDECLK");
> +	if (IS_ERR(clkp))
> +		return -ENODEV;
> +
> +	ideclkp = clkp;
> +	clk_enable(ideclkp);
> +	ide_palm_clk = clk_get_rate(ideclkp)/100000;
> +	ide_palm_clk = (10000/ide_palm_clk) + 1;
> +	/* Register the IDE interface with Linux ATA Interface */
> +	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (mem == NULL) {
> +		printk(KERN_ERR "failed to get memory region resource\n");
> +		return -ENODEV;
> +	}
> +	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (irq == NULL) {
> +		printk(KERN_ERR "failed to get IRQ resource\n");
> +		return -ENODEV;
> +	}
> +
> +	base = mem->start;
> +
> +	/* Configure the Palm Chip controller */
> +	palm_bk3710_chipinit(base);
> +
> +	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
> +	for (index = 0; index < IDE_NR_PORTS - 2; index++)
> +		ide_ctlr_info.io_ports[index] = pribase + index;
> +	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
> +			IDE_PALM_ATA_PRI_CTL_OFFSET;
> +	ide_ctlr_info.irq = irq->start;
> +	ide_ctlr_info.chipset = ide_palm3710;
> +
> +	if (ide_register_hw(&ide_ctlr_info, NULL, 0, &hwif) < 0) {
> +		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
> +		return -ENODEV;
> +	}
> +
> +	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
> +	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
> +	hwif->mmio = 1;
> +	default_hwif_mmiops(hwif);
> +	hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
> +						(input clk 99MHz) */

I've just noticed that there is no cable detection for UDMA modes > UDMA2?

> +	hwif->mwdma_mask = 0x7;
> +	hwif->drives[0].autotune = 1;
> +	hwif->drives[1].autotune = 1;
> +
> +	ide_setup_dma(hwif, mem->start, 8);
> +
> +	return 0;
> +}

[...]

Otherwise the driver looks fine and will be merged once the above issues
get addressed so please recast+resubmit it.

Thanks,
Bart

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH] Palmchip BK3710 IDE driver
@ 2008-02-05 16:04 Anton Salnikov
  2008-02-06  1:35 ` Bartlomiej Zolnierkiewicz
  2008-05-15 18:32 ` Sergei Shtylyov
  0 siblings, 2 replies; 27+ messages in thread
From: Anton Salnikov @ 2008-02-05 16:04 UTC (permalink / raw)
  To: linux-ide; +Cc: bzolnier

I've tested the driver on 2.6.24.

I've made the changes you asked for. But when I tested them on arm/mach-davinci 
architecture on the current Linus' git there was link error undefined reference 
to symbol ide_hwif_setup_dma().
However on x86_64 architecture it compiles well without any warnings with 
respect to link error of undefined clk_get() clk_enable() clk_get_rate(), which 
are not present in this architecture.


> I've just noticed that there is no cable detection for UDMA modes > UDMA2?
For the present controller in documentation: Cable Select (CSEL) - unsupported 
IDE controller signal. This signal is not necessary because an 80-conductor 
cable must be used with the DM644x.

Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>
---

 drivers/ide/Kconfig           |    9 
 drivers/ide/arm/Makefile      |    1 
 drivers/ide/arm/palm_bk3710.c |  420 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ide/ide-proc.c        |    1 
 include/linux/ide.h           |    2 
 5 files changed, 432 insertions(+), 1 deletion(-)

Index: 2.6.25.ide/drivers/ide/Kconfig
===================================================================
--- 2.6.25.ide.orig/drivers/ide/Kconfig
+++ 2.6.25.ide/drivers/ide/Kconfig
@@ -1009,6 +1009,15 @@ config BLK_DEV_Q40IDE
 	  normally be on; disable it only if you are running a custom hard
 	  drive subsystem through an expansion card.
 
+config BLK_DEV_PALMCHIP_BK3710
+	tristate "Palmchip bk3710 IDE controller support"
+	depends on ARCH_DAVINCI
+	select BLK_DEV_IDEDMA_PCI
+	help
+	  Say Y here if you want to support the onchip IDE controller on the
+	  TI DaVinci SoC
+
+
 config BLK_DEV_MPC8xx_IDE
 	tristate "MPC8xx IDE support"
 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
BLK_DEV_IDE=y && !PPC_MERGE
Index: 2.6.25.ide/drivers/ide/arm/Makefile
===================================================================
--- 2.6.25.ide.orig/drivers/ide/arm/Makefile
+++ 2.6.25.ide/drivers/ide/arm/Makefile
@@ -2,6 +2,7 @@
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
 obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 
 ifeq ($(CONFIG_IDE_ARM), m)
 	obj-m += ide_arm.o
Index: 2.6.25.ide/drivers/ide/arm/palm_bk3710.c
===================================================================
--- /dev/null
+++ 2.6.25.ide/drivers/ide/arm/palm_bk3710.c
@@ -0,0 +1,420 @@
+/*
+ * Palmchip bk3710 IDE controller
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * 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.
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/* Offset of the primary interface registers */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
+
+/* Primary Control Offset */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
+
+/*
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+struct palm_bk3710_udmatiming {
+	unsigned int rptime;	/* Ready to pause time  */
+	unsigned int cycletime;	/* Cycle Time           */
+};
+
+#define BK3710_BMICP		0x00
+#define BK3710_BMISP		0x02
+#define BK3710_BMIDTP		0x04
+#define BK3710_BMICS		0x08
+#define BK3710_BMISS		0x0A
+#define BK3710_BMIDTS		0x0C
+#define BK3710_IDETIMP		0x40
+#define BK3710_IDETIMS		0x42
+#define BK3710_SIDETIM		0x44
+#define BK3710_SLEWCTL		0x45
+#define BK3710_IDESTATUS	0x47
+#define BK3710_UDMACTL		0x48
+#define BK3710_UDMATIM		0x4A
+#define BK3710_MISCCTL		0x50
+#define BK3710_REGSTB		0x54
+#define BK3710_REGRCVR		0x58
+#define BK3710_DATSTB		0x5C
+#define BK3710_DATRCVR		0x60
+#define BK3710_DMASTB		0x64
+#define BK3710_DMARCVR		0x68
+#define BK3710_UDMASTB		0x6C
+#define BK3710_UDMATRP		0x70
+#define BK3710_UDMAENV		0x74
+#define BK3710_IORDYTMP		0x78
+#define BK3710_IORDYTMS		0x7C
+
+#include "../ide-timing.h"
+
+static long ide_palm_clk;
+
+static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
+	{160, 240},		/* UDMA Mode 0 */
+	{125, 160},		/* UDMA Mode 1 */
+	{100, 120},		/* UDMA Mode 2 */
+	{100, 90},		/* UDMA Mode 3 */
+	{85,  60},		/* UDMA Mode 4 */
+};
+
+static struct clk *ideclkp;
+
+/*static inline u8 hwif_read8(u32 base, u32 reg)
+{
+	return readb(base + reg);
+}
+
+static inline u16 hwif_read16(u32 base, u32 reg)
+{
+	return readw(base + reg);
+}
+
+static inline void hwif_write16(u32 base, u16 val, u32 reg)
+{
+	writew(val, base + reg);
+}
+
+static inline u32 hwif_read32(u32 base, u32 reg)
+{
+	return readl(base + reg);
+}
+
+static inline void hwif_write32(u32 base, u32 val, u32 reg)
+{
+	writel(val, base + reg);
+}*/
+
+static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+				    unsigned int mode)
+{
+	u8 tenv, trp, t0;
+	u32 val32;
+	u16 val16;
+
+	/* DMA Data Setup */
+	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
+	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
+			/ ide_palm_clk - 1;
+
+	/* udmatim Register */
+	val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
+	val16 |= (mode << (dev ? 4 : 0));
+	writew(val16, base + BK3710_UDMATIM);
+
+	/* udmastb Ultra DMA Access Strobe Width */
+	val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t0 << (dev ? 8 : 0));
+	writel(val32, base + BK3710_UDMASTB);
+
+	/* udmatrp Ultra DMA Ready to Pause Time */
+	val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+	val32 |= (trp << (dev ? 8 : 0));
+	writel(val32, base + BK3710_UDMATRP);
+
+	/* udmaenv Ultra DMA envelop Time */
+	val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+	val32 |= (tenv << (dev ? 8 : 0));
+	writel(val32, base + BK3710_UDMAENV);
+
+	/* Enable UDMA for Device */
+	val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
+	writew(val16, base + BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
+				   unsigned short min_cycle,
+				   unsigned int mode)
+{
+	u8 td, tkw, t0;
+	u32 val32;
+	u16 val16;
+	struct ide_timing *t;
+	int cycletime;
+
+	t = ide_timing_find_mode(mode);
+	cycletime = max_t(int, t->cycle, min_cycle);
+
+	/* DMA Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
+	tkw = t0 - td - 1;
+	td -= 1;
+
+	val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (td << (dev ? 8 : 0));
+	writel(val32, base + BK3710_DMASTB);
+
+	val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (tkw << (dev ? 8 : 0));
+	writel(val32, base + BK3710_DMARCVR);
+
+	/* Disable UDMA for Device */
+	val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
+	writew(val16, base + BK3710_UDMACTL);
+}
+
+static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
+				   unsigned int dev, unsigned int cycletime,
+				   unsigned int mode)
+{
+	u8 t2, t2i, t0;
+	u32 val32;
+	struct ide_timing *t;
+
+	/* PIO Data Setup */
+	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
+	      ide_palm_clk - 1)	/ ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2 << (dev ? 8 : 0));
+	writel(val32, base + BK3710_DATSTB);
+
+	val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2i << (dev ? 8 : 0));
+	writel(val32, base + BK3710_DATRCVR);
+
+	if (mate && mate->present) {
+		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
+
+		if (mode2 < mode)
+			mode = mode2;
+	}
+
+	/* TASKFILE Setup */
+	t = ide_timing_find_mode(XFER_PIO_0 + mode);
+	t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
+	t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
+
+	t2i = t0 - t2 - 1;
+	t2 -= 1;
+
+	val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2 << (dev ? 8 : 0));
+	writel(val32, base + BK3710_REGSTB);
+
+	val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+	val32 |= (t2i << (dev ? 8 : 0));
+	writel(val32, base + BK3710_REGRCVR);
+}
+
+static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
+{
+	int is_slave = drive->dn & 1;
+	void __iomem *base = (void *)drive->hwif->dma_base;
+
+	if (xferspeed >= XFER_UDMA_0) {
+		palm_bk3710_setudmamode(base, is_slave,
+					xferspeed - XFER_UDMA_0);
+	} else {
+		palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
+				       xferspeed);
+	}
+}
+
+static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
+{
+	unsigned int cycle_time;
+	int is_slave = drive->dn & 1;
+	ide_drive_t *mate;
+	void __iomem *base = (void *)drive->hwif->dma_base;
+
+	/*
+	 * Obtain the drive PIO data for tuning the Palm Chip registers
+	 */
+	cycle_time = ide_pio_cycle_time(drive, pio);
+	mate = ide_get_paired_drive(drive);
+	palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
+}
+
+static void __devinit palm_bk3710_chipinit(void __iomem *base)
+{
+	/*
+	 * enable the reset_en of ATA controller so that when ata signals
+	 * are brought out, by writing into device config. at that
+	 * time por_n signal should not be 'Z' and have a stable value.
+	 */
+	writel(0x0300, base + BK3710_MISCCTL);
+
+	/* wait for some time and deassert the reset of ATA Device. */
+	mdelay(100);
+
+	/* Deassert the Reset */
+	writel(0x0200, base + BK3710_MISCCTL);
+
+	/*
+	 * Program the IDETIMP Register Value based on the following assumptions
+	 *
+	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
+	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
+	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
+	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
+	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
+	 */
+	writew(0xB388, base + BK3710_IDETIMP);
+
+	/*
+	 * Configure  SIDETIM  Register
+	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
+	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
+	 */
+	writeb(0, base + BK3710_SIDETIM);
+
+	/*
+	 * UDMACTL Ultra-ATA DMA Control
+	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
+	 * (ATA_UDMACTL_UDMAP0	, 0 )
+	 *
+	 */
+	writew(0, base + BK3710_UDMACTL);
+
+	/*
+	 * MISCCTL Miscellaneous Conrol Register
+	 * (ATA_MISCCTL_RSTMODEP	, 1) |
+	 * (ATA_MISCCTL_RESETP		, 0) |
+	 * (ATA_MISCCTL_TIMORIDE	, 1)
+	 */
+	writel(0x201, base + BK3710_MISCCTL);
+
+	/*
+	 * IORDYTMP IORDY Timer for Primary Register
+	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+	 */
+	writel(0xFFFF, base + BK3710_IORDYTMP);
+
+	/*
+	 * Configure BMISP Register
+	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
+	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
+	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
+	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
+	 * (ATA_BMISP_DMAERROR	, CLEAR)
+	 */
+	writew(0, base + BK3710_BMISP);
+
+	palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
+	palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+static int __devinit palm_bk3710_probe(struct platform_device *pdev)
+{
+	hw_regs_t ide_ctlr_info;
+	int index = 0;
+	int pribase;
+	struct clk *clkp;
+	struct resource *mem, *irq;
+	ide_hwif_t *hwif;
+	void __iomem *base;
+
+	clkp = clk_get(NULL, "IDECLK");
+	if (IS_ERR(clkp))
+		return -ENODEV;
+
+	ideclkp = clkp;
+	clk_enable(ideclkp);
+	ide_palm_clk = clk_get_rate(ideclkp)/100000;
+	ide_palm_clk = (10000/ide_palm_clk) + 1;
+	/* Register the IDE interface with Linux ATA Interface */
+	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (mem == NULL) {
+		printk(KERN_ERR "failed to get memory region resource\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (irq == NULL) {
+		printk(KERN_ERR "failed to get IRQ resource\n");
+		return -ENODEV;
+	}
+
+	base = (void *)mem->start;
+
+	/* Configure the Palm Chip controller */
+	palm_bk3710_chipinit(base);
+
+	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
+	for (index = 0; index < IDE_NR_PORTS - 2; index++)
+		ide_ctlr_info.io_ports[index] = pribase + index;
+	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
+			IDE_PALM_ATA_PRI_CTL_OFFSET;
+	ide_ctlr_info.irq = irq->start;
+	ide_ctlr_info.chipset = ide_palm3710;
+
+	if (ide_register_hw(&ide_ctlr_info, NULL, &hwif) < 0) {
+		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
+		return -ENODEV;
+	}
+
+	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
+	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
+	hwif->mmio = 1;
+	default_hwif_mmiops(hwif);
+	hwif->cbl = ATA_CBL_PATA80;
+	hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
+						(input clk 99MHz) */
+	hwif->mwdma_mask = 0x7;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
+
+	ide_setup_dma(hwif, mem->start);
+
+	return 0;
+}
+
+static struct platform_driver platform_bk_driver = {
+	.driver = {
+		.name = "palm_bk3710",
+	},
+	.probe = palm_bk3710_probe,
+	.remove = NULL,
+};
+
+static int __init palm_bk3710_init(void)
+{
+	return platform_driver_register(&platform_bk_driver);
+}
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
+
Index: 2.6.25.ide/drivers/ide/ide-proc.c
===================================================================
--- 2.6.25.ide.orig/drivers/ide/ide-proc.c
+++ 2.6.25.ide/drivers/ide/ide-proc.c
@@ -65,6 +65,7 @@ static int proc_ide_read_imodel
 		case ide_4drives:	name = "4drives";	break;
 		case ide_pmac:		name = "mac-io";	break;
 		case ide_au1xxx:	name = "au1xxx";	break;
+		case ide_palm3710:      name = "palm3710";      break;
 		case ide_etrax100:	name = "etrax100";	break;
 		case ide_acorn:		name = "acorn";		break;
 		default:		name = "(unknown)";	break;
Index: 2.6.25.ide/include/linux/ide.h
===================================================================
--- 2.6.25.ide.orig/include/linux/ide.h
+++ 2.6.25.ide/include/linux/ide.h
@@ -173,7 +173,7 @@ enum {		ide_unknown,	ide_generic,	ide_pc
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_au1xxx, ide_forced
+		ide_au1xxx,	ide_palm3710,	ide_forced
 };
 
 typedef u8 hwif_chipset_t;

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-02-05 16:04 Anton Salnikov
@ 2008-02-06  1:35 ` Bartlomiej Zolnierkiewicz
  2008-05-15 18:32 ` Sergei Shtylyov
  1 sibling, 0 replies; 27+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-02-06  1:35 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide

On Tuesday 05 February 2008, Anton Salnikov wrote:
> I've tested the driver on 2.6.24.
> 
> I've made the changes you asked for. But when I tested them on arm/mach-davinci 

Thanks!

> architecture on the current Linus' git there was link error undefined reference 
> to symbol ide_hwif_setup_dma().
> However on x86_64 architecture it compiles well without any warnings with 
> respect to link error of undefined clk_get() clk_enable() clk_get_rate(), which 
> are not present in this architecture.

ide_hwif_setup_dma() comes from setup-pci.c which depends on BLK_DEV_IDEPCI.
palm_bk3710 host driver selects BLK_DEV_IDEDMA_PCI which should also select
BLK_DEV_IDEPCI but PCI doesn't even seem to be supported by this ARM platform.

I (hopefully) workarounded the issue by adding an additional #ifdef to
<linux/ide.h> but it is a unmaintanable and ugly hack:

Index: b/include/linux/ide.h
===================================================================
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1014,7 +1014,8 @@ extern int __ide_pci_register_driver(str
 void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *);
 void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+/* FIXME: palm_bk3710 uses BLK_DEV_IDEDMA_PCI without BLK_DEV_IDEPCI! */
+#if defined(CONFIG_BLK_DEV_IDEPCI) && defined(CONFIG_BLK_DEV_IDEDMA_PCI)
 void ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
 #else
 static inline void ide_hwif_setup_dma(ide_hwif_t *hwif,


Anton/Sergei: please look into fixing it properly - we probably just need to
to have a new config option (CONFIG_IDE_SFF_DMA sounds neat) to be selected by
both BLK_DEV_{IDEDMA_PCI,PALMCHIP_BK3710} and to replace BLK_DEV_IDEDMA_PCI
#ifdefs in ide-dma.c.

> > I've just noticed that there is no cable detection for UDMA modes > UDMA2?
> For the present controller in documentation: Cable Select (CSEL) - unsupported 
> IDE controller signal. This signal is not necessary because an 80-conductor 
> cable must be used with the DM644x.
> 
> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>

Minor issue: the original patch description got lost somehow so I just used
the one from the previous version.

> ---
> 
>  drivers/ide/Kconfig           |    9 
>  drivers/ide/arm/Makefile      |    1 
>  drivers/ide/arm/palm_bk3710.c |  420 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/ide/ide-proc.c        |    1 
>  include/linux/ide.h           |    2 
>  5 files changed, 432 insertions(+), 1 deletion(-)
> 
> Index: 2.6.25.ide/drivers/ide/Kconfig
> ===================================================================
> --- 2.6.25.ide.orig/drivers/ide/Kconfig
> +++ 2.6.25.ide/drivers/ide/Kconfig
> @@ -1009,6 +1009,15 @@ config BLK_DEV_Q40IDE
>  	  normally be on; disable it only if you are running a custom hard
>  	  drive subsystem through an expansion card.
>  
> +config BLK_DEV_PALMCHIP_BK3710
> +	tristate "Palmchip bk3710 IDE controller support"
> +	depends on ARCH_DAVINCI
> +	select BLK_DEV_IDEDMA_PCI
> +	help
> +	  Say Y here if you want to support the onchip IDE controller on the
> +	  TI DaVinci SoC
> +
> +
>  config BLK_DEV_MPC8xx_IDE
>  	tristate "MPC8xx IDE support"
>  	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && 
> BLK_DEV_IDE=y && !PPC_MERGE
> Index: 2.6.25.ide/drivers/ide/arm/Makefile
> ===================================================================
> --- 2.6.25.ide.orig/drivers/ide/arm/Makefile
> +++ 2.6.25.ide/drivers/ide/arm/Makefile
> @@ -2,6 +2,7 @@
>  obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
>  obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
>  obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
> +obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
>  
>  ifeq ($(CONFIG_IDE_ARM), m)
>  	obj-m += ide_arm.o
> Index: 2.6.25.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.25.ide/drivers/ide/arm/palm_bk3710.c

[...]

> +/*static inline u8 hwif_read8(u32 base, u32 reg)
> +{
> +	return readb(base + reg);
> +}
> +
> +static inline u16 hwif_read16(u32 base, u32 reg)
> +{
> +	return readw(base + reg);
> +}
> +
> +static inline void hwif_write16(u32 base, u16 val, u32 reg)
> +{
> +	writew(val, base + reg);
> +}
> +
> +static inline u32 hwif_read32(u32 base, u32 reg)
> +{
> +	return readl(base + reg);
> +}
> +
> +static inline void hwif_write32(u32 base, u32 val, u32 reg)
> +{
> +	writel(val, base + reg);
> +}*/

I removed this chunk while merging the patch (no need for a dead code)

also added "Reviewed-by:" tags crediting Alan & Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH] Palmchip BK3710 IDE driver
  2008-02-05 16:04 Anton Salnikov
  2008-02-06  1:35 ` Bartlomiej Zolnierkiewicz
@ 2008-05-15 18:32 ` Sergei Shtylyov
  1 sibling, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2008-05-15 18:32 UTC (permalink / raw)
  To: Anton Salnikov; +Cc: linux-ide, bzolnier

Anton Salnikov wrote:

> I've tested the driver on 2.6.24.

    Unfortunately, I've never seen the platofrm device registration code until 
now...

> Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com>

> Index: 2.6.25.ide/drivers/ide/arm/palm_bk3710.c
> ===================================================================
> --- /dev/null
> +++ 2.6.25.ide/drivers/ide/arm/palm_bk3710.c
> @@ -0,0 +1,420 @@
[...]
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (mem == NULL) {
> +		printk(KERN_ERR "failed to get memory region resource\n");
> +		return -ENODEV;
> +	}
> +	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
> +	if (irq == NULL) {
> +		printk(KERN_ERR "failed to get IRQ resource\n");
> +		return -ENODEV;
> +	}
> +
> +	base = (void *)mem->start;

   Crrap! You shouldn't specify virtual addresses in the device resources 
whatever arch you are using. Should've been ioremap() here. And where did only 
my eyes were?

MBR, Sergei

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2008-05-15 18:33 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-17 18:50 [PATCH] Palmchip BK3710 IDE driver Anton Salnikov
2008-01-17 18:57 ` Sergei Shtylyov
2008-01-17 23:23 ` Alan Cox
2008-01-18 14:14   ` Sergei Shtylyov
2008-01-18 15:04     ` Alan Cox
2008-01-18 18:03       ` Sergei Shtylyov
2008-01-18 22:20         ` Bartlomiej Zolnierkiewicz
2008-01-18 22:19 ` Bartlomiej Zolnierkiewicz
  -- strict thread matches above, loose matches on Subject: below --
2008-01-21 18:44 Anton Salnikov
2008-01-21 19:51 ` Alan Cox
2008-01-22 12:11   ` Anton Salnikov
2008-01-22 14:37     ` Alan Cox
2008-01-22 19:31     ` Jeff Garzik
2008-01-22 20:30 ` Sergei Shtylyov
2008-01-22 22:22   ` Alan Cox
2008-01-23 13:38     ` Sergei Shtylyov
2008-01-23 14:59       ` Alan Cox
2008-01-23 14:32 ` Sergei Shtylyov
2008-01-24 15:01 Anton Salnikov
2008-01-24 19:18 ` Sergei Shtylyov
2008-01-25 12:12 Anton Salnikov
2008-01-29 18:36 ` Sergei Shtylyov
2008-01-29 18:38   ` Alan Cox
2008-02-02  0:29 ` Bartlomiej Zolnierkiewicz
2008-02-05 16:04 Anton Salnikov
2008-02-06  1:35 ` Bartlomiej Zolnierkiewicz
2008-05-15 18:32 ` Sergei Shtylyov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).