* [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410
2010-05-27 8:22 [PATCH] Add Compact Flash driver for Samsung SoCs Kukjin Kim
@ 2010-05-27 8:22 ` Kukjin Kim
2010-05-27 8:52 ` Ben Dooks
2010-05-27 19:45 ` Russell King - ARM Linux
2010-05-27 8:22 ` [PATCH 2/4] ARM: S5PV210: Add support for Compact Flash driver on SMDKV210/SMDKC110 Kukjin Kim
` (2 subsequent siblings)
3 siblings, 2 replies; 24+ messages in thread
From: Kukjin Kim @ 2010-05-27 8:22 UTC (permalink / raw)
To: linux-arm-kernel
From: Abhilash Kesavan <a.kesavan@samsung.com>
Following is added for the CF-ATA driver:
- Platform data strucure definition and instantiation
- Platform device definition and enabling code
- Platform-specific gpio setup code
- CF controller register definitions
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
arch/arm/mach-s3c64xx/Kconfig | 7 +++
arch/arm/mach-s3c64xx/Makefile | 1 +
arch/arm/mach-s3c64xx/clock.c | 6 +++
arch/arm/mach-s3c64xx/include/mach/map.h | 5 ++-
arch/arm/mach-s3c64xx/include/mach/regs-clock.h | 5 ++
arch/arm/mach-s3c64xx/mach-smdk6410.c | 9 ++++
arch/arm/mach-s3c64xx/s3c6410.c | 1 +
arch/arm/mach-s3c64xx/setup-ide.c | 55 ++++++++++++++++++++++
arch/arm/plat-samsung/Kconfig | 5 ++
arch/arm/plat-samsung/Makefile | 1 +
arch/arm/plat-samsung/dev-ide.c | 52 +++++++++++++++++++++
arch/arm/plat-samsung/include/plat/ata.h | 38 +++++++++++++++
arch/arm/plat-samsung/include/plat/devs.h | 1 +
arch/arm/plat-samsung/include/plat/regs-ata.h | 56 +++++++++++++++++++++++
14 files changed, 241 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-s3c64xx/setup-ide.c
create mode 100644 arch/arm/plat-samsung/dev-ide.c
create mode 100644 arch/arm/plat-samsung/include/plat/ata.h
create mode 100644 arch/arm/plat-samsung/include/plat/regs-ata.h
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index f5a5972..c00401e 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -67,6 +67,11 @@ config S3C64XX_SETUP_SDHCI_GPIO
help
Common setup code for S3C64XX SDHCI GPIO configurations
+config S3C64XX_SETUP_IDE
+ bool
+ help
+ Common setup code for S3C64XX IDE.
+
# S36400 Macchine support
config MACH_SMDK6400
@@ -101,9 +106,11 @@ config MACH_SMDK6410
select S3C_DEV_USB_HSOTG
select S3C_DEV_WDT
select HAVE_S3C2410_WATCHDOG
+ select S3C_DEV_IDE
select S3C64XX_SETUP_SDHCI
select S3C64XX_SETUP_I2C1
select S3C64XX_SETUP_FB_24BPP
+ select S3C64XX_SETUP_IDE
help
Machine support for the Samsung SMDK6410
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 9d10069..0d52c35 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+obj-$(CONFIG_S3C64XX_SETUP_IDE) += setup-ide.o
# PM
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 7a4138b..9dac5c4 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -304,6 +304,12 @@ static struct clk init_clocks[] = {
.id = -1,
.parent = &clk_p,
.ctrlbit = S3C_CLKCON_PCLK_AC97,
+ }, {
+ .name = "cfcon",
+ .id = -1,
+ .parent = &clk_h,
+ .enable = s3c64xx_hclk_ctrl,
+ .ctrlbit = S3C_CLKCON_HCLK_IHOST,
}
};
diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
index e1eab3c..4b1ac79 100644
--- a/arch/arm/mach-s3c64xx/include/mach/map.h
+++ b/arch/arm/mach-s3c64xx/include/mach/map.h
@@ -86,6 +86,9 @@
#define S3C64XX_SZ_GPIO SZ_4K
#define S3C64XX_PA_SDRAM (0x50000000)
+
+#define S3C64XX_PA_CFCON (0x70300000)
+
#define S3C64XX_PA_VIC0 (0x71200000)
#define S3C64XX_PA_VIC1 (0x71300000)
@@ -118,7 +121,7 @@
#define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
#define S3C_PA_RTC S3C64XX_PA_RTC
#define S3C_PA_WDT S3C64XX_PA_WATCHDOG
-
+#define SAMSUNG_PA_CFCON S3C64XX_PA_CFCON
#define SAMSUNG_PA_ADC S3C64XX_PA_ADC
#endif /* __ASM_ARCH_6400_MAP_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
index 0114eb0..05332b9 100644
--- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
@@ -34,6 +34,7 @@
#define S3C_SCLK_GATE S3C_CLKREG(0x38)
#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
#define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
+#define S3C_MEM_SYS_CFG S3C_CLKREG(0x120)
/* CLKDIV0 */
#define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
@@ -154,4 +155,8 @@
#define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2)
#define S3C6400_CLKSRC_MFC (1 << 4)
+/* MEM_SYS_CFG */
+#define MEM_SYS_CFG_INDEP_CF 0x4000
+#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
+
#endif /* _PLAT_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index d9a0355..cc1bb0f 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -56,6 +56,7 @@
#include <mach/regs-gpio.h>
#include <mach/regs-sys.h>
#include <mach/regs-srom.h>
+#include <plat/ata.h>
#include <plat/iic.h>
#include <plat/fb.h>
#include <plat/gpio-cfg.h>
@@ -242,6 +243,11 @@ static struct platform_device smdk6410_b_pwr_5v = {
};
#endif
+static struct s3c_ide_platdata smdk6410_ide_pdata __initdata = {
+ .setup_gpio = s3c_ide_setup_gpio,
+ .cfg_mode = s3c_ide_cfg_mode,
+};
+
static struct map_desc smdk6410_iodesc[] = {};
static struct platform_device *smdk6410_devices[] __initdata = {
@@ -267,6 +273,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
&s3c_device_adc,
&s3c_device_ts,
&s3c_device_wdt,
+ &s3c_device_cfcon,
};
#ifdef CONFIG_REGULATOR
@@ -665,6 +672,8 @@ static void __init smdk6410_machine_init(void)
i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+ s3c_ide_set_platdata(&smdk6410_ide_pdata);
+
platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
}
diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
index 014401c..1d1dce4 100644
--- a/arch/arm/mach-s3c64xx/s3c6410.c
+++ b/arch/arm/mach-s3c64xx/s3c6410.c
@@ -58,6 +58,7 @@ void __init s3c6410_map_io(void)
s3c_device_nand.name = "s3c6400-nand";
s3c_onenand_setname("s3c6410-onenand");
s3c64xx_onenand1_setname("s3c6410-onenand");
+ s3c_device_cfcon.name = "s3c6400-pata";
}
void __init s3c6410_init_clocks(int xtal)
diff --git a/arch/arm/mach-s3c64xx/setup-ide.c b/arch/arm/mach-s3c64xx/setup-ide.c
new file mode 100644
index 0000000..0bf4e5e
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/setup-ide.c
@@ -0,0 +1,55 @@
+/* linux/arch/arm/mach-s3c64xx/setup-ide.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * S3C64XX setup information for IDE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <mach/gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-ata.h>
+
+void s3c_ide_setup_gpio(void)
+{
+ u32 reg;
+ u32 gpio = 0;
+
+ reg = __raw_readl(S3C_MEM_SYS_CFG) & (~0x3f);
+
+ /* Independent CF interface, CF chip select configuration */
+ __raw_writel(reg | MEM_SYS_CFG_INDEP_CF |
+ MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S3C_MEM_SYS_CFG);
+
+ s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4));
+
+ /* Set XhiDATA[15:0] pins as CF Data[15:0] */
+ for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++)
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5));
+
+ /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */
+ for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++)
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
+
+ /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */
+ s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1));
+ for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++)
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
+}
+
+void s3c_ide_cfg_mode(void __iomem *sfrbase)
+{
+ /* Select true-ide as the internal operating mode*/
+ writel(readl(sfrbase + S3C_CFATA_MUX) | S3C_CFATA_MUX_TRUEIDE,
+ sfrbase + S3C_CFATA_MUX);
+}
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 2753fb3..6ec97fe 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -175,6 +175,11 @@ config S3C_DEV_I2C2
help
Compile in platform device definitions for I2C channel 2
+config S3C_DEV_IDE
+ bool
+ help
+ Compile in platform device definitions for IDE
+
config S3C_DEV_FB
bool
help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index b1d82cc..252fc76 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o
obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o
obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o
+obj-$(CONFIG_S3C_DEV_IDE) += dev-ide.o
# DMA support
diff --git a/arch/arm/plat-samsung/dev-ide.c b/arch/arm/plat-samsung/dev-ide.c
new file mode 100644
index 0000000..c6b3292
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-ide.c
@@ -0,0 +1,52 @@
+/* linux/arch/arm/plat-samsung/dev-ide.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S3C CF-ATA device definition.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/map.h>
+#include <plat/ata.h>
+
+static struct resource s3c_cfcon_resource[] = {
+ [0] = {
+ .start = SAMSUNG_PA_CFCON,
+ .end = SAMSUNG_PA_CFCON + SZ_1M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_CFCON,
+ .end = IRQ_CFCON,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s3c_device_cfcon = {
+ .name = "s3c-pata",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s3c_cfcon_resource),
+ .resource = s3c_cfcon_resource,
+};
+
+void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
+{
+ struct s3c_ide_platdata *pd;
+
+ pd = (struct s3c_ide_platdata *)kmemdup(pdata,
+ sizeof(struct s3c_ide_platdata), GFP_KERNEL);
+ if (!pd) {
+ printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+ return;
+ }
+ s3c_device_cfcon.dev.platform_data = pd;
+}
diff --git a/arch/arm/plat-samsung/include/plat/ata.h b/arch/arm/plat-samsung/include/plat/ata.h
new file mode 100644
index 0000000..aea11dc
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/ata.h
@@ -0,0 +1,38 @@
+/* arch/arm/plat-samsung/include/plat/ata.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S3C - CF Controller platform_device info
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_ATA_H
+#define __ASM_PLAT_ATA_H __FILE__
+
+/**
+ * struct s3c_ide_platdata - S3C IDE driver platform data.
+ * @setup_gpio: Setup the external GPIO pins to the right state for data
+ * transfer in true-ide mode.
+ * @cfg_mode: Platform specific setup for configuring the CF controller
+ * in true-ide mode.
+ */
+struct s3c_ide_platdata {
+ void (*setup_gpio)(void);
+ void (*cfg_mode)(void __iomem *sfrbase);
+};
+
+/*
+ * s3c_ide_set_platdata() - Setup the platform specifc data for IDE driver.
+ * @pdata: Platform data for IDE driver.
+ */
+extern void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata);
+
+/* architecture-specific IDE configuration */
+extern void s3c_ide_setup_gpio(void);
+extern void s3c_ide_cfg_mode(void __iomem *sfrbase);
+
+#endif /*__ASM_PLAT_ATA_H */
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index e6144e4..e3fcddb 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -75,6 +75,7 @@ extern struct platform_device s5pc110_device_onenand;
extern struct platform_device s3c_device_usbgadget;
extern struct platform_device s3c_device_usb_hsotg;
+extern struct platform_device s3c_device_cfcon;
extern struct platform_device s5pv210_device_ac97;
extern struct platform_device s5pv210_device_pcm0;
diff --git a/arch/arm/plat-samsung/include/plat/regs-ata.h b/arch/arm/plat-samsung/include/plat/regs-ata.h
new file mode 100644
index 0000000..f73b267
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/regs-ata.h
@@ -0,0 +1,56 @@
+/* arch/arm/plat-samsung/include/plat/regs-ata.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S3C CF-ATA register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_REGS_ATA_H
+#define __ASM_PLAT_REGS_ATA_H __FILE__
+
+#define S3C_CFATA_REG(x) (x)
+
+#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
+
+#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
+#define S3C_ATA_STATUS S3C_CFATA_REG(0x4)
+#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
+#define S3C_ATA_SWRST S3C_CFATA_REG(0xc)
+#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
+#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
+#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
+
+#define S3C_ATA_MDMA_TIME S3C_CFATA_REG(0x28)
+#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
+#define S3C_ATA_UDMA_TIME S3C_CFATA_REG(0x30)
+#define S3C_ATA_XFR_NUM S3C_CFATA_REG(0x34)
+#define S3C_ATA_XFR_CNT S3C_CFATA_REG(0x38)
+#define S3C_ATA_TBUF_START S3C_CFATA_REG(0x3c)
+#define S3C_ATA_TBUF_SIZE S3C_CFATA_REG(0x40)
+#define S3C_ATA_SBUF_START S3C_CFATA_REG(0x44)
+#define S3C_ATA_SBUF_SIZE S3C_CFATA_REG(0x48)
+#define S3C_ATA_CADR_TBUF S3C_CFATA_REG(0x4c)
+#define S3C_ATA_CADR_SBUF S3C_CFATA_REG(0x50)
+#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
+#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
+#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
+#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
+#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
+#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
+#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
+#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
+#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
+#define S3C_ATA_PIO_READY S3C_CFATA_REG(0x78)
+#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
+
+#define S3C_CFATA_MUX_TRUEIDE 0x01
+
+#define S3C_ATA_CFG_SWAP 0x40
+#define S3C_ATA_CFG_IORDYEN 0x02
+
+#endif /* __ASM_PLAT_REGS_ATA_H */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410
2010-05-27 8:22 ` [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410 Kukjin Kim
@ 2010-05-27 8:52 ` Ben Dooks
2010-05-28 5:44 ` Marek Szyprowski
2010-06-02 2:31 ` Kukjin Kim
2010-05-27 19:45 ` Russell King - ARM Linux
1 sibling, 2 replies; 24+ messages in thread
From: Ben Dooks @ 2010-05-27 8:52 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 05:22:01PM +0900, Kukjin Kim wrote:
> From: Abhilash Kesavan <a.kesavan@samsung.com>
>
> Following is added for the CF-ATA driver:
> - Platform data strucure definition and instantiation
> - Platform device definition and enabling code
> - Platform-specific gpio setup code
> - CF controller register definitions
>
> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> arch/arm/mach-s3c64xx/Kconfig | 7 +++
> arch/arm/mach-s3c64xx/Makefile | 1 +
> arch/arm/mach-s3c64xx/clock.c | 6 +++
> arch/arm/mach-s3c64xx/include/mach/map.h | 5 ++-
> arch/arm/mach-s3c64xx/include/mach/regs-clock.h | 5 ++
> arch/arm/mach-s3c64xx/mach-smdk6410.c | 9 ++++
> arch/arm/mach-s3c64xx/s3c6410.c | 1 +
> arch/arm/mach-s3c64xx/setup-ide.c | 55 ++++++++++++++++++++++
> arch/arm/plat-samsung/Kconfig | 5 ++
> arch/arm/plat-samsung/Makefile | 1 +
> arch/arm/plat-samsung/dev-ide.c | 52 +++++++++++++++++++++
> arch/arm/plat-samsung/include/plat/ata.h | 38 +++++++++++++++
> arch/arm/plat-samsung/include/plat/devs.h | 1 +
> arch/arm/plat-samsung/include/plat/regs-ata.h | 56 +++++++++++++++++++++++
it would have been useful to keep the plat-samsung changes
seperate.
> 14 files changed, 241 insertions(+), 1 deletions(-)
> create mode 100644 arch/arm/mach-s3c64xx/setup-ide.c
> create mode 100644 arch/arm/plat-samsung/dev-ide.c
> create mode 100644 arch/arm/plat-samsung/include/plat/ata.h
> create mode 100644 arch/arm/plat-samsung/include/plat/regs-ata.h
>
> diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
> index f5a5972..c00401e 100644
> --- a/arch/arm/mach-s3c64xx/Kconfig
> +++ b/arch/arm/mach-s3c64xx/Kconfig
> @@ -67,6 +67,11 @@ config S3C64XX_SETUP_SDHCI_GPIO
> help
> Common setup code for S3C64XX SDHCI GPIO configurations
>
> +config S3C64XX_SETUP_IDE
> + bool
> + help
> + Common setup code for S3C64XX IDE.
> +
> # S36400 Macchine support
>
> config MACH_SMDK6400
> @@ -101,9 +106,11 @@ config MACH_SMDK6410
> select S3C_DEV_USB_HSOTG
> select S3C_DEV_WDT
> select HAVE_S3C2410_WATCHDOG
> + select S3C_DEV_IDE
> select S3C64XX_SETUP_SDHCI
> select S3C64XX_SETUP_I2C1
> select S3C64XX_SETUP_FB_24BPP
> + select S3C64XX_SETUP_IDE
> help
> Machine support for the Samsung SMDK6410
>
> diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
> index 9d10069..0d52c35 100644
> --- a/arch/arm/mach-s3c64xx/Makefile
> +++ b/arch/arm/mach-s3c64xx/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
> obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
> obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
> obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
> +obj-$(CONFIG_S3C64XX_SETUP_IDE) += setup-ide.o
>
> # PM
>
> diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
> index 7a4138b..9dac5c4 100644
> --- a/arch/arm/mach-s3c64xx/clock.c
> +++ b/arch/arm/mach-s3c64xx/clock.c
> @@ -304,6 +304,12 @@ static struct clk init_clocks[] = {
> .id = -1,
> .parent = &clk_p,
> .ctrlbit = S3C_CLKCON_PCLK_AC97,
> + }, {
> + .name = "cfcon",
> + .id = -1,
> + .parent = &clk_h,
> + .enable = s3c64xx_hclk_ctrl,
> + .ctrlbit = S3C_CLKCON_HCLK_IHOST,
> }
> };
>
> diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h
> index e1eab3c..4b1ac79 100644
> --- a/arch/arm/mach-s3c64xx/include/mach/map.h
> +++ b/arch/arm/mach-s3c64xx/include/mach/map.h
> @@ -86,6 +86,9 @@
> #define S3C64XX_SZ_GPIO SZ_4K
>
> #define S3C64XX_PA_SDRAM (0x50000000)
> +
> +#define S3C64XX_PA_CFCON (0x70300000)
> +
> #define S3C64XX_PA_VIC0 (0x71200000)
> #define S3C64XX_PA_VIC1 (0x71300000)
>
> @@ -118,7 +121,7 @@
> #define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
> #define S3C_PA_RTC S3C64XX_PA_RTC
> #define S3C_PA_WDT S3C64XX_PA_WATCHDOG
> -
> +#define SAMSUNG_PA_CFCON S3C64XX_PA_CFCON
> #define SAMSUNG_PA_ADC S3C64XX_PA_ADC
>
> #endif /* __ASM_ARCH_6400_MAP_H */
> diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> index 0114eb0..05332b9 100644
> --- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> +++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> @@ -34,6 +34,7 @@
> #define S3C_SCLK_GATE S3C_CLKREG(0x38)
> #define S3C_MEM0_GATE S3C_CLKREG(0x3C)
> #define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
> +#define S3C_MEM_SYS_CFG S3C_CLKREG(0x120)
>
> /* CLKDIV0 */
> #define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
> @@ -154,4 +155,8 @@
> #define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2)
> #define S3C6400_CLKSRC_MFC (1 << 4)
>
> +/* MEM_SYS_CFG */
> +#define MEM_SYS_CFG_INDEP_CF 0x4000
> +#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
> +
> #endif /* _PLAT_REGS_CLOCK_H */
> diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
> index d9a0355..cc1bb0f 100644
> --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
> +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
> @@ -56,6 +56,7 @@
> #include <mach/regs-gpio.h>
> #include <mach/regs-sys.h>
> #include <mach/regs-srom.h>
> +#include <plat/ata.h>
> #include <plat/iic.h>
> #include <plat/fb.h>
> #include <plat/gpio-cfg.h>
> @@ -242,6 +243,11 @@ static struct platform_device smdk6410_b_pwr_5v = {
> };
> #endif
>
> +static struct s3c_ide_platdata smdk6410_ide_pdata __initdata = {
> + .setup_gpio = s3c_ide_setup_gpio,
> + .cfg_mode = s3c_ide_cfg_mode,
These should have been called s3c64xx_ide...
I'll have a think about what we should be doing with this, it might
be wroth passing this via the archdata and leaving the platform data
for the board. If these configs are generally going to be per SoC
then i'd prefer to see this in the archdata and once per SoC.
> +};
> +
> static struct map_desc smdk6410_iodesc[] = {};
>
> static struct platform_device *smdk6410_devices[] __initdata = {
> @@ -267,6 +273,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
> &s3c_device_adc,
> &s3c_device_ts,
> &s3c_device_wdt,
> + &s3c_device_cfcon,
> };
>
> #ifdef CONFIG_REGULATOR
> @@ -665,6 +672,8 @@ static void __init smdk6410_machine_init(void)
> i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
> i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
>
> + s3c_ide_set_platdata(&smdk6410_ide_pdata);
> +
> platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
> }
>
> diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c
> index 014401c..1d1dce4 100644
> --- a/arch/arm/mach-s3c64xx/s3c6410.c
> +++ b/arch/arm/mach-s3c64xx/s3c6410.c
> @@ -58,6 +58,7 @@ void __init s3c6410_map_io(void)
> s3c_device_nand.name = "s3c6400-nand";
> s3c_onenand_setname("s3c6410-onenand");
> s3c64xx_onenand1_setname("s3c6410-onenand");
> + s3c_device_cfcon.name = "s3c6400-pata";
> }
let's get this sorted out and use one method. see Kyungmin Park's prev.
comments on the subject.
> void __init s3c6410_init_clocks(int xtal)
> diff --git a/arch/arm/mach-s3c64xx/setup-ide.c b/arch/arm/mach-s3c64xx/setup-ide.c
> new file mode 100644
> index 0000000..0bf4e5e
> --- /dev/null
> +++ b/arch/arm/mach-s3c64xx/setup-ide.c
> @@ -0,0 +1,55 @@
> +/* linux/arch/arm/mach-s3c64xx/setup-ide.c
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * S3C64XX setup information for IDE
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/io.h>
> +
> +#include <mach/map.h>
> +#include <mach/gpio.h>
> +#include <mach/regs-clock.h>
> +#include <plat/gpio-cfg.h>
> +#include <plat/regs-ata.h>
> +
> +void s3c_ide_setup_gpio(void)
> +{
> + u32 reg;
> + u32 gpio = 0;
> +
> + reg = __raw_readl(S3C_MEM_SYS_CFG) & (~0x3f);
> +
> + /* Independent CF interface, CF chip select configuration */
> + __raw_writel(reg | MEM_SYS_CFG_INDEP_CF |
> + MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S3C_MEM_SYS_CFG);
> +
> + s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4));
> +
> + /* Set XhiDATA[15:0] pins as CF Data[15:0] */
> + for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++)
> + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5));
> +
> + /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */
> + for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++)
> + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
> +
> + /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */
> + s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1));
> + for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++)
> + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
i'll update this to the cfgrange when merging the cfgrange code.
> +}
> +
> +void s3c_ide_cfg_mode(void __iomem *sfrbase)
> +{
> + /* Select true-ide as the internal operating mode*/
> + writel(readl(sfrbase + S3C_CFATA_MUX) | S3C_CFATA_MUX_TRUEIDE,
> + sfrbase + S3C_CFATA_MUX);
> +}
maybe we just put this in the driver and select on type.
> diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
> index 2753fb3..6ec97fe 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -175,6 +175,11 @@ config S3C_DEV_I2C2
> help
> Compile in platform device definitions for I2C channel 2
>
> +config S3C_DEV_IDE
> + bool
> + help
> + Compile in platform device definitions for IDE
> +
> config S3C_DEV_FB
> bool
> help
> diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
> index b1d82cc..252fc76 100644
> --- a/arch/arm/plat-samsung/Makefile
> +++ b/arch/arm/plat-samsung/Makefile
> @@ -48,6 +48,7 @@ obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o
>
> obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o
> obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o
> +obj-$(CONFIG_S3C_DEV_IDE) += dev-ide.o
>
> # DMA support
>
> diff --git a/arch/arm/plat-samsung/dev-ide.c b/arch/arm/plat-samsung/dev-ide.c
> new file mode 100644
> index 0000000..c6b3292
> --- /dev/null
> +++ b/arch/arm/plat-samsung/dev-ide.c
> @@ -0,0 +1,52 @@
> +/* linux/arch/arm/plat-samsung/dev-ide.c
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * S3C CF-ATA device definition.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/interrupt.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +#include <mach/map.h>
> +#include <plat/ata.h>
do we need linux/io.h in here?
soem spacing inebtwee nthe include groups would be nice too,.
> +static struct resource s3c_cfcon_resource[] = {
> + [0] = {
> + .start = SAMSUNG_PA_CFCON,
> + .end = SAMSUNG_PA_CFCON + SZ_1M - 1,
> + .flags = IORESOURCE_MEM,
do we really need to map SZ_1M?
> + },
> + [1] = {
> + .start = IRQ_CFCON,
> + .end = IRQ_CFCON,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +struct platform_device s3c_device_cfcon = {
> + .name = "s3c-pata",
if the name is going to change, let's simply not bother
setting one here.
> + .id = 0,
> + .num_resources = ARRAY_SIZE(s3c_cfcon_resource),
> + .resource = s3c_cfcon_resource,
> +};
> +void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
> +{
> + struct s3c_ide_platdata *pd;
> +
> + pd = (struct s3c_ide_platdata *)kmemdup(pdata,
^^^^^ not needed.
> + sizeof(struct s3c_ide_platdata), GFP_KERNEL);
> + if (!pd) {
> + printk(KERN_ERR "%s: no memory for platform data\n", __func__);
> + return;
> + }
> + s3c_device_cfcon.dev.platform_data = pd;
> +}
> diff --git a/arch/arm/plat-samsung/include/plat/ata.h b/arch/arm/plat-samsung/include/plat/ata.h
> new file mode 100644
> index 0000000..aea11dc
> --- /dev/null
> +++ b/arch/arm/plat-samsung/include/plat/ata.h
> @@ -0,0 +1,38 @@
> +/* arch/arm/plat-samsung/include/plat/ata.h
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * S3C - CF Controller platform_device info
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#ifndef __ASM_PLAT_ATA_H
> +#define __ASM_PLAT_ATA_H __FILE__
> +
> +/**
> + * struct s3c_ide_platdata - S3C IDE driver platform data.
> + * @setup_gpio: Setup the external GPIO pins to the right state for data
> + * transfer in true-ide mode.
> + * @cfg_mode: Platform specific setup for configuring the CF controller
> + * in true-ide mode.
> + */
> +struct s3c_ide_platdata {
> + void (*setup_gpio)(void);
> + void (*cfg_mode)(void __iomem *sfrbase);
> +};
> +
> +/*
> + * s3c_ide_set_platdata() - Setup the platform specifc data for IDE driver.
> + * @pdata: Platform data for IDE driver.
> + */
> +extern void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata);
> +
> +/* architecture-specific IDE configuration */
> +extern void s3c_ide_setup_gpio(void);
> +extern void s3c_ide_cfg_mode(void __iomem *sfrbase);
> +
> +#endif /*__ASM_PLAT_ATA_H */
> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
> index e6144e4..e3fcddb 100644
> --- a/arch/arm/plat-samsung/include/plat/devs.h
> +++ b/arch/arm/plat-samsung/include/plat/devs.h
> @@ -75,6 +75,7 @@ extern struct platform_device s5pc110_device_onenand;
>
> extern struct platform_device s3c_device_usbgadget;
> extern struct platform_device s3c_device_usb_hsotg;
> +extern struct platform_device s3c_device_cfcon;
>
> extern struct platform_device s5pv210_device_ac97;
> extern struct platform_device s5pv210_device_pcm0;
> diff --git a/arch/arm/plat-samsung/include/plat/regs-ata.h b/arch/arm/plat-samsung/include/plat/regs-ata.h
> new file mode 100644
> index 0000000..f73b267
> --- /dev/null
> +++ b/arch/arm/plat-samsung/include/plat/regs-ata.h
> @@ -0,0 +1,56 @@
> +/* arch/arm/plat-samsung/include/plat/regs-ata.h
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * S3C CF-ATA register definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> +*/
> +
> +#ifndef __ASM_PLAT_REGS_ATA_H
> +#define __ASM_PLAT_REGS_ATA_H __FILE__
> +
> +#define S3C_CFATA_REG(x) (x)
> +
> +#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
> +
> +#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
> +#define S3C_ATA_STATUS S3C_CFATA_REG(0x4)
> +#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
> +#define S3C_ATA_SWRST S3C_CFATA_REG(0xc)
> +#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
> +#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
> +#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
> +
> +#define S3C_ATA_MDMA_TIME S3C_CFATA_REG(0x28)
> +#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
> +#define S3C_ATA_UDMA_TIME S3C_CFATA_REG(0x30)
> +#define S3C_ATA_XFR_NUM S3C_CFATA_REG(0x34)
> +#define S3C_ATA_XFR_CNT S3C_CFATA_REG(0x38)
> +#define S3C_ATA_TBUF_START S3C_CFATA_REG(0x3c)
> +#define S3C_ATA_TBUF_SIZE S3C_CFATA_REG(0x40)
> +#define S3C_ATA_SBUF_START S3C_CFATA_REG(0x44)
> +#define S3C_ATA_SBUF_SIZE S3C_CFATA_REG(0x48)
> +#define S3C_ATA_CADR_TBUF S3C_CFATA_REG(0x4c)
> +#define S3C_ATA_CADR_SBUF S3C_CFATA_REG(0x50)
> +#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
> +#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
> +#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
> +#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
> +#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
> +#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
> +#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
> +#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
> +#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
> +#define S3C_ATA_PIO_READY S3C_CFATA_REG(0x78)
> +#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
> +
> +#define S3C_CFATA_MUX_TRUEIDE 0x01
> +
> +#define S3C_ATA_CFG_SWAP 0x40
> +#define S3C_ATA_CFG_IORDYEN 0x02
> +
> +#endif /* __ASM_PLAT_REGS_ATA_H */
> --
> 1.6.2.5
>
--
--
Ben
Q: What's a light-year?
A: One-third less calories than a regular year.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410
2010-05-27 8:52 ` Ben Dooks
@ 2010-05-28 5:44 ` Marek Szyprowski
2010-06-02 2:31 ` Kukjin Kim
1 sibling, 0 replies; 24+ messages in thread
From: Marek Szyprowski @ 2010-05-28 5:44 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Thursday, May 27, 2010 10:53 AM Ben Dooks wrote:
> On Thu, May 27, 2010 at 05:22:01PM +0900, Kukjin Kim wrote:
> > From: Abhilash Kesavan <a.kesavan@samsung.com>
> >
> > Following is added for the CF-ATA driver:
> > - Platform data strucure definition and instantiation
> > - Platform device definition and enabling code
> > - Platform-specific gpio setup code
> > - CF controller register definitions
> >
> > Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> > Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> > arch/arm/mach-s3c64xx/Kconfig | 7 +++
> > arch/arm/mach-s3c64xx/Makefile | 1 +
> > arch/arm/mach-s3c64xx/clock.c | 6 +++
> > arch/arm/mach-s3c64xx/include/mach/map.h | 5 ++-
> > arch/arm/mach-s3c64xx/include/mach/regs-clock.h | 5 ++
> > arch/arm/mach-s3c64xx/mach-smdk6410.c | 9 ++++
> > arch/arm/mach-s3c64xx/s3c6410.c | 1 +
> > arch/arm/mach-s3c64xx/setup-ide.c | 55
> ++++++++++++++++++++++
> > arch/arm/plat-samsung/Kconfig | 5 ++
> > arch/arm/plat-samsung/Makefile | 1 +
> > arch/arm/plat-samsung/dev-ide.c | 52
> +++++++++++++++++++++
> > arch/arm/plat-samsung/include/plat/ata.h | 38 +++++++++++++++
> > arch/arm/plat-samsung/include/plat/devs.h | 1 +
> > arch/arm/plat-samsung/include/plat/regs-ata.h | 56
> +++++++++++++++++++++++
>
> it would have been useful to keep the plat-samsung changes
> seperate.
>
> > 14 files changed, 241 insertions(+), 1 deletions(-)
> > create mode 100644 arch/arm/mach-s3c64xx/setup-ide.c
> > create mode 100644 arch/arm/plat-samsung/dev-ide.c
> > create mode 100644 arch/arm/plat-samsung/include/plat/ata.h
> > create mode 100644 arch/arm/plat-samsung/include/plat/regs-ata.h
> >
> > diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-
> s3c64xx/Kconfig
> > index f5a5972..c00401e 100644
> > --- a/arch/arm/mach-s3c64xx/Kconfig
> > +++ b/arch/arm/mach-s3c64xx/Kconfig
> > @@ -67,6 +67,11 @@ config S3C64XX_SETUP_SDHCI_GPIO
> > help
> > Common setup code for S3C64XX SDHCI GPIO configurations
> >
> > +config S3C64XX_SETUP_IDE
> > + bool
> > + help
> > + Common setup code for S3C64XX IDE.
> > +
> > # S36400 Macchine support
> >
> > config MACH_SMDK6400
> > @@ -101,9 +106,11 @@ config MACH_SMDK6410
> > select S3C_DEV_USB_HSOTG
> > select S3C_DEV_WDT
> > select HAVE_S3C2410_WATCHDOG
> > + select S3C_DEV_IDE
> > select S3C64XX_SETUP_SDHCI
> > select S3C64XX_SETUP_I2C1
> > select S3C64XX_SETUP_FB_24BPP
> > + select S3C64XX_SETUP_IDE
> > help
> > Machine support for the Samsung SMDK6410
> >
> > diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-
> s3c64xx/Makefile
> > index 9d10069..0d52c35 100644
> > --- a/arch/arm/mach-s3c64xx/Makefile
> > +++ b/arch/arm/mach-s3c64xx/Makefile
> > @@ -38,6 +38,7 @@ obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
> > obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
> > obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
> > obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
> > +obj-$(CONFIG_S3C64XX_SETUP_IDE) += setup-ide.o
> >
> > # PM
> >
> > diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-
> s3c64xx/clock.c
> > index 7a4138b..9dac5c4 100644
> > --- a/arch/arm/mach-s3c64xx/clock.c
> > +++ b/arch/arm/mach-s3c64xx/clock.c
> > @@ -304,6 +304,12 @@ static struct clk init_clocks[] = {
> > .id = -1,
> > .parent = &clk_p,
> > .ctrlbit = S3C_CLKCON_PCLK_AC97,
> > + }, {
> > + .name = "cfcon",
> > + .id = -1,
> > + .parent = &clk_h,
> > + .enable = s3c64xx_hclk_ctrl,
> > + .ctrlbit = S3C_CLKCON_HCLK_IHOST,
> > }
> > };
> >
> > diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-
> s3c64xx/include/mach/map.h
> > index e1eab3c..4b1ac79 100644
> > --- a/arch/arm/mach-s3c64xx/include/mach/map.h
> > +++ b/arch/arm/mach-s3c64xx/include/mach/map.h
> > @@ -86,6 +86,9 @@
> > #define S3C64XX_SZ_GPIO SZ_4K
> >
> > #define S3C64XX_PA_SDRAM (0x50000000)
> > +
> > +#define S3C64XX_PA_CFCON (0x70300000)
> > +
> > #define S3C64XX_PA_VIC0 (0x71200000)
> > #define S3C64XX_PA_VIC1 (0x71300000)
> >
> > @@ -118,7 +121,7 @@
> > #define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
> > #define S3C_PA_RTC S3C64XX_PA_RTC
> > #define S3C_PA_WDT S3C64XX_PA_WATCHDOG
> > -
> > +#define SAMSUNG_PA_CFCON S3C64XX_PA_CFCON
> > #define SAMSUNG_PA_ADC S3C64XX_PA_ADC
> >
> > #endif /* __ASM_ARCH_6400_MAP_H */
> > diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> > index 0114eb0..05332b9 100644
> > --- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> > +++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> > @@ -34,6 +34,7 @@
> > #define S3C_SCLK_GATE S3C_CLKREG(0x38)
> > #define S3C_MEM0_GATE S3C_CLKREG(0x3C)
> > #define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
> > +#define S3C_MEM_SYS_CFG S3C_CLKREG(0x120)
> >
> > /* CLKDIV0 */
> > #define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
> > @@ -154,4 +155,8 @@
> > #define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2)
> > #define S3C6400_CLKSRC_MFC (1 << 4)
> >
> > +/* MEM_SYS_CFG */
> > +#define MEM_SYS_CFG_INDEP_CF 0x4000
> > +#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
> > +
> > #endif /* _PLAT_REGS_CLOCK_H */
> > diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-
> s3c64xx/mach-smdk6410.c
> > index d9a0355..cc1bb0f 100644
> > --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
> > +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
> > @@ -56,6 +56,7 @@
> > #include <mach/regs-gpio.h>
> > #include <mach/regs-sys.h>
> > #include <mach/regs-srom.h>
> > +#include <plat/ata.h>
> > #include <plat/iic.h>
> > #include <plat/fb.h>
> > #include <plat/gpio-cfg.h>
> > @@ -242,6 +243,11 @@ static struct platform_device smdk6410_b_pwr_5v = {
> > };
> > #endif
> >
> > +static struct s3c_ide_platdata smdk6410_ide_pdata __initdata = {
> > + .setup_gpio = s3c_ide_setup_gpio,
> > + .cfg_mode = s3c_ide_cfg_mode,
>
>
> These should have been called s3c64xx_ide...
>
> I'll have a think about what we should be doing with this, it might
> be wroth passing this via the archdata and leaving the platform data
> for the board. If these configs are generally going to be per SoC
> then i'd prefer to see this in the archdata and once per SoC.
>
> > +};
> > +
> > static struct map_desc smdk6410_iodesc[] = {};
> >
> > static struct platform_device *smdk6410_devices[] __initdata = {
> > @@ -267,6 +273,7 @@ static struct platform_device *smdk6410_devices[]
> __initdata = {
> > &s3c_device_adc,
> > &s3c_device_ts,
> > &s3c_device_wdt,
> > + &s3c_device_cfcon,
> > };
> >
> > #ifdef CONFIG_REGULATOR
> > @@ -665,6 +672,8 @@ static void __init smdk6410_machine_init(void)
> > i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
> > i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
> >
> > + s3c_ide_set_platdata(&smdk6410_ide_pdata);
> > +
> > platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
> > }
> >
> > diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-
> s3c64xx/s3c6410.c
> > index 014401c..1d1dce4 100644
> > --- a/arch/arm/mach-s3c64xx/s3c6410.c
> > +++ b/arch/arm/mach-s3c64xx/s3c6410.c
> > @@ -58,6 +58,7 @@ void __init s3c6410_map_io(void)
> > s3c_device_nand.name = "s3c6400-nand";
> > s3c_onenand_setname("s3c6410-onenand");
> > s3c64xx_onenand1_setname("s3c6410-onenand");
> > + s3c_device_cfcon.name = "s3c6400-pata";
> > }
>
> let's get this sorted out and use one method. see Kyungmin Park's prev.
> comments on the subject.
There are boards that doesn't have cf/ide connector at all. It would be good
to have s3c-dev not compiled in for some custom kernels. It would be better
to hide the driver name change behind a function/macro like it is done for
the one-nand driver.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410
2010-05-27 8:52 ` Ben Dooks
2010-05-28 5:44 ` Marek Szyprowski
@ 2010-06-02 2:31 ` Kukjin Kim
1 sibling, 0 replies; 24+ messages in thread
From: Kukjin Kim @ 2010-06-02 2:31 UTC (permalink / raw)
To: linux-arm-kernel
Ben Dooks wrote:
>
> On Thu, May 27, 2010 at 05:22:01PM +0900, Kukjin Kim wrote:
> > From: Abhilash Kesavan <a.kesavan@samsung.com>
> >
> > Following is added for the CF-ATA driver:
> > - Platform data strucure definition and instantiation
> > - Platform device definition and enabling code
> > - Platform-specific gpio setup code
> > - CF controller register definitions
> >
> > Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> > Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> > arch/arm/mach-s3c64xx/Kconfig | 7 +++
> > arch/arm/mach-s3c64xx/Makefile | 1 +
> > arch/arm/mach-s3c64xx/clock.c | 6 +++
> > arch/arm/mach-s3c64xx/include/mach/map.h | 5 ++-
> > arch/arm/mach-s3c64xx/include/mach/regs-clock.h | 5 ++
> > arch/arm/mach-s3c64xx/mach-smdk6410.c | 9 ++++
> > arch/arm/mach-s3c64xx/s3c6410.c | 1 +
> > arch/arm/mach-s3c64xx/setup-ide.c | 55
> ++++++++++++++++++++++
> > arch/arm/plat-samsung/Kconfig | 5 ++
> > arch/arm/plat-samsung/Makefile | 1 +
> > arch/arm/plat-samsung/dev-ide.c | 52
> +++++++++++++++++++++
> > arch/arm/plat-samsung/include/plat/ata.h | 38 +++++++++++++++
> > arch/arm/plat-samsung/include/plat/devs.h | 1 +
> > arch/arm/plat-samsung/include/plat/regs-ata.h | 56
> +++++++++++++++++++++++
>
> it would have been useful to keep the plat-samsung changes
> seperate.
>
Ok..will separate the plat-samsung and machine code into different patches.
> > 14 files changed, 241 insertions(+), 1 deletions(-)
> > create mode 100644 arch/arm/mach-s3c64xx/setup-ide.c
> > create mode 100644 arch/arm/plat-samsung/dev-ide.c
> > create mode 100644 arch/arm/plat-samsung/include/plat/ata.h
> > create mode 100644 arch/arm/plat-samsung/include/plat/regs-ata.h
> >
> > diff --git a/arch/arm/mach-s3c64xx/Kconfig
b/arch/arm/mach-s3c64xx/Kconfig
> > index f5a5972..c00401e 100644
> > --- a/arch/arm/mach-s3c64xx/Kconfig
> > +++ b/arch/arm/mach-s3c64xx/Kconfig
> > @@ -67,6 +67,11 @@ config S3C64XX_SETUP_SDHCI_GPIO
> > help
> > Common setup code for S3C64XX SDHCI GPIO configurations
> >
> > +config S3C64XX_SETUP_IDE
> > + bool
> > + help
> > + Common setup code for S3C64XX IDE.
> > +
> > # S36400 Macchine support
> >
> > config MACH_SMDK6400
> > @@ -101,9 +106,11 @@ config MACH_SMDK6410
> > select S3C_DEV_USB_HSOTG
> > select S3C_DEV_WDT
> > select HAVE_S3C2410_WATCHDOG
> > + select S3C_DEV_IDE
> > select S3C64XX_SETUP_SDHCI
> > select S3C64XX_SETUP_I2C1
> > select S3C64XX_SETUP_FB_24BPP
> > + select S3C64XX_SETUP_IDE
> > help
> > Machine support for the Samsung SMDK6410
> >
> > diff --git a/arch/arm/mach-s3c64xx/Makefile
b/arch/arm/mach-s3c64xx/Makefile
> > index 9d10069..0d52c35 100644
> > --- a/arch/arm/mach-s3c64xx/Makefile
> > +++ b/arch/arm/mach-s3c64xx/Makefile
> > @@ -38,6 +38,7 @@ obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
> > obj-$(CONFIG_S3C64XX_SETUP_SDHCI) += setup-sdhci.o
> > obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
> > obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
> > +obj-$(CONFIG_S3C64XX_SETUP_IDE) += setup-ide.o
> >
> > # PM
> >
> > diff --git a/arch/arm/mach-s3c64xx/clock.c
b/arch/arm/mach-s3c64xx/clock.c
> > index 7a4138b..9dac5c4 100644
> > --- a/arch/arm/mach-s3c64xx/clock.c
> > +++ b/arch/arm/mach-s3c64xx/clock.c
> > @@ -304,6 +304,12 @@ static struct clk init_clocks[] = {
> > .id = -1,
> > .parent = &clk_p,
> > .ctrlbit = S3C_CLKCON_PCLK_AC97,
> > + }, {
> > + .name = "cfcon",
> > + .id = -1,
> > + .parent = &clk_h,
> > + .enable = s3c64xx_hclk_ctrl,
> > + .ctrlbit = S3C_CLKCON_HCLK_IHOST,
> > }
> > };
> >
> > diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-
> s3c64xx/include/mach/map.h
> > index e1eab3c..4b1ac79 100644
> > --- a/arch/arm/mach-s3c64xx/include/mach/map.h
> > +++ b/arch/arm/mach-s3c64xx/include/mach/map.h
> > @@ -86,6 +86,9 @@
> > #define S3C64XX_SZ_GPIO SZ_4K
> >
> > #define S3C64XX_PA_SDRAM (0x50000000)
> > +
> > +#define S3C64XX_PA_CFCON (0x70300000)
> > +
> > #define S3C64XX_PA_VIC0 (0x71200000)
> > #define S3C64XX_PA_VIC1 (0x71300000)
> >
> > @@ -118,7 +121,7 @@
> > #define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY
> > #define S3C_PA_RTC S3C64XX_PA_RTC
> > #define S3C_PA_WDT S3C64XX_PA_WATCHDOG
> > -
> > +#define SAMSUNG_PA_CFCON S3C64XX_PA_CFCON
> > #define SAMSUNG_PA_ADC S3C64XX_PA_ADC
> >
> > #endif /* __ASM_ARCH_6400_MAP_H */
> > diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
b/arch/arm/mach-
> s3c64xx/include/mach/regs-clock.h
> > index 0114eb0..05332b9 100644
> > --- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> > +++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
> > @@ -34,6 +34,7 @@
> > #define S3C_SCLK_GATE S3C_CLKREG(0x38)
> > #define S3C_MEM0_GATE S3C_CLKREG(0x3C)
> > #define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C)
> > +#define S3C_MEM_SYS_CFG S3C_CLKREG(0x120)
> >
> > /* CLKDIV0 */
> > #define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12)
> > @@ -154,4 +155,8 @@
> > #define S3C6400_CLKSRC_EPLL_MOUT_SHIFT (2)
> > #define S3C6400_CLKSRC_MFC (1 << 4)
> >
> > +/* MEM_SYS_CFG */
> > +#define MEM_SYS_CFG_INDEP_CF 0x4000
> > +#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
> > +
> > #endif /* _PLAT_REGS_CLOCK_H */
> > diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-
> s3c64xx/mach-smdk6410.c
> > index d9a0355..cc1bb0f 100644
> > --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
> > +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
> > @@ -56,6 +56,7 @@
> > #include <mach/regs-gpio.h>
> > #include <mach/regs-sys.h>
> > #include <mach/regs-srom.h>
> > +#include <plat/ata.h>
> > #include <plat/iic.h>
> > #include <plat/fb.h>
> > #include <plat/gpio-cfg.h>
> > @@ -242,6 +243,11 @@ static struct platform_device smdk6410_b_pwr_5v = {
> > };
> > #endif
> >
> > +static struct s3c_ide_platdata smdk6410_ide_pdata __initdata = {
> > + .setup_gpio = s3c_ide_setup_gpio,
> > + .cfg_mode = s3c_ide_cfg_mode,
>
>
> These should have been called s3c64xx_ide...
>
> I'll have a think about what we should be doing with this, it might
> be wroth passing this via the archdata and leaving the platform data
> for the board. If these configs are generally going to be per SoC
> then i'd prefer to see this in the archdata and once per SoC.
>
Will change it to per SoC.
> > +};
> > +
> > static struct map_desc smdk6410_iodesc[] = {};
> >
> > static struct platform_device *smdk6410_devices[] __initdata = {
> > @@ -267,6 +273,7 @@ static struct platform_device *smdk6410_devices[]
> __initdata = {
> > &s3c_device_adc,
> > &s3c_device_ts,
> > &s3c_device_wdt,
> > + &s3c_device_cfcon,
> > };
> >
> > #ifdef CONFIG_REGULATOR
> > @@ -665,6 +672,8 @@ static void __init smdk6410_machine_init(void)
> > i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
> > i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
> >
> > + s3c_ide_set_platdata(&smdk6410_ide_pdata);
> > +
> > platform_add_devices(smdk6410_devices,
> ARRAY_SIZE(smdk6410_devices));
> > }
> >
> > diff --git a/arch/arm/mach-s3c64xx/s3c6410.c
b/arch/arm/mach-s3c64xx/s3c6410.c
> > index 014401c..1d1dce4 100644
> > --- a/arch/arm/mach-s3c64xx/s3c6410.c
> > +++ b/arch/arm/mach-s3c64xx/s3c6410.c
> > @@ -58,6 +58,7 @@ void __init s3c6410_map_io(void)
> > s3c_device_nand.name = "s3c6400-nand";
> > s3c_onenand_setname("s3c6410-onenand");
> > s3c64xx_onenand1_setname("s3c6410-onenand");
> > + s3c_device_cfcon.name = "s3c6400-pata";
> > }
>
> let's get this sorted out and use one method. see Kyungmin Park's prev.
> comments on the subject.
>
Will create a new file ata-core.h on the lines of iic-core.h/onenand-core.h
> > void __init s3c6410_init_clocks(int xtal)
> > diff --git a/arch/arm/mach-s3c64xx/setup-ide.c
b/arch/arm/mach-s3c64xx/setup-
> ide.c
> > new file mode 100644
> > index 0000000..0bf4e5e
> > --- /dev/null
> > +++ b/arch/arm/mach-s3c64xx/setup-ide.c
> > @@ -0,0 +1,55 @@
> > +/* linux/arch/arm/mach-s3c64xx/setup-ide.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.com/
> > + *
> > + * S3C64XX setup information for IDE
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > +*/
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/types.h>
> > +#include <linux/io.h>
> > +
> > +#include <mach/map.h>
> > +#include <mach/gpio.h>
> > +#include <mach/regs-clock.h>
> > +#include <plat/gpio-cfg.h>
> > +#include <plat/regs-ata.h>
> > +
> > +void s3c_ide_setup_gpio(void)
> > +{
> > + u32 reg;
> > + u32 gpio = 0;
> > +
> > + reg = __raw_readl(S3C_MEM_SYS_CFG) & (~0x3f);
> > +
> > + /* Independent CF interface, CF chip select configuration */
> > + __raw_writel(reg | MEM_SYS_CFG_INDEP_CF |
> > + MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S3C_MEM_SYS_CFG);
> > +
> > + s3c_gpio_cfgpin(S3C64XX_GPB(4), S3C_GPIO_SFN(4));
> > +
> > + /* Set XhiDATA[15:0] pins as CF Data[15:0] */
> > + for (gpio = S3C64XX_GPK(0); gpio <= S3C64XX_GPK(15); gpio++)
> > + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(5));
> > +
> > + /* Set XhiADDR[2:0] pins as CF ADDR[2:0] */
> > + for (gpio = S3C64XX_GPL(0); gpio <= S3C64XX_GPL(2); gpio++)
> > + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
> > +
> > + /* Set Xhi ctrl pins as CF ctrl pins(IORDY, IOWR, IORD, CE[0:1]) */
> > + s3c_gpio_cfgpin(S3C64XX_GPM(5), S3C_GPIO_SFN(1));
> > + for (gpio = S3C64XX_GPM(0); gpio <= S3C64XX_GPM(4); gpio++)
> > + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(6));
>
> i'll update this to the cfgrange when merging the cfgrange code.
>
OK
> > +}
> > +
> > +void s3c_ide_cfg_mode(void __iomem *sfrbase)
> > +{
> > + /* Select true-ide as the internal operating mode*/
> > + writel(readl(sfrbase + S3C_CFATA_MUX) | S3C_CFATA_MUX_TRUEIDE,
> > + sfrbase + S3C_CFATA_MUX);
> > +}
>
> maybe we just put this in the driver and select on type.
>
Will move it to the driver file.
> > diff --git a/arch/arm/plat-samsung/Kconfig
b/arch/arm/plat-samsung/Kconfig
> > index 2753fb3..6ec97fe 100644
> > --- a/arch/arm/plat-samsung/Kconfig
> > +++ b/arch/arm/plat-samsung/Kconfig
> > @@ -175,6 +175,11 @@ config S3C_DEV_I2C2
> > help
> > Compile in platform device definitions for I2C channel 2
> >
> > +config S3C_DEV_IDE
> > + bool
> > + help
> > + Compile in platform device definitions for IDE
> > +
> > config S3C_DEV_FB
> > bool
> > help
> > diff --git a/arch/arm/plat-samsung/Makefile
b/arch/arm/plat-samsung/Makefile
> > index b1d82cc..252fc76 100644
> > --- a/arch/arm/plat-samsung/Makefile
> > +++ b/arch/arm/plat-samsung/Makefile
> > @@ -48,6 +48,7 @@ obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o
> >
> > obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o
> > obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o
> > +obj-$(CONFIG_S3C_DEV_IDE) += dev-ide.o
> >
> > # DMA support
> >
> > diff --git a/arch/arm/plat-samsung/dev-ide.c
b/arch/arm/plat-samsung/dev-ide.c
> > new file mode 100644
> > index 0000000..c6b3292
> > --- /dev/null
> > +++ b/arch/arm/plat-samsung/dev-ide.c
> > @@ -0,0 +1,52 @@
> > +/* linux/arch/arm/plat-samsung/dev-ide.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.com
> > + *
> > + * S3C CF-ATA device definition.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > +*/
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/types.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/io.h>
> > +#include <mach/map.h>
> > +#include <plat/ata.h>
>
> do we need linux/io.h in here?
>
No..will remove it.
> soem spacing inebtwee nthe include groups would be nice too,.
>
OK
> > +static struct resource s3c_cfcon_resource[] = {
> > + [0] = {
> > + .start = SAMSUNG_PA_CFCON,
> > + .end = SAMSUNG_PA_CFCON + SZ_1M - 1,
> > + .flags = IORESOURCE_MEM,
>
> do we really need to map SZ_1M?
Will change it to SZ_16K.
> > + },
> > + [1] = {
> > + .start = IRQ_CFCON,
> > + .end = IRQ_CFCON,
> > + .flags = IORESOURCE_IRQ,
> > + },
> > +};
> > +
> > +struct platform_device s3c_device_cfcon = {
> > + .name = "s3c-pata",
>
> if the name is going to change, let's simply not bother
> setting one here.
>
Will remove the name.
> > + .id = 0,
> > + .num_resources = ARRAY_SIZE(s3c_cfcon_resource),
> > + .resource = s3c_cfcon_resource,
> > +};
>
> > +void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata)
> > +{
> > + struct s3c_ide_platdata *pd;
> > +
> > + pd = (struct s3c_ide_platdata *)kmemdup(pdata,
> ^^^^^ not needed.
Will remove it.
> > + sizeof(struct s3c_ide_platdata), GFP_KERNEL);
> > + if (!pd) {
> > + printk(KERN_ERR "%s: no memory for platform data\n",
> __func__);
> > + return;
> > + }
> > + s3c_device_cfcon.dev.platform_data = pd;
> > +}
> > diff --git a/arch/arm/plat-samsung/include/plat/ata.h b/arch/arm/plat-
> samsung/include/plat/ata.h
> > new file mode 100644
> > index 0000000..aea11dc
> > --- /dev/null
> > +++ b/arch/arm/plat-samsung/include/plat/ata.h
> > @@ -0,0 +1,38 @@
> > +/* arch/arm/plat-samsung/include/plat/ata.h
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.com
> > + *
> > + * S3C - CF Controller platform_device info
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > +*/
> > +
> > +#ifndef __ASM_PLAT_ATA_H
> > +#define __ASM_PLAT_ATA_H __FILE__
> > +
> > +/**
> > + * struct s3c_ide_platdata - S3C IDE driver platform data.
> > + * @setup_gpio: Setup the external GPIO pins to the right state for data
> > + * transfer in true-ide mode.
> > + * @cfg_mode: Platform specific setup for configuring the CF controller
> > + * in true-ide mode.
> > + */
> > +struct s3c_ide_platdata {
> > + void (*setup_gpio)(void);
> > + void (*cfg_mode)(void __iomem *sfrbase);
> > +};
> > +
> > +/*
> > + * s3c_ide_set_platdata() - Setup the platform specifc data for IDE
driver.
> > + * @pdata: Platform data for IDE driver.
> > + */
> > +extern void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata);
> > +
> > +/* architecture-specific IDE configuration */
> > +extern void s3c_ide_setup_gpio(void);
> > +extern void s3c_ide_cfg_mode(void __iomem *sfrbase);
> > +
> > +#endif /*__ASM_PLAT_ATA_H */
> > diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-
> samsung/include/plat/devs.h
> > index e6144e4..e3fcddb 100644
> > --- a/arch/arm/plat-samsung/include/plat/devs.h
> > +++ b/arch/arm/plat-samsung/include/plat/devs.h
> > @@ -75,6 +75,7 @@ extern struct platform_device s5pc110_device_onenand;
> >
> > extern struct platform_device s3c_device_usbgadget;
> > extern struct platform_device s3c_device_usb_hsotg;
> > +extern struct platform_device s3c_device_cfcon;
> >
> > extern struct platform_device s5pv210_device_ac97;
> > extern struct platform_device s5pv210_device_pcm0;
> > diff --git a/arch/arm/plat-samsung/include/plat/regs-ata.h
b/arch/arm/plat-
> samsung/include/plat/regs-ata.h
> > new file mode 100644
> > index 0000000..f73b267
> > --- /dev/null
> > +++ b/arch/arm/plat-samsung/include/plat/regs-ata.h
> > @@ -0,0 +1,56 @@
> > +/* arch/arm/plat-samsung/include/plat/regs-ata.h
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.com
> > + *
> > + * S3C CF-ATA register definitions
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > +*/
> > +
> > +#ifndef __ASM_PLAT_REGS_ATA_H
> > +#define __ASM_PLAT_REGS_ATA_H __FILE__
> > +
> > +#define S3C_CFATA_REG(x) (x)
> > +
> > +#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
> > +
> > +#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
> > +#define S3C_ATA_STATUS S3C_CFATA_REG(0x4)
> > +#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
> > +#define S3C_ATA_SWRST S3C_CFATA_REG(0xc)
> > +#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
> > +#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
> > +#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
> > +
> > +#define S3C_ATA_MDMA_TIME S3C_CFATA_REG(0x28)
> > +#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
> > +#define S3C_ATA_UDMA_TIME S3C_CFATA_REG(0x30)
> > +#define S3C_ATA_XFR_NUM S3C_CFATA_REG(0x34)
> > +#define S3C_ATA_XFR_CNT S3C_CFATA_REG(0x38)
> > +#define S3C_ATA_TBUF_START S3C_CFATA_REG(0x3c)
> > +#define S3C_ATA_TBUF_SIZE S3C_CFATA_REG(0x40)
> > +#define S3C_ATA_SBUF_START S3C_CFATA_REG(0x44)
> > +#define S3C_ATA_SBUF_SIZE S3C_CFATA_REG(0x48)
> > +#define S3C_ATA_CADR_TBUF S3C_CFATA_REG(0x4c)
> > +#define S3C_ATA_CADR_SBUF S3C_CFATA_REG(0x50)
> > +#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
> > +#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
> > +#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
> > +#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
> > +#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
> > +#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
> > +#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
> > +#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
> > +#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
> > +#define S3C_ATA_PIO_READY S3C_CFATA_REG(0x78)
> > +#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
> > +
> > +#define S3C_CFATA_MUX_TRUEIDE 0x01
> > +
> > +#define S3C_ATA_CFG_SWAP 0x40
> > +#define S3C_ATA_CFG_IORDYEN 0x02
> > +
> > +#endif /* __ASM_PLAT_REGS_ATA_H */
> > --
> > 1.6.2.5
> >
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410
2010-05-27 8:22 ` [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410 Kukjin Kim
2010-05-27 8:52 ` Ben Dooks
@ 2010-05-27 19:45 ` Russell King - ARM Linux
2010-06-02 2:33 ` Kukjin Kim
1 sibling, 1 reply; 24+ messages in thread
From: Russell King - ARM Linux @ 2010-05-27 19:45 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 05:22:01PM +0900, Kukjin Kim wrote:
> +#include <mach/map.h>
> +#include <mach/gpio.h>
shouldn't this be linux/gpio.h ?
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 2/4] ARM: S5PV210: Add support for Compact Flash driver on SMDKV210/SMDKC110
2010-05-27 8:22 [PATCH] Add Compact Flash driver for Samsung SoCs Kukjin Kim
2010-05-27 8:22 ` [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410 Kukjin Kim
@ 2010-05-27 8:22 ` Kukjin Kim
2010-05-27 19:46 ` Russell King - ARM Linux
2010-05-27 8:22 ` [PATCH 3/4] ARM: S5PC100: Add support for Compact Flash driver on SMDKC100 Kukjin Kim
2010-05-27 8:22 ` [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver Kukjin Kim
3 siblings, 1 reply; 24+ messages in thread
From: Kukjin Kim @ 2010-05-27 8:22 UTC (permalink / raw)
To: linux-arm-kernel
From: Abhilash Kesavan <a.kesavan@samsung.com>
Following is added for the CF-ATA driver:
- Platform data strucure instantiation
- Platform device definition and enabling code
- Platform-specific gpio setup code
- Fixed IRQ naming to match across 64xx and v210
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
arch/arm/mach-s5pv210/Kconfig | 9 +++++
arch/arm/mach-s5pv210/Makefile | 1 +
arch/arm/mach-s5pv210/cpu.c | 1 +
arch/arm/mach-s5pv210/include/mach/irqs.h | 2 +-
arch/arm/mach-s5pv210/include/mach/map.h | 4 ++-
arch/arm/mach-s5pv210/mach-smdkc110.c | 8 ++++
arch/arm/mach-s5pv210/mach-smdkv210.c | 7 ++++
arch/arm/mach-s5pv210/setup-ide.c | 51 +++++++++++++++++++++++++++++
8 files changed, 81 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-s5pv210/setup-ide.c
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 0761eac..29b900e 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -43,6 +43,11 @@ config S5PV210_SETUP_SDHCI_GPIO
help
Common setup code for SDHCI gpio.
+config S5PV210_SETUP_IDE
+ bool
+ help
+ Common setup code for S5PV210 IDE GPIO configurations
+
# machine support
config MACH_AQUILA
@@ -75,6 +80,8 @@ config MACH_SMDKV210
select SAMSUNG_DEV_TS
select S3C_DEV_WDT
select HAVE_S3C2410_WATCHDOG
+ select S3C_DEV_IDE
+ select S5PV210_SETUP_IDE
help
Machine support for Samsung SMDKV210
@@ -84,6 +91,8 @@ config MACH_SMDKC110
select ARCH_SPARSEMEM_ENABLE
select S3C_DEV_WDT
select HAVE_S3C2410_WATCHDOG
+ select S3C_DEV_IDE
+ select S5PV210_SETUP_IDE
help
Machine support for Samsung SMDKC110
S5PC110(MCP) is one of package option of S5PV210
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 30be9a6..af55785 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -31,5 +31,6 @@ obj-$(CONFIG_S5PC110_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S5PV210_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PV210_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PV210_SETUP_I2C2) += setup-i2c2.o
+obj-$(CONFIG_S5PV210_SETUP_IDE) += setup-ide.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S5PV210_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 411a4a9..fac2f0d 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -79,6 +79,7 @@ void __init s5pv210_map_io(void)
#ifdef CONFIG_S3C_DEV_ADC
s3c_device_adc.name = "s3c64xx-adc";
#endif
+ s3c_device_cfcon.name = "s5pv210-pata";
iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index 9689537..e1d3c45 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -45,7 +45,7 @@
#define IRQ_IEMIEC S5P_IRQ_VIC1(6)
#define IRQ_ONENAND S5P_IRQ_VIC1(7)
#define IRQ_NFC S5P_IRQ_VIC1(8)
-#define IRQ_CFC S5P_IRQ_VIC1(9)
+#define IRQ_CFCON S5P_IRQ_VIC1(9)
#define IRQ_UART0 S5P_IRQ_VIC1(10)
#define IRQ_UART1 S5P_IRQ_VIC1(11)
#define IRQ_UART2 S5P_IRQ_VIC1(12)
diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h
index 34eb168..48b8c02 100644
--- a/arch/arm/mach-s5pv210/include/mach/map.h
+++ b/arch/arm/mach-s5pv210/include/mach/map.h
@@ -54,6 +54,8 @@
#define S5PV210_PA_SROMC (0xE8000000)
+#define S5PV210_PA_CFCON (0xE8200000)
+
#define S5PV210_PA_MDMA 0xFA200000
#define S5PV210_PA_PDMA0 0xE0900000
#define S5PV210_PA_PDMA1 0xE0A00000
@@ -102,7 +104,7 @@
#define S3C_PA_IIC2 S5PV210_PA_IIC2
#define S3C_PA_FB S5PV210_PA_FB
#define S3C_PA_WDT S5PV210_PA_WATCHDOG
-
+#define SAMSUNG_PA_CFCON S5PV210_PA_CFCON
#define SAMSUNG_PA_ADC S5PV210_PA_ADC
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index 4c8903c..7fce0a2 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -25,6 +25,7 @@
#include <plat/s5pv210.h>
#include <plat/devs.h>
#include <plat/cpu.h>
+#include <plat/ata.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -71,10 +72,15 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
},
};
+static struct s3c_ide_platdata smdkv210_ide_pdata __initdata = {
+ .setup_gpio = s3c_ide_setup_gpio,
+};
+
static struct platform_device *smdkc110_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_ac97,
&s3c_device_wdt,
+ &s3c_device_cfcon,
};
static void __init smdkc110_map_io(void)
@@ -86,6 +92,8 @@ static void __init smdkc110_map_io(void)
static void __init smdkc110_machine_init(void)
{
+ s3c_ide_set_platdata(&smdkv210_ide_pdata);
+
platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
}
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 0d46279..ac42e7c 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -27,6 +27,7 @@
#include <plat/cpu.h>
#include <plat/adc.h>
#include <plat/ts.h>
+#include <plat/ata.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define S5PV210_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -73,12 +74,17 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = {
},
};
+static struct s3c_ide_platdata smdkv210_ide_pdata __initdata = {
+ .setup_gpio = s3c_ide_setup_gpio,
+};
+
static struct platform_device *smdkv210_devices[] __initdata = {
&s5pv210_device_iis0,
&s5pv210_device_ac97,
&s3c_device_adc,
&s3c_device_ts,
&s3c_device_wdt,
+ &s3c_device_cfcon,
};
static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
@@ -97,6 +103,7 @@ static void __init smdkv210_map_io(void)
static void __init smdkv210_machine_init(void)
{
s3c24xx_ts_set_platdata(&s3c_ts_platform);
+ s3c_ide_set_platdata(&smdkv210_ide_pdata);
platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
}
diff --git a/arch/arm/mach-s5pv210/setup-ide.c b/arch/arm/mach-s5pv210/setup-ide.c
new file mode 100644
index 0000000..9d892ac
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-ide.c
@@ -0,0 +1,51 @@
+/* linux/arch/arm/mach-s5pv210/setup-ide.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5PV210 setup information for IDE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_ide_setup_gpio(void)
+{
+ unsigned int gpio = 0;
+
+ for (gpio = S5PV210_GPJ0(0); gpio <= S5PV210_GPJ0(7); gpio++) {
+ /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST,
+ CF_DMACK */
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ for (gpio = S5PV210_GPJ2(0); gpio <= S5PV210_GPJ2(7); gpio++) {
+ /*CF_Data[0 - 7] */
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ for (gpio = S5PV210_GPJ3(0); gpio <= S5PV210_GPJ3(7); gpio++) {
+ /* CF_Data[8 - 15] */
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ for (gpio = S5PV210_GPJ4(0); gpio <= S5PV210_GPJ4(3); gpio++) {
+ /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 3/4] ARM: S5PC100: Add support for Compact Flash driver on SMDKC100
2010-05-27 8:22 [PATCH] Add Compact Flash driver for Samsung SoCs Kukjin Kim
2010-05-27 8:22 ` [PATCH 1/4] ARM: S3C64XX: Add support for Compact Flash driver on SMDK6410 Kukjin Kim
2010-05-27 8:22 ` [PATCH 2/4] ARM: S5PV210: Add support for Compact Flash driver on SMDKV210/SMDKC110 Kukjin Kim
@ 2010-05-27 8:22 ` Kukjin Kim
2010-05-27 19:47 ` Russell King - ARM Linux
2010-05-27 8:22 ` [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver Kukjin Kim
3 siblings, 1 reply; 24+ messages in thread
From: Kukjin Kim @ 2010-05-27 8:22 UTC (permalink / raw)
To: linux-arm-kernel
From: Abhilash Kesavan <a.kesavan@samsung.com>
Following is added for the CF-ATA driver:
- Platform data strucure instantiatio
- Platform device definition and enabling code
- Platform-specific gpio setup code
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
arch/arm/mach-s5pc100/Kconfig | 7 ++
arch/arm/mach-s5pc100/Makefile | 1 +
arch/arm/mach-s5pc100/cpu.c | 1 +
arch/arm/mach-s5pc100/include/mach/irqs.h | 2 +-
arch/arm/mach-s5pc100/include/mach/map.h | 4 +
arch/arm/mach-s5pc100/include/mach/regs-clock.h | 3 +
arch/arm/mach-s5pc100/mach-smdkc100.c | 8 ++
arch/arm/mach-s5pc100/setup-ide.c | 79 +++++++++++++++++++++++
8 files changed, 104 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-s5pc100/setup-ide.c
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index b2a11df..d030c95 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -36,17 +36,24 @@ config S5PC100_SETUP_SDHCI_GPIO
help
Common setup code for SDHCI gpio.
+config S5PC100_SETUP_IDE
+ bool
+ help
+ Common setup code for S5PC100 IDE GPIO configurations
+
config MACH_SMDKC100
bool "SMDKC100"
select CPU_S5PC100
select S3C_DEV_FB
select S3C_DEV_I2C1
+ select S3C_DEV_IDE
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC1
select S3C_DEV_HSMMC2
select S5PC100_SETUP_FB_24BPP
select S5PC100_SETUP_I2C1
select S5PC100_SETUP_SDHCI
+ select S5PC100_SETUP_IDE
help
Machine support for the Samsung SMDKC100
diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile
index 543f3de..f192d1a 100644
--- a/arch/arm/mach-s5pc100/Makefile
+++ b/arch/arm/mach-s5pc100/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o
obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o
obj-$(CONFIG_S5PC100_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_S5PC100_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
+obj-$(CONFIG_S5PC100_SETUP_IDE) += setup-ide.o
# device support
obj-y += dev-audio.o
diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c
index 7b5bdbc..7df6db0 100644
--- a/arch/arm/mach-s5pc100/cpu.c
+++ b/arch/arm/mach-s5pc100/cpu.c
@@ -92,6 +92,7 @@ void __init s5pc100_map_io(void)
s3c_i2c1_setname("s3c2440-i2c");
s3c_onenand_setname("s5pc100-onenand");
+ s3c_device_cfcon.name = "s5pc100-pata";
}
void __init s5pc100_init_clocks(int xtal)
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index 28aa551..bfcc0b9 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -38,7 +38,7 @@
#define IRQ_IEMIEC S5P_IRQ_VIC1(6)
#define IRQ_ONENAND S5P_IRQ_VIC1(7)
#define IRQ_NFC S5P_IRQ_VIC1(8)
-#define IRQ_CFC S5P_IRQ_VIC1(9)
+#define IRQ_CFCON S5P_IRQ_VIC1(9)
#define IRQ_UART0 S5P_IRQ_VIC1(10)
#define IRQ_UART1 S5P_IRQ_VIC1(11)
#define IRQ_UART2 S5P_IRQ_VIC1(12)
diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h
index cadae43..c5f944a 100644
--- a/arch/arm/mach-s5pc100/include/mach/map.h
+++ b/arch/arm/mach-s5pc100/include/mach/map.h
@@ -61,6 +61,9 @@
#define S5PC100_PA_ONENAND (0xE7100000)
+/* CF Controller */
+#define S5PC100_PA_CFCON (0xE7800000)
+
/* DMA */
#define S5PC100_PA_MDMA (0xE8100000)
#define S5PC100_PA_PDMA0 (0xE9000000)
@@ -134,5 +137,6 @@
#define S3C_PA_ONENAND S5PC100_PA_ONENAND
#define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF
#define S3C_SZ_ONENAND_BUF S5PC100_SZ_ONENAND_BUF
+#define SAMSUNG_PA_CFCON S5PC100_PA_CFCON
#endif /* __ASM_ARCH_C100_MAP_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-clock.h b/arch/arm/mach-s5pc100/include/mach/regs-clock.h
index 5d27d28..bc92da2 100644
--- a/arch/arm/mach-s5pc100/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pc100/include/mach/regs-clock.h
@@ -71,7 +71,10 @@
#define S5P_CLKDIV1_PCLKD1_SHIFT (16)
#define S5PC100_SWRESET S5PC100_REG_OTHERS(0x000)
+#define S5PC100_MEM_SYS_CFG S5PC100_REG_OTHERS(0x200)
#define S5PC100_SWRESET_RESETVAL 0xc100
+#define MEM_SYS_CFG_EBI_FIX_PRI_CFCON 0x30
+
#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index af22f82..e69ddf9 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -42,6 +42,7 @@
#include <plat/s5pc100.h>
#include <plat/fb.h>
#include <plat/iic.h>
+#include <plat/ata.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define S5PC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -149,6 +150,11 @@ static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = {
.setup_gpio = s5pc100_fb_gpio_setup_24bpp,
};
+static struct s3c_ide_platdata smdkc100_ide_pdata __initdata = {
+ .setup_gpio = s3c_ide_setup_gpio,
+ .cfg_mode = s3c_ide_cfg_mode,
+};
+
static struct platform_device *smdkc100_devices[] __initdata = {
&s3c_device_i2c0,
&s3c_device_i2c1,
@@ -159,6 +165,7 @@ static struct platform_device *smdkc100_devices[] __initdata = {
&smdkc100_lcd_powerdev,
&s5pc100_device_iis0,
&s5pc100_device_ac97,
+ &s3c_device_cfcon,
};
static void __init smdkc100_map_io(void)
@@ -177,6 +184,7 @@ static void __init smdkc100_machine_init(void)
i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
s3c_fb_set_platdata(&smdkc100_lcd_pdata);
+ s3c_ide_set_platdata(&smdkc100_ide_pdata);
/* LCD init */
gpio_request(S5PC100_GPD(0), "GPD");
diff --git a/arch/arm/mach-s5pc100/setup-ide.c b/arch/arm/mach-s5pc100/setup-ide.c
new file mode 100644
index 0000000..f4abb5a
--- /dev/null
+++ b/arch/arm/mach-s5pc100/setup-ide.c
@@ -0,0 +1,79 @@
+/* linux/arch/arm/mach-s5pc100/setup-ide.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5PC100 setup information for IDE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+#include <mach/regs-clock.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-ata.h>
+
+void s3c_ide_setup_gpio(void)
+{
+ u32 reg;
+ u32 gpio = 0;
+
+ /* Independent CF interface, CF chip select configuration */
+ reg = __raw_readl(S5PC100_MEM_SYS_CFG) & (~0x3f);
+ __raw_writel(reg | MEM_SYS_CFG_EBI_FIX_PRI_CFCON, S5PC100_MEM_SYS_CFG);
+
+ /* CF_Add[0 - 2], CF_IORDY, CF_INTRQ, CF_DMARQ, CF_DMARST, CF_DMACK */
+ for (gpio = S5PC100_GPJ0(0); gpio <= S5PC100_GPJ0(7); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ /*CF_Data[0 - 7] */
+ for (gpio = S5PC100_GPJ2(0); gpio <= S5PC100_GPJ2(7); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ /* CF_Data[8 - 15] */
+ for (gpio = S5PC100_GPJ3(0); gpio <= S5PC100_GPJ3(7); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ /* CF_CS0, CF_CS1, CF_IORD, CF_IOWR */
+ for (gpio = S5PC100_GPJ4(0); gpio <= S5PC100_GPJ4(3); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(4));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+ }
+
+ /* EBI_OE, EBI_WE */
+ for (gpio = S5PC100_GPK0(6); gpio <= S5PC100_GPK0(7); gpio++)
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0));
+
+ /* CF_OE, CF_WE */
+ for (gpio = S5PC100_GPK1(6); gpio <= S5PC100_GPK1(7); gpio++) {
+ s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+ }
+
+ /* CF_CD */
+ s3c_gpio_cfgpin(S5PC100_GPK3(5), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PC100_GPK3(5), S3C_GPIO_PULL_NONE);
+}
+
+void s3c_ide_cfg_mode(void __iomem *sfrbase)
+{
+ /* Select true-ide as the internal operating mode*/
+ writel(readl(sfrbase + S3C_CFATA_MUX) | S3C_CFATA_MUX_TRUEIDE,
+ sfrbase + S3C_CFATA_MUX);
+}
--
1.6.2.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:22 [PATCH] Add Compact Flash driver for Samsung SoCs Kukjin Kim
` (2 preceding siblings ...)
2010-05-27 8:22 ` [PATCH 3/4] ARM: S5PC100: Add support for Compact Flash driver on SMDKC100 Kukjin Kim
@ 2010-05-27 8:22 ` Kukjin Kim
2010-05-27 8:43 ` Ben Dooks
` (3 more replies)
3 siblings, 4 replies; 24+ messages in thread
From: Kukjin Kim @ 2010-05-27 8:22 UTC (permalink / raw)
To: linux-arm-kernel
From: Abhilash Kesavan <a.kesavan@samsung.com>
Adds support for the Samsung PATA controller. This driver is based on the
Libata subsystem and references the earlier patches sent for IDE subsystem.
Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1 +
drivers/ata/pata_samsung.c | 591 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 601 insertions(+), 0 deletions(-)
create mode 100644 drivers/ata/pata_samsung.c
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index e68541f..ce40f66 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -640,6 +640,15 @@ config PATA_RZ1000
If unsure, say N.
+config PATA_SAMSUNG
+ tristate "Samsung SoC PATA support"
+ depends on S3C_DEV_IDE
+ help
+ This option enables basic support for Samsung's S3C/S5P board
+ PATA controllers via the new ATA layer
+
+ If unsure, say N.
+
config PATA_SC1200
tristate "SC1200 PATA support"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index d0a93c4..0b6d29a 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
obj-$(CONFIG_PATA_RDC) += pata_rdc.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
+obj-$(CONFIG_PATA_SAMSUNG) += pata_samsung.o
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
diff --git a/drivers/ata/pata_samsung.c b/drivers/ata/pata_samsung.c
new file mode 100644
index 0000000..14381e4
--- /dev/null
+++ b/drivers/ata/pata_samsung.c
@@ -0,0 +1,591 @@
+/* linux/drivers/ata/pata_samsung.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * PATA driver for Samsung SoC's.
+ * Supports CF Interface in True IDE mode. Currently only PIO mode has been
+ * implemented; UDMA support has to be added.
+ *
+ * Based on:
+ * PATA driver for AT91SAM9260 Static Memory Controller
+ * PATA driver for Toshiba SCC controller
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/libata.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <plat/ata.h>
+#include <plat/regs-ata.h>
+
+#define DRV_NAME "pata_samsung"
+#define DRV_VERSION "0.1"
+
+enum s3c_cpu_type {
+ TYPE_S3C6400,
+ TYPE_S5PC100,
+ TYPE_S5PV210,
+};
+
+/*
+ * struct s3c_ide_info - S3C PATA instance.
+ * @clk: The clock resource for this controller.
+ * @ide_addr: The area mapped for the hardware registers.
+ * @sfr_addr: The area mapped for the special function registers.
+ * @irq: The IRQ number we are using.
+ * @cpu_type: The exact type of this controller.
+ * @fifo_status_reg: The ATA_FIFO_STATUS register offset.
+ */
+struct s3c_ide_info {
+ struct clk *clk;
+ void __iomem *ide_addr;
+ void __iomem *sfr_addr;
+ unsigned int irq;
+ enum s3c_cpu_type cpu_type;
+ unsigned int fifo_status_reg;
+};
+
+static unsigned long piotime[5];
+
+static void pata_s3c_set_endian(void *s3c_ide_regbase, u8 mode)
+{
+ u32 reg = readl(s3c_ide_regbase + S3C_ATA_CFG);
+ reg = mode ? (reg & ~S3C_ATA_CFG_SWAP) : (reg | S3C_ATA_CFG_SWAP);
+ writel(reg, s3c_ide_regbase + S3C_ATA_CFG);
+}
+
+static void pata_s3c_tune_chipset(struct s3c_ide_info *info, u8 ide_mode)
+{
+ ulong ata_cfg = readl(info->ide_addr + S3C_ATA_CFG);
+
+ /* IORDY is enabled for modes > PIO2 */
+ if (XFER_PIO_0 <= ide_mode && ide_mode <= XFER_PIO_4) {
+
+ switch (ide_mode) {
+ case XFER_PIO_0:
+ case XFER_PIO_1:
+ case XFER_PIO_2:
+ ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
+ break;
+ case XFER_PIO_3:
+ case XFER_PIO_4:
+ ata_cfg |= S3C_ATA_CFG_IORDYEN;
+ break;
+ }
+
+ writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
+ writel(piotime[ide_mode - XFER_PIO_0],
+ info->ide_addr + S3C_ATA_PIO_TIME);
+ } else {
+ /* Default to PIO0 */
+ ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
+ writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
+ writel(piotime[0], info->ide_addr + S3C_ATA_PIO_TIME);
+ }
+}
+
+static void
+pata_s3c_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ struct s3c_ide_info *info = ap->host->private_data;
+
+ /* Configure IORDY based on PIO mode and also set the timing value */
+ pata_s3c_tune_chipset(info, adev->pio_mode);
+}
+
+/*
+ * Waits until the IDE controller is able to perform next read/write
+ * operation to the disk. Needed for 64XX series boards only.
+ */
+static int wait_for_host_ready(struct s3c_ide_info *info)
+{
+ ulong timeout;
+
+ /* wait for maximum of 20 msec */
+ timeout = jiffies + msecs_to_jiffies(20);
+ while (time_before(jiffies, timeout)) {
+ if ((readl(info->ide_addr + info->fifo_status_reg) >> 28) == 0)
+ return 0;
+ }
+ return -EBUSY;
+}
+
+/*
+ * Writes to one of the task file registers.
+ */
+static void ata_outb(struct ata_host *host, u8 addr, void __iomem *reg)
+{
+ struct s3c_ide_info *info = host->private_data;
+
+ wait_for_host_ready(info);
+ __raw_writeb(addr, reg);
+}
+
+/*
+ * Reads from one of the task file registers.
+ */
+static u8 ata_inb(struct ata_host *host, void __iomem *reg)
+{
+ struct s3c_ide_info *info = host->private_data;
+ u8 temp;
+
+ wait_for_host_ready(info);
+ temp = __raw_readb(reg);
+ wait_for_host_ready(info);
+ temp = __raw_readb(info->ide_addr + S3C_ATA_PIO_RDATA);
+ return temp;
+}
+
+/*
+ * pata_s3c_tf_load - send taskfile registers to host controller
+ */
+static void pata_s3c_tf_load(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+ if (tf->ctl != ap->last_ctl) {
+ if (ioaddr->ctl_addr)
+ ata_outb(ap->host, tf->ctl, ioaddr->ctl_addr);
+ ap->last_ctl = tf->ctl;
+ ata_wait_idle(ap);
+ }
+
+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ WARN_ON_ONCE(!ioaddr->ctl_addr);
+ ata_outb(ap->host, tf->hob_feature, ioaddr->feature_addr);
+ ata_outb(ap->host, tf->hob_nsect, ioaddr->nsect_addr);
+ ata_outb(ap->host, tf->hob_lbal, ioaddr->lbal_addr);
+ ata_outb(ap->host, tf->hob_lbam, ioaddr->lbam_addr);
+ ata_outb(ap->host, tf->hob_lbah, ioaddr->lbah_addr);
+ }
+
+ if (is_addr) {
+ ata_outb(ap->host, tf->feature, ioaddr->feature_addr);
+ ata_outb(ap->host, tf->nsect, ioaddr->nsect_addr);
+ ata_outb(ap->host, tf->lbal, ioaddr->lbal_addr);
+ ata_outb(ap->host, tf->lbam, ioaddr->lbam_addr);
+ ata_outb(ap->host, tf->lbah, ioaddr->lbah_addr);
+ }
+
+ if (tf->flags & ATA_TFLAG_DEVICE)
+ ata_outb(ap->host, tf->device, ioaddr->device_addr);
+
+ ata_wait_idle(ap);
+}
+
+/*
+ * pata_s3c_tf_read - input device's ATA taskfile shadow registers
+ */
+static void pata_s3c_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ struct ata_ioports *ioaddr = &ap->ioaddr;
+
+ tf->command = ata_sff_check_status(ap);
+ tf->feature = ata_inb(ap->host, ioaddr->error_addr);
+ tf->nsect = ata_inb(ap->host, ioaddr->nsect_addr);
+ tf->lbal = ata_inb(ap->host, ioaddr->lbal_addr);
+ tf->lbam = ata_inb(ap->host, ioaddr->lbam_addr);
+ tf->lbah = ata_inb(ap->host, ioaddr->lbah_addr);
+ tf->device = ata_inb(ap->host, ioaddr->device_addr);
+
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ if (likely(ioaddr->ctl_addr)) {
+ iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+ tf->hob_feature = ata_inb(ap->host, ioaddr->error_addr);
+ tf->hob_nsect = ata_inb(ap->host, ioaddr->nsect_addr);
+ tf->hob_lbal = ata_inb(ap->host, ioaddr->lbal_addr);
+ tf->hob_lbam = ata_inb(ap->host, ioaddr->lbam_addr);
+ tf->hob_lbah = ata_inb(ap->host, ioaddr->lbah_addr);
+ iowrite8(tf->ctl, ioaddr->ctl_addr);
+ ap->last_ctl = tf->ctl;
+ } else
+ WARN_ON_ONCE(1);
+ }
+}
+
+/*
+ * pata_s3c_exec_command - issue ATA command to host controller
+ */
+static void pata_s3c_exec_command(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ ata_outb(ap->host, tf->command, ap->ioaddr.command_addr);
+ ata_sff_pause(ap);
+}
+
+/*
+ * pata_s3c_check_status - Read device status register
+ */
+static u8 pata_s3c_check_status(struct ata_port *ap)
+{
+ return ata_inb(ap->host, ap->ioaddr.status_addr);
+}
+
+/*
+ * pata_s3c_data_xfer - Transfer data by PIO
+ */
+unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char *buf,
+ unsigned int buflen, int rw)
+{
+ struct ata_port *ap = dev->link->ap;
+ struct s3c_ide_info *info = ap->host->private_data;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
+ unsigned int words = buflen >> 1, i;
+ u16 *temp_addr = (u16 *)buf;
+
+ if (rw == READ) {
+ for (i = 0; i < words; i++, temp_addr++) {
+ wait_for_host_ready(info);
+ *temp_addr = __raw_readw(data_addr);
+ wait_for_host_ready(info);
+ *temp_addr = __raw_readw(info->ide_addr
+ + S3C_ATA_PIO_RDATA);
+ }
+ } else {
+ for (i = 0; i < words; i++, temp_addr++) {
+ wait_for_host_ready(info);
+ writel(*temp_addr, data_addr);
+ }
+ }
+
+ return words << 1;
+}
+
+static struct scsi_host_template pata_s3c_sht = {
+ ATA_PIO_SHT(DRV_NAME),
+};
+
+static struct ata_port_operations pata_s3c_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_check_status = pata_s3c_check_status,
+ .sff_tf_load = pata_s3c_tf_load,
+ .sff_tf_read = pata_s3c_tf_read,
+ .sff_data_xfer = pata_s3c_data_xfer,
+ .sff_exec_command = pata_s3c_exec_command,
+ .qc_prep = ata_noop_qc_prep,
+ .set_piomode = pata_s3c_set_piomode,
+};
+
+static struct ata_port_operations pata_s5p_port_ops = {
+ .inherits = &ata_sff_port_ops,
+ .qc_prep = ata_noop_qc_prep,
+ .set_piomode = pata_s3c_set_piomode,
+};
+
+static void pata_s3c_enable(void *s3c_ide_regbase, u8 state)
+{
+ u32 temp = readl(s3c_ide_regbase + S3C_ATA_CTRL);
+ temp = state ? temp | 1 : temp & ~1;
+ writel(temp, s3c_ide_regbase + S3C_ATA_CTRL);
+}
+
+static irqreturn_t pata_s3c_irq(int irq, void *dev_instance)
+{
+ struct ata_host *host = dev_instance;
+ struct s3c_ide_info *info = host->private_data;
+ u32 reg;
+
+ reg = readl(info->ide_addr + S3C_ATA_IRQ);
+ writel(reg, info->ide_addr + S3C_ATA_IRQ);
+
+ return ata_sff_interrupt(irq, dev_instance);
+}
+
+static void pata_s3c_setup_timing(struct s3c_ide_info *info)
+{
+ uint t1, t2, teoc, i;
+
+ uint pio_t1[5] = { 70, 50, 30, 30, 25 };
+ uint pio_t2[5] = { 290, 290, 290, 80, 70 };
+ uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
+
+ ulong cycle_time = (uint) (1000000000 / clk_get_rate(info->clk));
+
+ for (i = 0; i < 5; i++) {
+ t1 = (pio_t1[i] / cycle_time) & 0x0f;
+ t2 = (pio_t2[i] / cycle_time) & 0xff;
+ teoc = (pio_teoc[i] / cycle_time) & 0xff;
+ piotime[i] = (teoc << 12) | (t2 << 4) | t1;
+ }
+}
+
+static void pata_s3c_hwinit(struct s3c_ide_info *info,
+ struct s3c_ide_platdata *pdata)
+{
+ /* Select true-ide as the internal operating mode*/
+ if (pdata && (pdata->cfg_mode))
+ pdata->cfg_mode(info->sfr_addr);
+
+ switch (info->cpu_type) {
+ case TYPE_S3C6400:
+ /* Configure as big endian and enable the i/f*/
+ pata_s3c_set_endian(info->ide_addr, 1);
+ pata_s3c_enable(info->ide_addr, 1);
+ mdelay(100);
+
+ /* Remove IRQ Status */
+ writel(0x1f, info->ide_addr + S3C_ATA_IRQ);
+ writel(0x1b, info->ide_addr + S3C_ATA_IRQ_MSK);
+ break;
+
+ case TYPE_S5PV210:
+ case TYPE_S5PC100:
+ /* Configure as little endian and enable the i/f */
+ pata_s3c_set_endian(info->ide_addr, 0);
+ pata_s3c_enable(info->ide_addr, 1);
+ mdelay(100);
+
+ /* Remove IRQ Status */
+ writel(0x3f, info->ide_addr + S3C_ATA_IRQ);
+ writel(0x3f, info->ide_addr + S3C_ATA_IRQ_MSK);
+ break;
+
+ default:
+ BUG();
+ }
+}
+
+static int __devinit pata_s3c_probe(struct platform_device *pdev)
+{
+ struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
+ struct device *dev = &pdev->dev;
+ struct s3c_ide_info *info;
+ struct resource *res;
+ struct ata_port *ap;
+ struct ata_host *host;
+ enum s3c_cpu_type cpu_type;
+ int ret;
+
+ cpu_type = platform_get_device_id(pdev)->driver_data;
+
+ info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ dev_err(dev, "failed to allocate memory for device data\n");
+ return -ENOMEM;
+ }
+
+ info->irq = platform_get_irq(pdev, 0);
+ if (info->irq < 0) {
+ dev_err(dev, "could not obtain irq number\n");
+ ret = -ENODEV;
+ goto release_device_mem;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(dev, "failed to get mem resource\n");
+ ret = -ENODEV;
+ goto release_device_mem;
+ }
+
+ info->ide_addr = devm_ioremap(dev,
+ res->start, res->end - res->start + 1);
+ if (!info->ide_addr) {
+ dev_err(dev, "failed to map IO base address\n");
+ ret = -ENOMEM;
+ goto release_mem;
+ }
+
+ info->clk = clk_get(&pdev->dev, "cfcon");
+ if (IS_ERR(info->clk)) {
+ dev_err(dev, "failed to get access to cf controller clock\n");
+ ret = PTR_ERR(info->clk);
+ info->clk = NULL;
+ goto unmap;
+ }
+
+ if (clk_enable(info->clk)) {
+ dev_err(dev, "failed to enable clock source.\n");
+ goto clkerr;
+ }
+
+ /* init ata host */
+ host = ata_host_alloc(dev, 1);
+ if (!host) {
+ dev_err(dev, "failed to allocate ide host\n");
+ ret = -ENOMEM;
+ goto stop_clk;
+ }
+
+ ap = host->ports[0];
+ ap->flags |= ATA_FLAG_MMIO;
+ ap->pio_mask = ATA_PIO4;
+
+ if (cpu_type == TYPE_S3C6400) {
+ ap->ops = &pata_s3c_port_ops;
+ info->sfr_addr = info->ide_addr + 0x1800;
+ info->ide_addr = info->ide_addr + 0x1900;
+ info->fifo_status_reg = 0x94;
+ } else if (cpu_type == TYPE_S5PC100) {
+ ap->ops = &pata_s5p_port_ops;
+ info->sfr_addr = info->ide_addr + 0x1800;
+ info->ide_addr = info->ide_addr + 0x1900;
+ info->fifo_status_reg = 0x84;
+ } else {
+ ap->ops = &pata_s5p_port_ops;
+ info->fifo_status_reg = 0x84;
+ }
+
+ info->cpu_type = cpu_type;
+
+ if (!(info->irq)) {
+ ap->flags |= ATA_FLAG_PIO_POLLING;
+ ata_port_desc(ap, "no IRQ, using PIO polling\n");
+ }
+
+ ap->ioaddr.cmd_addr = info->ide_addr + S3C_ATA_CMD;
+ ap->ioaddr.data_addr = info->ide_addr + S3C_ATA_PIO_DTR;
+ ap->ioaddr.error_addr = info->ide_addr + S3C_ATA_PIO_FED;
+ ap->ioaddr.feature_addr = info->ide_addr + S3C_ATA_PIO_FED;
+ ap->ioaddr.nsect_addr = info->ide_addr + S3C_ATA_PIO_SCR;
+ ap->ioaddr.lbal_addr = info->ide_addr + S3C_ATA_PIO_LLR;
+ ap->ioaddr.lbam_addr = info->ide_addr + S3C_ATA_PIO_LMR;
+ ap->ioaddr.lbah_addr = info->ide_addr + S3C_ATA_PIO_LHR;
+ ap->ioaddr.device_addr = info->ide_addr + S3C_ATA_PIO_DVR;
+ ap->ioaddr.status_addr = info->ide_addr + S3C_ATA_PIO_CSD;
+ ap->ioaddr.command_addr = info->ide_addr + S3C_ATA_PIO_CSD;
+ ap->ioaddr.altstatus_addr = info->ide_addr + S3C_ATA_PIO_DAD;
+ ap->ioaddr.ctl_addr = info->ide_addr + S3C_ATA_PIO_DAD;
+
+
+ ata_port_desc(ap, "mmio cmd 0x%llx ",
+ (unsigned long long)res->start);
+
+ host->private_data = info;
+
+ /* Calculates timing parameters for PIO mode */
+ pata_s3c_setup_timing(info);
+
+ if (pdata && (pdata->setup_gpio))
+ pdata->setup_gpio();
+
+ /* Set endianness and enable the interface */
+ pata_s3c_hwinit(info, pdata);
+
+ return ata_host_activate(host, info->irq ? info->irq : 0,
+ info->irq ? pata_s3c_irq : NULL,
+ IRQF_DISABLED, &pata_s3c_sht);
+
+ dev_set_drvdata(&pdev->dev, host);
+
+stop_clk:
+ clk_disable(info->clk);
+clkerr:
+ clk_put(info->clk);
+unmap:
+ devm_iounmap(dev, info->ide_addr);
+release_mem:
+ release_mem_region(res->start, res->end - res->start + 1);
+release_device_mem:
+ kfree(info);
+return ret;
+}
+
+static int __devexit pata_s3c_remove(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct s3c_ide_info *info;
+ struct resource *res;
+
+ if (!host)
+ return 0;
+ info = host->private_data;
+
+ ata_host_detach(host);
+
+ devm_iounmap(&pdev->dev, info->ide_addr);
+ clk_disable(info->clk);
+ clk_put(info->clk);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
+ kfree(info);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int pata_s3c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ if (host)
+ return ata_host_suspend(host, state);
+ else
+ return 0;
+}
+
+static int pata_s3c_resume(struct platform_device *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
+ struct s3c_ide_info *info;
+
+ info = host->private_data;
+
+ if (host) {
+ pata_s3c_hwinit(info, pdata);
+ ata_host_resume(host);
+ }
+
+ return 0;
+}
+#endif
+
+/* driver device registration */
+static struct platform_device_id pata_s3c_driver_ids[] = {
+ {
+ .name = "s3c6400-pata",
+ .driver_data = TYPE_S3C6400,
+ }, {
+ .name = "s5pc100-pata",
+ .driver_data = TYPE_S5PC100,
+ }, {
+ .name = "s5pv210-pata",
+ .driver_data = TYPE_S5PV210,
+ },
+ { }
+};
+
+MODULE_DEVICE_TABLE(platform, pata_s3c_driver_ids);
+
+static struct platform_driver pata_s3c_driver = {
+ .probe = pata_s3c_probe,
+ .remove = __devexit_p(pata_s3c_remove),
+ .id_table = pata_s3c_driver_ids,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+#ifdef CONFIG_PM
+ .suspend = pata_s3c_suspend,
+ .resume = pata_s3c_resume,
+#endif
+};
+
+static int __init pata_s3c_init(void)
+{
+ return platform_driver_register(&pata_s3c_driver);
+}
+
+static void __exit pata_s3c_exit(void)
+{
+ platform_driver_unregister(&pata_s3c_driver);
+}
+
+module_init(pata_s3c_init);
+module_exit(pata_s3c_exit);
+
+MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>");
+MODULE_DESCRIPTION("low-level driver for Samsung PATA controller");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
--
1.6.2.5
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:22 ` [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver Kukjin Kim
@ 2010-05-27 8:43 ` Ben Dooks
2010-06-02 2:37 ` Kukjin Kim
2010-05-27 8:43 ` Jassi Brar
` (2 subsequent siblings)
3 siblings, 1 reply; 24+ messages in thread
From: Ben Dooks @ 2010-05-27 8:43 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 05:22:04PM +0900, Kukjin Kim wrote:
> From: Abhilash Kesavan <a.kesavan@samsung.com>
>
> Adds support for the Samsung PATA controller. This driver is based on the
> Libata subsystem and references the earlier patches sent for IDE subsystem.
>
> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> drivers/ata/Kconfig | 9 +
> drivers/ata/Makefile | 1 +
> drivers/ata/pata_samsung.c | 591 ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 601 insertions(+), 0 deletions(-)
> create mode 100644 drivers/ata/pata_samsung.c
>
> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> index e68541f..ce40f66 100644
> --- a/drivers/ata/Kconfig
> +++ b/drivers/ata/Kconfig
> @@ -640,6 +640,15 @@ config PATA_RZ1000
>
> If unsure, say N.
>
> +config PATA_SAMSUNG
> + tristate "Samsung SoC PATA support"
> + depends on S3C_DEV_IDE
> + help
> + This option enables basic support for Samsung's S3C/S5P board
> + PATA controllers via the new ATA layer
> +
> + If unsure, say N.
> +
> config PATA_SC1200
> tristate "SC1200 PATA support"
> depends on PCI
> diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
> index d0a93c4..0b6d29a 100644
> --- a/drivers/ata/Makefile
> +++ b/drivers/ata/Makefile
> @@ -62,6 +62,7 @@ obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
> obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
> obj-$(CONFIG_PATA_RDC) += pata_rdc.o
> obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
> +obj-$(CONFIG_PATA_SAMSUNG) += pata_samsung.o
do you want to call it pata_samsung_soc.o instead, in case samsung make
otehr types of pata controller?
> obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
> obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
> obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
> diff --git a/drivers/ata/pata_samsung.c b/drivers/ata/pata_samsung.c
> new file mode 100644
> index 0000000..14381e4
> --- /dev/null
> +++ b/drivers/ata/pata_samsung.c
> @@ -0,0 +1,591 @@
> +/* linux/drivers/ata/pata_samsung.c
> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + *
> + * PATA driver for Samsung SoC's.
SoCs.
> + * Supports CF Interface in True IDE mode. Currently only PIO mode has been
> + * implemented; UDMA support has to be added.
> + *
> + * Based on:
> + * PATA driver for AT91SAM9260 Static Memory Controller
> + * PATA driver for Toshiba SCC controller
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation.
> +*/
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/clk.h>
> +#include <linux/libata.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <plat/ata.h>
> +#include <plat/regs-ata.h>
> +
> +#define DRV_NAME "pata_samsung"
> +#define DRV_VERSION "0.1"
> +
> +enum s3c_cpu_type {
> + TYPE_S3C6400,
> + TYPE_S5PC100,
> + TYPE_S5PV210,
> +};
> +
> +/*
> + * struct s3c_ide_info - S3C PATA instance.
> + * @clk: The clock resource for this controller.
> + * @ide_addr: The area mapped for the hardware registers.
> + * @sfr_addr: The area mapped for the special function registers.
> + * @irq: The IRQ number we are using.
> + * @cpu_type: The exact type of this controller.
> + * @fifo_status_reg: The ATA_FIFO_STATUS register offset.
> + */
> +struct s3c_ide_info {
> + struct clk *clk;
> + void __iomem *ide_addr;
> + void __iomem *sfr_addr;
> + unsigned int irq;
> + enum s3c_cpu_type cpu_type;
> + unsigned int fifo_status_reg;
> +};
> +
> +static unsigned long piotime[5];
> +
> +static void pata_s3c_set_endian(void *s3c_ide_regbase, u8 mode)
> +{
> + u32 reg = readl(s3c_ide_regbase + S3C_ATA_CFG);
> + reg = mode ? (reg & ~S3C_ATA_CFG_SWAP) : (reg | S3C_ATA_CFG_SWAP);
> + writel(reg, s3c_ide_regbase + S3C_ATA_CFG);
> +}
> +
> +static void pata_s3c_tune_chipset(struct s3c_ide_info *info, u8 ide_mode)
> +{
> + ulong ata_cfg = readl(info->ide_addr + S3C_ATA_CFG);
> +
> + /* IORDY is enabled for modes > PIO2 */
> + if (XFER_PIO_0 <= ide_mode && ide_mode <= XFER_PIO_4) {
> +
> + switch (ide_mode) {
> + case XFER_PIO_0:
> + case XFER_PIO_1:
> + case XFER_PIO_2:
> + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
> + break;
> + case XFER_PIO_3:
> + case XFER_PIO_4:
> + ata_cfg |= S3C_ATA_CFG_IORDYEN;
> + break;
> + }
> +
> + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> + writel(piotime[ide_mode - XFER_PIO_0],
> + info->ide_addr + S3C_ATA_PIO_TIME);
> + } else {
> + /* Default to PIO0 */
> + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
technically no need to ().
> + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> + writel(piotime[0], info->ide_addr + S3C_ATA_PIO_TIME);
> + }
> +}
> +
> +static void
> +pata_s3c_set_piomode(struct ata_port *ap, struct ata_device *adev)
> +{
> + struct s3c_ide_info *info = ap->host->private_data;
> +
> + /* Configure IORDY based on PIO mode and also set the timing value */
> + pata_s3c_tune_chipset(info, adev->pio_mode);
> +}
> +
> +/*
> + * Waits until the IDE controller is able to perform next read/write
> + * operation to the disk. Needed for 64XX series boards only.
> + */
> +static int wait_for_host_ready(struct s3c_ide_info *info)
> +{
> + ulong timeout;
> +
> + /* wait for maximum of 20 msec */
> + timeout = jiffies + msecs_to_jiffies(20);
> + while (time_before(jiffies, timeout)) {
> + if ((readl(info->ide_addr + info->fifo_status_reg) >> 28) == 0)
> + return 0;
> + }
> + return -EBUSY;
> +}
> +
> +/*
> + * Writes to one of the task file registers.
> + */
> +static void ata_outb(struct ata_host *host, u8 addr, void __iomem *reg)
> +{
> + struct s3c_ide_info *info = host->private_data;
> +
> + wait_for_host_ready(info);
> + __raw_writeb(addr, reg);
> +}
probably want writeb() here. you've used the non __raw versions elsewhere.
> +/*
> + * Reads from one of the task file registers.
> + */
> +static u8 ata_inb(struct ata_host *host, void __iomem *reg)
> +{
> + struct s3c_ide_info *info = host->private_data;
> + u8 temp;
> +
> + wait_for_host_ready(info);
> + temp = __raw_readb(reg);
> + wait_for_host_ready(info);
> + temp = __raw_readb(info->ide_addr + S3C_ATA_PIO_RDATA);
> + return temp;
> +}
> +
> +/*
> + * pata_s3c_tf_load - send taskfile registers to host controller
> + */
> +static void pata_s3c_tf_load(struct ata_port *ap,
> + const struct ata_taskfile *tf)
> +{
> + struct ata_ioports *ioaddr = &ap->ioaddr;
> + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
> +
> + if (tf->ctl != ap->last_ctl) {
> + if (ioaddr->ctl_addr)
> + ata_outb(ap->host, tf->ctl, ioaddr->ctl_addr);
> + ap->last_ctl = tf->ctl;
> + ata_wait_idle(ap);
> + }
> +
> + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
> + WARN_ON_ONCE(!ioaddr->ctl_addr);
> + ata_outb(ap->host, tf->hob_feature, ioaddr->feature_addr);
> + ata_outb(ap->host, tf->hob_nsect, ioaddr->nsect_addr);
> + ata_outb(ap->host, tf->hob_lbal, ioaddr->lbal_addr);
> + ata_outb(ap->host, tf->hob_lbam, ioaddr->lbam_addr);
> + ata_outb(ap->host, tf->hob_lbah, ioaddr->lbah_addr);
> + }
> +
> + if (is_addr) {
> + ata_outb(ap->host, tf->feature, ioaddr->feature_addr);
> + ata_outb(ap->host, tf->nsect, ioaddr->nsect_addr);
> + ata_outb(ap->host, tf->lbal, ioaddr->lbal_addr);
> + ata_outb(ap->host, tf->lbam, ioaddr->lbam_addr);
> + ata_outb(ap->host, tf->lbah, ioaddr->lbah_addr);
> + }
> +
> + if (tf->flags & ATA_TFLAG_DEVICE)
> + ata_outb(ap->host, tf->device, ioaddr->device_addr);
> +
> + ata_wait_idle(ap);
> +}
> +
> +/*
> + * pata_s3c_tf_read - input device's ATA taskfile shadow registers
> + */
> +static void pata_s3c_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
> +{
> + struct ata_ioports *ioaddr = &ap->ioaddr;
> +
> + tf->command = ata_sff_check_status(ap);
> + tf->feature = ata_inb(ap->host, ioaddr->error_addr);
> + tf->nsect = ata_inb(ap->host, ioaddr->nsect_addr);
> + tf->lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> + tf->lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> + tf->lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> + tf->device = ata_inb(ap->host, ioaddr->device_addr);
> +
> + if (tf->flags & ATA_TFLAG_LBA48) {
> + if (likely(ioaddr->ctl_addr)) {
> + iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
> + tf->hob_feature = ata_inb(ap->host, ioaddr->error_addr);
> + tf->hob_nsect = ata_inb(ap->host, ioaddr->nsect_addr);
> + tf->hob_lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> + tf->hob_lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> + tf->hob_lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> + iowrite8(tf->ctl, ioaddr->ctl_addr);
> + ap->last_ctl = tf->ctl;
> + } else
> + WARN_ON_ONCE(1);
> + }
> +}
> +
> +/*
> + * pata_s3c_exec_command - issue ATA command to host controller
> + */
> +static void pata_s3c_exec_command(struct ata_port *ap,
> + const struct ata_taskfile *tf)
> +{
> + ata_outb(ap->host, tf->command, ap->ioaddr.command_addr);
> + ata_sff_pause(ap);
> +}
> +
> +/*
> + * pata_s3c_check_status - Read device status register
> + */
> +static u8 pata_s3c_check_status(struct ata_port *ap)
> +{
> + return ata_inb(ap->host, ap->ioaddr.status_addr);
> +}
> +
> +/*
> + * pata_s3c_data_xfer - Transfer data by PIO
> + */
> +unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char *buf,
> + unsigned int buflen, int rw)
> +{
> + struct ata_port *ap = dev->link->ap;
> + struct s3c_ide_info *info = ap->host->private_data;
> + void __iomem *data_addr = ap->ioaddr.data_addr;
> + unsigned int words = buflen >> 1, i;
> + u16 *temp_addr = (u16 *)buf;
hmm, how about calling it data_ptr instead of temp_addr?
> + if (rw == READ) {
> + for (i = 0; i < words; i++, temp_addr++) {
> + wait_for_host_ready(info);
> + *temp_addr = __raw_readw(data_addr);
> + wait_for_host_ready(info);
> + *temp_addr = __raw_readw(info->ide_addr
> + + S3C_ATA_PIO_RDATA)
think you want readw() here, please ensure consitency.
this also look a bit weird, you are writing to *temp_addr twice,
could you simply dicscard the first read?
note, you say s3c64xx only needs wait_for_host_ready() but you
always call it?
> + }
> + } else {
> + for (i = 0; i < words; i++, temp_addr++) {
> + wait_for_host_ready(info);
> + writel(*temp_addr, data_addr);
> + }
> + }
> +
> + return words << 1;
> +}
> +
> +static struct scsi_host_template pata_s3c_sht = {
> + ATA_PIO_SHT(DRV_NAME),
> +};
> +
> +static struct ata_port_operations pata_s3c_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .sff_check_status = pata_s3c_check_status,
> + .sff_tf_load = pata_s3c_tf_load,
> + .sff_tf_read = pata_s3c_tf_read,
> + .sff_data_xfer = pata_s3c_data_xfer,
> + .sff_exec_command = pata_s3c_exec_command,
> + .qc_prep = ata_noop_qc_prep,
> + .set_piomode = pata_s3c_set_piomode,
> +};
> +
> +static struct ata_port_operations pata_s5p_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .qc_prep = ata_noop_qc_prep,
> + .set_piomode = pata_s3c_set_piomode,
> +};
> +
> +static void pata_s3c_enable(void *s3c_ide_regbase, u8 state)
> +{
> + u32 temp = readl(s3c_ide_regbase + S3C_ATA_CTRL);
> + temp = state ? temp | 1 : temp & ~1;
you might want ()around the temp |1 and temp & ~1
> + writel(temp, s3c_ide_regbase + S3C_ATA_CTRL);
> +}
> +
> +static irqreturn_t pata_s3c_irq(int irq, void *dev_instance)
> +{
> + struct ata_host *host = dev_instance;
> + struct s3c_ide_info *info = host->private_data;
> + u32 reg;
> +
> + reg = readl(info->ide_addr + S3C_ATA_IRQ);
> + writel(reg, info->ide_addr + S3C_ATA_IRQ);
> +
> + return ata_sff_interrupt(irq, dev_instance);
> +}
> +
> +static void pata_s3c_setup_timing(struct s3c_ide_info *info)
> +{
> + uint t1, t2, teoc, i;
> +
> + uint pio_t1[5] = { 70, 50, 30, 30, 25 };
> + uint pio_t2[5] = { 290, 290, 290, 80, 70 };
> + uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
> +
> + ulong cycle_time = (uint) (1000000000 / clk_get_rate(info->clk));
ulong and uinit? surely pick one. you might want to keep UL and cajhnge
1000000000 to 1000000000UL
> + for (i = 0; i < 5; i++) {
> + t1 = (pio_t1[i] / cycle_time) & 0x0f;
> + t2 = (pio_t2[i] / cycle_time) & 0xff;
> + teoc = (pio_teoc[i] / cycle_time) & 0xff;
> + piotime[i] = (teoc << 12) | (t2 << 4) | t1;
> + }
> +}
> +
> +static void pata_s3c_hwinit(struct s3c_ide_info *info,
> + struct s3c_ide_platdata *pdata)
> +{
> + /* Select true-ide as the internal operating mode*/
> + if (pdata && (pdata->cfg_mode))
> + pdata->cfg_mode(info->sfr_addr);
> +
> + switch (info->cpu_type) {
> + case TYPE_S3C6400:
> + /* Configure as big endian and enable the i/f*/
> + pata_s3c_set_endian(info->ide_addr, 1);
> + pata_s3c_enable(info->ide_addr, 1);
> + mdelay(100);
> +
> + /* Remove IRQ Status */
> + writel(0x1f, info->ide_addr + S3C_ATA_IRQ);
> + writel(0x1b, info->ide_addr + S3C_ATA_IRQ_MSK);
> + break;
> +
> + case TYPE_S5PV210:
> + case TYPE_S5PC100:
> + /* Configure as little endian and enable the i/f */
> + pata_s3c_set_endian(info->ide_addr, 0);
> + pata_s3c_enable(info->ide_addr, 1);
> + mdelay(100);
> +
> + /* Remove IRQ Status */
> + writel(0x3f, info->ide_addr + S3C_ATA_IRQ);
> + writel(0x3f, info->ide_addr + S3C_ATA_IRQ_MSK);
> + break;
> +
> + default:
> + BUG();
> + }
> +}
> +
> +static int __devinit pata_s3c_probe(struct platform_device *pdev)
> +{
> + struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
> + struct device *dev = &pdev->dev;
> + struct s3c_ide_info *info;
> + struct resource *res;
> + struct ata_port *ap;
> + struct ata_host *host;
> + enum s3c_cpu_type cpu_type;
> + int ret;
> +
> + cpu_type = platform_get_device_id(pdev)->driver_data;
> +
> + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> + if (!info) {
> + dev_err(dev, "failed to allocate memory for device data\n");
> + return -ENOMEM;
> + }
> +
> + info->irq = platform_get_irq(pdev, 0);
> + if (info->irq < 0) {
> + dev_err(dev, "could not obtain irq number\n");
> + ret = -ENODEV;
> + goto release_device_mem;
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (res == NULL) {
> + dev_err(dev, "failed to get mem resource\n");
> + ret = -ENODEV;
if i remeber correctly, you don't want to be returning -ENODEV as
it will be ignored by the uper layers.
> + goto release_device_mem;
> + }
> +
> + info->ide_addr = devm_ioremap(dev,
> + res->start, res->end - res->start + 1);
resource_size() is your friend here.
> + if (!info->ide_addr) {
> + dev_err(dev, "failed to map IO base address\n");
> + ret = -ENOMEM;
> + goto release_mem;
> + }
> +
> + info->clk = clk_get(&pdev->dev, "cfcon");
need to do something about using explicit names here, should be clk_get(, NULL)
> + if (IS_ERR(info->clk)) {
> + dev_err(dev, "failed to get access to cf controller clock\n");
> + ret = PTR_ERR(info->clk);
> + info->clk = NULL;
> + goto unmap;
> + }
> +
> + if (clk_enable(info->clk)) {
> + dev_err(dev, "failed to enable clock source.\n");
> + goto clkerr;
> + }
> +
> + /* init ata host */
> + host = ata_host_alloc(dev, 1);
> + if (!host) {
> + dev_err(dev, "failed to allocate ide host\n");
> + ret = -ENOMEM;
> + goto stop_clk;
> + }
> +
> + ap = host->ports[0];
> + ap->flags |= ATA_FLAG_MMIO;
> + ap->pio_mask = ATA_PIO4;
> +
> + if (cpu_type == TYPE_S3C6400) {
> + ap->ops = &pata_s3c_port_ops;
> + info->sfr_addr = info->ide_addr + 0x1800;
> + info->ide_addr = info->ide_addr + 0x1900;
> + info->fifo_status_reg = 0x94;
> + } else if (cpu_type == TYPE_S5PC100) {
> + ap->ops = &pata_s5p_port_ops;
> + info->sfr_addr = info->ide_addr + 0x1800;
> + info->ide_addr = info->ide_addr + 0x1900;
> + info->fifo_status_reg = 0x84;
> + } else {
> + ap->ops = &pata_s5p_port_ops;
> + info->fifo_status_reg = 0x84;
> + }
> +
> + info->cpu_type = cpu_type;
> +
> + if (!(info->irq)) {
> + ap->flags |= ATA_FLAG_PIO_POLLING;
> + ata_port_desc(ap, "no IRQ, using PIO polling\n");
> + }
> +
> + ap->ioaddr.cmd_addr = info->ide_addr + S3C_ATA_CMD;
> + ap->ioaddr.data_addr = info->ide_addr + S3C_ATA_PIO_DTR;
> + ap->ioaddr.error_addr = info->ide_addr + S3C_ATA_PIO_FED;
> + ap->ioaddr.feature_addr = info->ide_addr + S3C_ATA_PIO_FED;
> + ap->ioaddr.nsect_addr = info->ide_addr + S3C_ATA_PIO_SCR;
> + ap->ioaddr.lbal_addr = info->ide_addr + S3C_ATA_PIO_LLR;
> + ap->ioaddr.lbam_addr = info->ide_addr + S3C_ATA_PIO_LMR;
> + ap->ioaddr.lbah_addr = info->ide_addr + S3C_ATA_PIO_LHR;
> + ap->ioaddr.device_addr = info->ide_addr + S3C_ATA_PIO_DVR;
> + ap->ioaddr.status_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> + ap->ioaddr.command_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> + ap->ioaddr.altstatus_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> + ap->ioaddr.ctl_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> +
> +
> + ata_port_desc(ap, "mmio cmd 0x%llx ",
> + (unsigned long long)res->start);
> +
> + host->private_data = info;
> +
> + /* Calculates timing parameters for PIO mode */
> + pata_s3c_setup_timing(info);
> +
> + if (pdata && (pdata->setup_gpio))
no need for () around the pdata->setup_gpio
> + pdata->setup_gpio();
> +
> + /* Set endianness and enable the interface */
> + pata_s3c_hwinit(info, pdata);
> +
> + return ata_host_activate(host, info->irq ? info->irq : 0,
> + info->irq ? pata_s3c_irq : NULL,
> + IRQF_DISABLED, &pata_s3c_sht);
do you really need to run with IRQs disabled?
> + dev_set_drvdata(&pdev->dev, host);
> +
> +stop_clk:
> + clk_disable(info->clk);
> +clkerr:
> + clk_put(info->clk);
> +unmap:
> + devm_iounmap(dev, info->ide_addr);
> +release_mem:
> + release_mem_region(res->start, res->end - res->start + 1);
> +release_device_mem:
> + kfree(info);
> +return ret;
> +}
> +
> +static int __devexit pata_s3c_remove(struct platform_device *pdev)
> +{
> + struct ata_host *host = dev_get_drvdata(&pdev->dev);
> + struct s3c_ide_info *info;
> + struct resource *res;
> +
> + if (!host)
> + return 0;
> + info = host->private_data;
> +
> + ata_host_detach(host);
> +
> + devm_iounmap(&pdev->dev, info->ide_addr);
> + clk_disable(info->clk);
> + clk_put(info->clk);
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + release_mem_region(res->start, res->end - res->start + 1);
> + kfree(info);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int pata_s3c_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + struct ata_host *host = dev_get_drvdata(&pdev->dev);
> + if (host)
> + return ata_host_suspend(host, state);
> + else
> + return 0;
> +}
> +
> +static int pata_s3c_resume(struct platform_device *pdev)
> +{
> + struct ata_host *host = dev_get_drvdata(&pdev->dev);
> + struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
> + struct s3c_ide_info *info;
> +
> + info = host->private_data;
> +
> + if (host) {
> + pata_s3c_hwinit(info, pdata);
> + ata_host_resume(host);
> + }
> +
> + return 0;
> +}
> +#endif
> +
> +/* driver device registration */
> +static struct platform_device_id pata_s3c_driver_ids[] = {
> + {
> + .name = "s3c6400-pata",
> + .driver_data = TYPE_S3C6400,
> + }, {
> + .name = "s5pc100-pata",
> + .driver_data = TYPE_S5PC100,
> + }, {
> + .name = "s5pv210-pata",
> + .driver_data = TYPE_S5PV210,
> + },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(platform, pata_s3c_driver_ids);
> +
> +static struct platform_driver pata_s3c_driver = {
> + .probe = pata_s3c_probe,
> + .remove = __devexit_p(pata_s3c_remove),
> + .id_table = pata_s3c_driver_ids,
> + .driver = {
> + .name = DRV_NAME,
> + .owner = THIS_MODULE,
> + },
> +#ifdef CONFIG_PM
> + .suspend = pata_s3c_suspend,
> + .resume = pata_s3c_resume,
> +#endif
please look at using the new pm_ops.
> +};
> +
> +static int __init pata_s3c_init(void)
> +{
> + return platform_driver_register(&pata_s3c_driver);
> +}
> +
> +static void __exit pata_s3c_exit(void)
> +{
> + platform_driver_unregister(&pata_s3c_driver);
> +}
> +
> +module_init(pata_s3c_init);
> +module_exit(pata_s3c_exit);
> +
> +MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>");
> +MODULE_DESCRIPTION("low-level driver for Samsung PATA controller");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION(DRV_VERSION);
> --
> 1.6.2.5
not bad, needs some cleanup.
--
Ben
Q: What's a light-year?
A: One-third less calories than a regular year.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:43 ` Ben Dooks
@ 2010-06-02 2:37 ` Kukjin Kim
0 siblings, 0 replies; 24+ messages in thread
From: Kukjin Kim @ 2010-06-02 2:37 UTC (permalink / raw)
To: linux-arm-kernel
Ben Dooks wrote:
>
> On Thu, May 27, 2010 at 05:22:04PM +0900, Kukjin Kim wrote:
> > From: Abhilash Kesavan <a.kesavan@samsung.com>
> >
> > Adds support for the Samsung PATA controller. This driver is based on the
> > Libata subsystem and references the earlier patches sent for IDE
subsystem.
> >
> > Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> > drivers/ata/Kconfig | 9 +
> > drivers/ata/Makefile | 1 +
> > drivers/ata/pata_samsung.c | 591
> ++++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 601 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/ata/pata_samsung.c
> >
> > diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> > index e68541f..ce40f66 100644
> > --- a/drivers/ata/Kconfig
> > +++ b/drivers/ata/Kconfig
> > @@ -640,6 +640,15 @@ config PATA_RZ1000
> >
> > If unsure, say N.
> >
> > +config PATA_SAMSUNG
> > + tristate "Samsung SoC PATA support"
> > + depends on S3C_DEV_IDE
> > + help
> > + This option enables basic support for Samsung's S3C/S5P board
> > + PATA controllers via the new ATA layer
> > +
> > + If unsure, say N.
> > +
> > config PATA_SC1200
> > tristate "SC1200 PATA support"
> > depends on PCI
> > diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
> > index d0a93c4..0b6d29a 100644
> > --- a/drivers/ata/Makefile
> > +++ b/drivers/ata/Makefile
> > @@ -62,6 +62,7 @@ obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
> > obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
> > obj-$(CONFIG_PATA_RDC) += pata_rdc.o
> > obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
> > +obj-$(CONFIG_PATA_SAMSUNG) += pata_samsung.o
> do you want to call it pata_samsung_soc.o instead, in case samsung make
> otehr types of pata controller?
Will change the name to pata_samsung_cf.
> > obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
> > obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
> > obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
> > diff --git a/drivers/ata/pata_samsung.c b/drivers/ata/pata_samsung.c
> > new file mode 100644
> > index 0000000..14381e4
> > --- /dev/null
> > +++ b/drivers/ata/pata_samsung.c
> > @@ -0,0 +1,591 @@
> > +/* linux/drivers/ata/pata_samsung.c
> > + *
> > + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> > + * http://www.samsung.com
> > + *
> > + * PATA driver for Samsung SoC's.
> SoCs.
OK
> > + * Supports CF Interface in True IDE mode. Currently only PIO mode has
been
> > + * implemented; UDMA support has to be added.
> > + *
> > + * Based on:
> > + * PATA driver for AT91SAM9260 Static Memory Controller
> > + * PATA driver for Toshiba SCC controller
> > + *
> > + * This program is free software; you can redistribute it and/or modify
it
> > + * under the terms of the GNU General Public License version 2
> > + * as published by the Free Software Foundation.
> > +*/
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/init.h>
> > +#include <linux/clk.h>
> > +#include <linux/libata.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +
> > +#include <plat/ata.h>
> > +#include <plat/regs-ata.h>
> > +
> > +#define DRV_NAME "pata_samsung"
> > +#define DRV_VERSION "0.1"
> > +
> > +enum s3c_cpu_type {
> > + TYPE_S3C6400,
> > + TYPE_S5PC100,
> > + TYPE_S5PV210,
> > +};
> > +
> > +/*
> > + * struct s3c_ide_info - S3C PATA instance.
> > + * @clk: The clock resource for this controller.
> > + * @ide_addr: The area mapped for the hardware registers.
> > + * @sfr_addr: The area mapped for the special function registers.
> > + * @irq: The IRQ number we are using.
> > + * @cpu_type: The exact type of this controller.
> > + * @fifo_status_reg: The ATA_FIFO_STATUS register offset.
> > + */
> > +struct s3c_ide_info {
> > + struct clk *clk;
> > + void __iomem *ide_addr;
> > + void __iomem *sfr_addr;
> > + unsigned int irq;
> > + enum s3c_cpu_type cpu_type;
> > + unsigned int fifo_status_reg;
> > +};
> > +
> > +static unsigned long piotime[5];
> > +
> > +static void pata_s3c_set_endian(void *s3c_ide_regbase, u8 mode)
> > +{
> > + u32 reg = readl(s3c_ide_regbase + S3C_ATA_CFG);
> > + reg = mode ? (reg & ~S3C_ATA_CFG_SWAP) : (reg |
> S3C_ATA_CFG_SWAP);
> > + writel(reg, s3c_ide_regbase + S3C_ATA_CFG);
> > +}
> > +
> > +static void pata_s3c_tune_chipset(struct s3c_ide_info *info, u8
ide_mode)
> > +{
> > + ulong ata_cfg = readl(info->ide_addr + S3C_ATA_CFG);
> > +
> > + /* IORDY is enabled for modes > PIO2 */
> > + if (XFER_PIO_0 <= ide_mode && ide_mode <= XFER_PIO_4) {
> > +
> > + switch (ide_mode) {
> > + case XFER_PIO_0:
> > + case XFER_PIO_1:
> > + case XFER_PIO_2:
> > + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
> > + break;
> > + case XFER_PIO_3:
> > + case XFER_PIO_4:
> > + ata_cfg |= S3C_ATA_CFG_IORDYEN;
> > + break;
> > + }
> > +
> > + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> > + writel(piotime[ide_mode - XFER_PIO_0],
> > + info->ide_addr + S3C_ATA_PIO_TIME);
> > + } else {
> > + /* Default to PIO0 */
> > + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
> technically no need to ().
OK
> > + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> > + writel(piotime[0], info->ide_addr + S3C_ATA_PIO_TIME);
> > + }
> > +}
> > +
> > +static void
> > +pata_s3c_set_piomode(struct ata_port *ap, struct ata_device *adev)
> > +{
> > + struct s3c_ide_info *info = ap->host->private_data;
> > +
> > + /* Configure IORDY based on PIO mode and also set the timing value */
> > + pata_s3c_tune_chipset(info, adev->pio_mode);
> > +}
> > +
> > +/*
> > + * Waits until the IDE controller is able to perform next read/write
> > + * operation to the disk. Needed for 64XX series boards only.
> > + */
> > +static int wait_for_host_ready(struct s3c_ide_info *info)
> > +{
> > + ulong timeout;
> > +
> > + /* wait for maximum of 20 msec */
> > + timeout = jiffies + msecs_to_jiffies(20);
> > + while (time_before(jiffies, timeout)) {
> > + if ((readl(info->ide_addr + info->fifo_status_reg) >> 28) ==
0)
> > + return 0;
> > + }
> > + return -EBUSY;
> > +}
> > +
> > +/*
> > + * Writes to one of the task file registers.
> > + */
> > +static void ata_outb(struct ata_host *host, u8 addr, void __iomem *reg)
> > +{
> > + struct s3c_ide_info *info = host->private_data;
> > +
> > + wait_for_host_ready(info);
> > + __raw_writeb(addr, reg);
> > +}
>
> probably want writeb() here. you've used the non __raw versions elsewhere.
>
OK
> > +/*
> > + * Reads from one of the task file registers.
> > + */
> > +static u8 ata_inb(struct ata_host *host, void __iomem *reg)
> > +{
> > + struct s3c_ide_info *info = host->private_data;
> > + u8 temp;
> > +
> > + wait_for_host_ready(info);
> > + temp = __raw_readb(reg);
> > + wait_for_host_ready(info);
> > + temp = __raw_readb(info->ide_addr + S3C_ATA_PIO_RDATA);
> > + return temp;
> > +}
> > +
> > +/*
> > + * pata_s3c_tf_load - send taskfile registers to host controller
> > + */
> > +static void pata_s3c_tf_load(struct ata_port *ap,
> > + const struct ata_taskfile *tf)
> > +{
> > + struct ata_ioports *ioaddr = &ap->ioaddr;
> > + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
> > +
> > + if (tf->ctl != ap->last_ctl) {
> > + if (ioaddr->ctl_addr)
> > + ata_outb(ap->host, tf->ctl, ioaddr->ctl_addr);
> > + ap->last_ctl = tf->ctl;
> > + ata_wait_idle(ap);
> > + }
> > +
> > + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
> > + WARN_ON_ONCE(!ioaddr->ctl_addr);
> > + ata_outb(ap->host, tf->hob_feature, ioaddr->feature_addr);
> > + ata_outb(ap->host, tf->hob_nsect, ioaddr->nsect_addr);
> > + ata_outb(ap->host, tf->hob_lbal, ioaddr->lbal_addr);
> > + ata_outb(ap->host, tf->hob_lbam, ioaddr->lbam_addr);
> > + ata_outb(ap->host, tf->hob_lbah, ioaddr->lbah_addr);
> > + }
> > +
> > + if (is_addr) {
> > + ata_outb(ap->host, tf->feature, ioaddr->feature_addr);
> > + ata_outb(ap->host, tf->nsect, ioaddr->nsect_addr);
> > + ata_outb(ap->host, tf->lbal, ioaddr->lbal_addr);
> > + ata_outb(ap->host, tf->lbam, ioaddr->lbam_addr);
> > + ata_outb(ap->host, tf->lbah, ioaddr->lbah_addr);
> > + }
> > +
> > + if (tf->flags & ATA_TFLAG_DEVICE)
> > + ata_outb(ap->host, tf->device, ioaddr->device_addr);
> > +
> > + ata_wait_idle(ap);
> > +}
> > +
> > +/*
> > + * pata_s3c_tf_read - input device's ATA taskfile shadow registers
> > + */
> > +static void pata_s3c_tf_read(struct ata_port *ap, struct ata_taskfile
*tf)
> > +{
> > + struct ata_ioports *ioaddr = &ap->ioaddr;
> > +
> > + tf->command = ata_sff_check_status(ap);
> > + tf->feature = ata_inb(ap->host, ioaddr->error_addr);
> > + tf->nsect = ata_inb(ap->host, ioaddr->nsect_addr);
> > + tf->lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> > + tf->lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> > + tf->lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> > + tf->device = ata_inb(ap->host, ioaddr->device_addr);
> > +
> > + if (tf->flags & ATA_TFLAG_LBA48) {
> > + if (likely(ioaddr->ctl_addr)) {
> > + iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
> > + tf->hob_feature = ata_inb(ap->host,
ioaddr->error_addr);
> > + tf->hob_nsect = ata_inb(ap->host,
ioaddr->nsect_addr);
> > + tf->hob_lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> > + tf->hob_lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> > + tf->hob_lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> > + iowrite8(tf->ctl, ioaddr->ctl_addr);
> > + ap->last_ctl = tf->ctl;
> > + } else
> > + WARN_ON_ONCE(1);
> > + }
> > +}
> > +
> > +/*
> > + * pata_s3c_exec_command - issue ATA command to host controller
> > + */
> > +static void pata_s3c_exec_command(struct ata_port *ap,
> > + const struct ata_taskfile *tf)
> > +{
> > + ata_outb(ap->host, tf->command, ap->ioaddr.command_addr);
> > + ata_sff_pause(ap);
> > +}
> > +
> > +/*
> > + * pata_s3c_check_status - Read device status register
> > + */
> > +static u8 pata_s3c_check_status(struct ata_port *ap)
> > +{
> > + return ata_inb(ap->host, ap->ioaddr.status_addr);
> > +}
> > +
> > +/*
> > + * pata_s3c_data_xfer - Transfer data by PIO
> > + */
> > +unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char
*buf,
> > + unsigned int buflen, int rw)
> > +{
> > + struct ata_port *ap = dev->link->ap;
> > + struct s3c_ide_info *info = ap->host->private_data;
> > + void __iomem *data_addr = ap->ioaddr.data_addr;
> > + unsigned int words = buflen >> 1, i;
> > + u16 *temp_addr = (u16 *)buf;
>
> hmm, how about calling it data_ptr instead of temp_addr?
>
OK
> > + if (rw == READ) {
> > + for (i = 0; i < words; i++, temp_addr++) {
> > + wait_for_host_ready(info);
> > + *temp_addr = __raw_readw(data_addr);
> > + wait_for_host_ready(info);
> > + *temp_addr = __raw_readw(info->ide_addr
> > + + S3C_ATA_PIO_RDATA)
>
> think you want readw() here, please ensure consitency.
>
> this also look a bit weird, you are writing to *temp_addr twice,
> could you simply dicscard the first read?
>
> note, you say s3c64xx only needs wait_for_host_ready() but you
> always call it?
>
wait_for_host_ready is called via pata_s3c_port_ops which is only for 64xx.
> > + }
> > + } else {
> > + for (i = 0; i < words; i++, temp_addr++) {
> > + wait_for_host_ready(info);
> > + writel(*temp_addr, data_addr);
> > + }
> > + }
> > +
> > + return words << 1;
> > +}
> > +
> > +static struct scsi_host_template pata_s3c_sht = {
> > + ATA_PIO_SHT(DRV_NAME),
> > +};
> > +
> > +static struct ata_port_operations pata_s3c_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .sff_check_status = pata_s3c_check_status,
> > + .sff_tf_load = pata_s3c_tf_load,
> > + .sff_tf_read = pata_s3c_tf_read,
> > + .sff_data_xfer = pata_s3c_data_xfer,
> > + .sff_exec_command = pata_s3c_exec_command,
> > + .qc_prep = ata_noop_qc_prep,
> > + .set_piomode = pata_s3c_set_piomode,
> > +};
> > +
> > +static struct ata_port_operations pata_s5p_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .qc_prep = ata_noop_qc_prep,
> > + .set_piomode = pata_s3c_set_piomode,
> > +};
> > +
> > +static void pata_s3c_enable(void *s3c_ide_regbase, u8 state)
> > +{
> > + u32 temp = readl(s3c_ide_regbase + S3C_ATA_CTRL);
> > + temp = state ? temp | 1 : temp & ~1;
> you might want ()around the temp |1 and temp & ~1
OK
> > + writel(temp, s3c_ide_regbase + S3C_ATA_CTRL);
> > +}
> > +
> > +static irqreturn_t pata_s3c_irq(int irq, void *dev_instance)
> > +{
> > + struct ata_host *host = dev_instance;
> > + struct s3c_ide_info *info = host->private_data;
> > + u32 reg;
> > +
> > + reg = readl(info->ide_addr + S3C_ATA_IRQ);
> > + writel(reg, info->ide_addr + S3C_ATA_IRQ);
> > +
> > + return ata_sff_interrupt(irq, dev_instance);
> > +}
> > +
> > +static void pata_s3c_setup_timing(struct s3c_ide_info *info)
> > +{
> > + uint t1, t2, teoc, i;
> > +
> > + uint pio_t1[5] = { 70, 50, 30, 30, 25 };
> > + uint pio_t2[5] = { 290, 290, 290, 80, 70 };
> > + uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
> > +
> > + ulong cycle_time = (uint) (1000000000 / clk_get_rate(info->clk));
>
> ulong and uinit? surely pick one. you might want to keep UL and cajhnge
> 1000000000 to 1000000000UL
>
OK
> > + for (i = 0; i < 5; i++) {
> > + t1 = (pio_t1[i] / cycle_time) & 0x0f;
> > + t2 = (pio_t2[i] / cycle_time) & 0xff;
> > + teoc = (pio_teoc[i] / cycle_time) & 0xff;
> > + piotime[i] = (teoc << 12) | (t2 << 4) | t1;
> > + }
> > +}
> > +
> > +static void pata_s3c_hwinit(struct s3c_ide_info *info,
> > + struct s3c_ide_platdata *pdata)
> > +{
> > + /* Select true-ide as the internal operating mode*/
> > + if (pdata && (pdata->cfg_mode))
> > + pdata->cfg_mode(info->sfr_addr);
> > +
> > + switch (info->cpu_type) {
> > + case TYPE_S3C6400:
> > + /* Configure as big endian and enable the i/f*/
> > + pata_s3c_set_endian(info->ide_addr, 1);
> > + pata_s3c_enable(info->ide_addr, 1);
> > + mdelay(100);
> > +
> > + /* Remove IRQ Status */
> > + writel(0x1f, info->ide_addr + S3C_ATA_IRQ);
> > + writel(0x1b, info->ide_addr + S3C_ATA_IRQ_MSK);
> > + break;
> > +
> > + case TYPE_S5PV210:
> > + case TYPE_S5PC100:
> > + /* Configure as little endian and enable the i/f */
> > + pata_s3c_set_endian(info->ide_addr, 0);
> > + pata_s3c_enable(info->ide_addr, 1);
> > + mdelay(100);
> > +
> > + /* Remove IRQ Status */
> > + writel(0x3f, info->ide_addr + S3C_ATA_IRQ);
> > + writel(0x3f, info->ide_addr + S3C_ATA_IRQ_MSK);
> > + break;
> > +
> > + default:
> > + BUG();
> > + }
> > +}
> > +
> > +static int __devinit pata_s3c_probe(struct platform_device *pdev)
> > +{
> > + struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
> > + struct device *dev = &pdev->dev;
> > + struct s3c_ide_info *info;
> > + struct resource *res;
> > + struct ata_port *ap;
> > + struct ata_host *host;
> > + enum s3c_cpu_type cpu_type;
> > + int ret;
> > +
> > + cpu_type = platform_get_device_id(pdev)->driver_data;
> > +
> > + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> > + if (!info) {
> > + dev_err(dev, "failed to allocate memory for device data\n");
> > + return -ENOMEM;
> > + }
> > +
> > + info->irq = platform_get_irq(pdev, 0);
> > + if (info->irq < 0) {
> > + dev_err(dev, "could not obtain irq number\n");
> > + ret = -ENODEV;
> > + goto release_device_mem;
> > + }
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + if (res == NULL) {
> > + dev_err(dev, "failed to get mem resource\n");
> > + ret = -ENODEV;
>
> if i remeber correctly, you don't want to be returning -ENODEV as
> it will be ignored by the uper layers.
>
Will replace with EINVAL.
> > + goto release_device_mem;
> > + }
> > +
> > + info->ide_addr = devm_ioremap(dev,
> > + res->start, res->end - res->start + 1);
>
> resource_size() is your friend here.
>
OK
> > + if (!info->ide_addr) {
> > + dev_err(dev, "failed to map IO base address\n");
> > + ret = -ENOMEM;
> > + goto release_mem;
> > + }
> > +
> > + info->clk = clk_get(&pdev->dev, "cfcon");
>
> need to do something about using explicit names here, should be clk_get(,
NULL)
>
OK
> > + if (IS_ERR(info->clk)) {
> > + dev_err(dev, "failed to get access to cf controller
clock\n");
> > + ret = PTR_ERR(info->clk);
> > + info->clk = NULL;
> > + goto unmap;
> > + }
> > +
> > + if (clk_enable(info->clk)) {
> > + dev_err(dev, "failed to enable clock source.\n");
> > + goto clkerr;
> > + }
> > +
> > + /* init ata host */
> > + host = ata_host_alloc(dev, 1);
> > + if (!host) {
> > + dev_err(dev, "failed to allocate ide host\n");
> > + ret = -ENOMEM;
> > + goto stop_clk;
> > + }
> > +
> > + ap = host->ports[0];
> > + ap->flags |= ATA_FLAG_MMIO;
> > + ap->pio_mask = ATA_PIO4;
> > +
> > + if (cpu_type == TYPE_S3C6400) {
> > + ap->ops = &pata_s3c_port_ops;
> > + info->sfr_addr = info->ide_addr + 0x1800;
> > + info->ide_addr = info->ide_addr + 0x1900;
> > + info->fifo_status_reg = 0x94;
> > + } else if (cpu_type == TYPE_S5PC100) {
> > + ap->ops = &pata_s5p_port_ops;
> > + info->sfr_addr = info->ide_addr + 0x1800;
> > + info->ide_addr = info->ide_addr + 0x1900;
> > + info->fifo_status_reg = 0x84;
> > + } else {
> > + ap->ops = &pata_s5p_port_ops;
> > + info->fifo_status_reg = 0x84;
> > + }
> > +
> > + info->cpu_type = cpu_type;
> > +
> > + if (!(info->irq)) {
> > + ap->flags |= ATA_FLAG_PIO_POLLING;
> > + ata_port_desc(ap, "no IRQ, using PIO polling\n");
> > + }
> > +
> > + ap->ioaddr.cmd_addr = info->ide_addr + S3C_ATA_CMD;
> > + ap->ioaddr.data_addr = info->ide_addr + S3C_ATA_PIO_DTR;
> > + ap->ioaddr.error_addr = info->ide_addr + S3C_ATA_PIO_FED;
> > + ap->ioaddr.feature_addr = info->ide_addr + S3C_ATA_PIO_FED;
> > + ap->ioaddr.nsect_addr = info->ide_addr + S3C_ATA_PIO_SCR;
> > + ap->ioaddr.lbal_addr = info->ide_addr + S3C_ATA_PIO_LLR;
> > + ap->ioaddr.lbam_addr = info->ide_addr + S3C_ATA_PIO_LMR;
> > + ap->ioaddr.lbah_addr = info->ide_addr + S3C_ATA_PIO_LHR;
> > + ap->ioaddr.device_addr = info->ide_addr + S3C_ATA_PIO_DVR;
> > + ap->ioaddr.status_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> > + ap->ioaddr.command_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> > + ap->ioaddr.altstatus_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> > + ap->ioaddr.ctl_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> > +
> > +
> > + ata_port_desc(ap, "mmio cmd 0x%llx ",
> > + (unsigned long long)res->start);
> > +
> > + host->private_data = info;
> > +
> > + /* Calculates timing parameters for PIO mode */
> > + pata_s3c_setup_timing(info);
> > +
> > + if (pdata && (pdata->setup_gpio))
> no need for () around the pdata->setup_gpio
OK
> > + pdata->setup_gpio();
> > +
> > + /* Set endianness and enable the interface */
> > + pata_s3c_hwinit(info, pdata);
> > +
> > + return ata_host_activate(host, info->irq ? info->irq : 0,
> > + info->irq ? pata_s3c_irq : NULL,
> > + IRQF_DISABLED, &pata_s3c_sht);
>
> do you really need to run with IRQs disabled?
>
No.. will correct it
> > + dev_set_drvdata(&pdev->dev, host);
> > +
> > +stop_clk:
> > + clk_disable(info->clk);
> > +clkerr:
> > + clk_put(info->clk);
> > +unmap:
> > + devm_iounmap(dev, info->ide_addr);
> > +release_mem:
> > + release_mem_region(res->start, res->end - res->start + 1);
> > +release_device_mem:
> > + kfree(info);
> > +return ret;
> > +}
> > +
> > +static int __devexit pata_s3c_remove(struct platform_device *pdev)
> > +{
> > + struct ata_host *host = dev_get_drvdata(&pdev->dev);
> > + struct s3c_ide_info *info;
> > + struct resource *res;
> > +
> > + if (!host)
> > + return 0;
> > + info = host->private_data;
> > +
> > + ata_host_detach(host);
> > +
> > + devm_iounmap(&pdev->dev, info->ide_addr);
> > + clk_disable(info->clk);
> > + clk_put(info->clk);
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + release_mem_region(res->start, res->end - res->start + 1);
> > + kfree(info);
> > +
> > + return 0;
> > +}
> > +
> > +#ifdef CONFIG_PM
> > +static int pata_s3c_suspend(struct platform_device *pdev, pm_message_t
state)
> > +{
> > + struct ata_host *host = dev_get_drvdata(&pdev->dev);
> > + if (host)
> > + return ata_host_suspend(host, state);
> > + else
> > + return 0;
> > +}
> > +
> > +static int pata_s3c_resume(struct platform_device *pdev)
> > +{
> > + struct ata_host *host = dev_get_drvdata(&pdev->dev);
> > + struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
> > + struct s3c_ide_info *info;
> > +
> > + info = host->private_data;
> > +
> > + if (host) {
> > + pata_s3c_hwinit(info, pdata);
> > + ata_host_resume(host);
> > + }
> > +
> > + return 0;
> > +}
> > +#endif
> > +
> > +/* driver device registration */
> > +static struct platform_device_id pata_s3c_driver_ids[] = {
> > + {
> > + .name = "s3c6400-pata",
> > + .driver_data = TYPE_S3C6400,
> > + }, {
> > + .name = "s5pc100-pata",
> > + .driver_data = TYPE_S5PC100,
> > + }, {
> > + .name = "s5pv210-pata",
> > + .driver_data = TYPE_S5PV210,
> > + },
> > + { }
> > +};
> > +
> > +MODULE_DEVICE_TABLE(platform, pata_s3c_driver_ids);
> > +
> > +static struct platform_driver pata_s3c_driver = {
> > + .probe = pata_s3c_probe,
> > + .remove = __devexit_p(pata_s3c_remove),
> > + .id_table = pata_s3c_driver_ids,
> > + .driver = {
> > + .name = DRV_NAME,
> > + .owner = THIS_MODULE,
> > + },
> > +#ifdef CONFIG_PM
> > + .suspend = pata_s3c_suspend,
> > + .resume = pata_s3c_resume,
> > +#endif
> please look at using the new pm_ops.
>
Will use dev_pm_ops.
> > +};
> > +
> > +static int __init pata_s3c_init(void)
> > +{
> > + return platform_driver_register(&pata_s3c_driver);
> > +}
> > +
> > +static void __exit pata_s3c_exit(void)
> > +{
> > + platform_driver_unregister(&pata_s3c_driver);
> > +}
> > +
> > +module_init(pata_s3c_init);
> > +module_exit(pata_s3c_exit);
> > +
> > +MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>");
> > +MODULE_DESCRIPTION("low-level driver for Samsung PATA controller");
> > +MODULE_LICENSE("GPL");
> > +MODULE_VERSION(DRV_VERSION);
> > --
> > 1.6.2.5
>
> not bad, needs some cleanup.
>
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:22 ` [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver Kukjin Kim
2010-05-27 8:43 ` Ben Dooks
@ 2010-05-27 8:43 ` Jassi Brar
2010-05-27 8:57 ` Ben Dooks
2010-05-27 10:17 ` Sergei Shtylyov
2010-05-27 21:52 ` Tejun Heo
3 siblings, 1 reply; 24+ messages in thread
From: Jassi Brar @ 2010-05-27 8:43 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 5:22 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> From: Abhilash Kesavan <a.kesavan@samsung.com>
>
> Adds support for the Samsung PATA controller. This driver is based on the
> Libata subsystem and references the earlier patches sent for IDE subsystem.
>
> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> ---
> ?drivers/ata/Kconfig ? ? ? ?| ? ?9 +
> ?drivers/ata/Makefile ? ? ? | ? ?1 +
> ?drivers/ata/pata_samsung.c | ?591
Fasten your seat belts before reading further....
Rather than generic 'samsung', I would suggest the driver named
after the SoC, that is supported first(chronologically) in mainline kernel.
All newer SoCs should be simply taken to contain the controller of that SoC.
Otherwise, the same naming problem comes back to haunt us should
Samsung decides to use a different IP in future SoCs. What would we
call that driver? pata_samsung_v2.c ?
my two sparks
Jassi
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:43 ` Jassi Brar
@ 2010-05-27 8:57 ` Ben Dooks
2010-05-27 9:18 ` Jassi Brar
0 siblings, 1 reply; 24+ messages in thread
From: Ben Dooks @ 2010-05-27 8:57 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 05:43:47PM +0900, Jassi Brar wrote:
> On Thu, May 27, 2010 at 5:22 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> > From: Abhilash Kesavan <a.kesavan@samsung.com>
> >
> > Adds support for the Samsung PATA controller. This driver is based on the
> > Libata subsystem and references the earlier patches sent for IDE subsystem.
> >
> > Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> > ---
> > ?drivers/ata/Kconfig ? ? ? ?| ? ?9 +
> > ?drivers/ata/Makefile ? ? ? | ? ?1 +
> > ?drivers/ata/pata_samsung.c | ?591
>
> Fasten your seat belts before reading further....
>
> Rather than generic 'samsung', I would suggest the driver named
> after the SoC, that is supported first(chronologically) in mainline kernel.
> All newer SoCs should be simply taken to contain the controller of that SoC.
> Otherwise, the same naming problem comes back to haunt us should
> Samsung decides to use a different IP in future SoCs. What would we
> call that driver? pata_samsung_v2.c ?
I'm not so bothered, but it could be pata_samsung_cfcon or anything,
a new block could be called pata_samsung_v2 or fred for all I really
care about this.
> my two sparks
> Jassi
--
--
Ben
Q: What's a light-year?
A: One-third less calories than a regular year.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:57 ` Ben Dooks
@ 2010-05-27 9:18 ` Jassi Brar
0 siblings, 0 replies; 24+ messages in thread
From: Jassi Brar @ 2010-05-27 9:18 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, May 27, 2010 at 5:57 PM, Ben Dooks <ben-linux@fluff.org> wrote:
> On Thu, May 27, 2010 at 05:43:47PM +0900, Jassi Brar wrote:
>> On Thu, May 27, 2010 at 5:22 PM, Kukjin Kim <kgene.kim@samsung.com> wrote:
>> > From: Abhilash Kesavan <a.kesavan@samsung.com>
>> >
>> > Adds support for the Samsung PATA controller. This driver is based on the
>> > Libata subsystem and references the earlier patches sent for IDE subsystem.
>> >
>> > Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
>> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
>> > ---
>> > ?drivers/ata/Kconfig ? ? ? ?| ? ?9 +
>> > ?drivers/ata/Makefile ? ? ? | ? ?1 +
>> > ?drivers/ata/pata_samsung.c | ?591
>>
>> Fasten your seat belts before reading further....
>>
>> Rather than generic 'samsung', I would suggest the driver named
>> after the SoC, that is supported first(chronologically) in mainline kernel.
>> All newer SoCs should be simply taken to contain the controller of that SoC.
>> Otherwise, the same naming problem comes back to haunt us should
>> Samsung decides to use a different IP in future SoCs. What would we
>> call that driver? pata_samsung_v2.c ?
>
> I'm not so bothered, but it could be pata_samsung_cfcon or anything,
> a new block could be called pata_samsung_v2 or fred
well, then pata_samsung.c is better for we know chances of this IP change in
future SoCs are quite slim.
And even if it does change we shall call it
pata_samsung_really_final_this_time.c ;)
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:22 ` [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver Kukjin Kim
2010-05-27 8:43 ` Ben Dooks
2010-05-27 8:43 ` Jassi Brar
@ 2010-05-27 10:17 ` Sergei Shtylyov
2010-06-02 2:42 ` Kukjin Kim
2010-05-27 21:52 ` Tejun Heo
3 siblings, 1 reply; 24+ messages in thread
From: Sergei Shtylyov @ 2010-05-27 10:17 UTC (permalink / raw)
To: linux-arm-kernel
Hello.
Kukjin Kim wrote:
> From: Abhilash Kesavan <a.kesavan@samsung.com>
> Adds support for the Samsung PATA controller. This driver is based on the
> Libata subsystem and references the earlier patches sent for IDE subsystem.
> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
> diff --git a/drivers/ata/pata_samsung.c b/drivers/ata/pata_samsung.c
> new file mode 100644
> index 0000000..14381e4
> --- /dev/null
> +++ b/drivers/ata/pata_samsung.c
> @@ -0,0 +1,591 @@
[...]
> +static void pata_s3c_tune_chipset(struct s3c_ide_info *info, u8 ide_mode)
> +{
> + ulong ata_cfg = readl(info->ide_addr + S3C_ATA_CFG);
> +
> + /* IORDY is enabled for modes > PIO2 */
> + if (XFER_PIO_0 <= ide_mode && ide_mode <= XFER_PIO_4) {
> +
> + switch (ide_mode) {
> + case XFER_PIO_0:
> + case XFER_PIO_1:
> + case XFER_PIO_2:
> + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
Useless parens.
> + break;
> + case XFER_PIO_3:
> + case XFER_PIO_4:
> + ata_cfg |= S3C_ATA_CFG_IORDYEN;
IORDY should be controlled by ata_id_pio_need_iordy(), not by mode
number. PIO2 also can have IODRY enabled.
> + break;
> + }
> +
> + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> + writel(piotime[ide_mode - XFER_PIO_0],
> + info->ide_addr + S3C_ATA_PIO_TIME);
> + } else {
> + /* Default to PIO0 */
> + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
> + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> + writel(piotime[0], info->ide_addr + S3C_ATA_PIO_TIME);
If you don't support DMA modes or modes higher than PIO4 (PIO5 and
PIO6 would have been good for CF though), just do nothing.
> + }
> +}
> +
> +static void
> +pata_s3c_set_piomode(struct ata_port *ap, struct ata_device *adev)
> +{
> + struct s3c_ide_info *info = ap->host->private_data;
> +
> + /* Configure IORDY based on PIO mode and also set the timing value */
> + pata_s3c_tune_chipset(info, adev->pio_mode);
Don't see why you need a separate function for that. Maybe in
preparation to UDMA support?
> +/*
> + * Writes to one of the task file registers.
> + */
> +static void ata_outb(struct ata_host *host, u8 addr, void __iomem *reg)
> +{
> + struct s3c_ide_info *info = host->private_data;
> +
> + wait_for_host_ready(info);
> + __raw_writeb(addr, reg);
You should use write?() or __raw_write?() consistently...
> +/*
> + * pata_s3c_tf_load - send taskfile registers to host controller
> + */
> +static void pata_s3c_tf_load(struct ata_port *ap,
> + const struct ata_taskfile *tf)
> +{
> + struct ata_ioports *ioaddr = &ap->ioaddr;
> + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
> +
> + if (tf->ctl != ap->last_ctl) {
> + if (ioaddr->ctl_addr)
This register does exist and you assign ioaddr->ctl_addr in
pata_s3c_probe(), hence the check is pointless.
> + ata_outb(ap->host, tf->ctl, ioaddr->ctl_addr);
> + ap->last_ctl = tf->ctl;
> + ata_wait_idle(ap);
> + }
> +
> + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
> + WARN_ON_ONCE(!ioaddr->ctl_addr);
You don't need this either.
> +/*
> + * pata_s3c_tf_read - input device's ATA taskfile shadow registers
> + */
> +static void pata_s3c_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
> +{
> + struct ata_ioports *ioaddr = &ap->ioaddr;
> +
> + tf->command = ata_sff_check_status(ap);
But you have overriden this method, so ata_sff_check_status()
shouldn't work!
> + tf->feature = ata_inb(ap->host, ioaddr->error_addr);
> + tf->nsect = ata_inb(ap->host, ioaddr->nsect_addr);
> + tf->lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> + tf->lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> + tf->lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> + tf->device = ata_inb(ap->host, ioaddr->device_addr);
> +
> + if (tf->flags & ATA_TFLAG_LBA48) {
> + if (likely(ioaddr->ctl_addr)) {
Not just likely, it's always true. Emilinate the check please.
> + iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
> + tf->hob_feature = ata_inb(ap->host, ioaddr->error_addr);
> + tf->hob_nsect = ata_inb(ap->host, ioaddr->nsect_addr);
> + tf->hob_lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> + tf->hob_lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> + tf->hob_lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> + iowrite8(tf->ctl, ioaddr->ctl_addr);
> + ap->last_ctl = tf->ctl;
> + } else
> + WARN_ON_ONCE(1);
Not needed.
> +/*
> + * pata_s3c_data_xfer - Transfer data by PIO
> + */
> +unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char *buf,
> + unsigned int buflen, int rw)
> +{
> + struct ata_port *ap = dev->link->ap;
> + struct s3c_ide_info *info = ap->host->private_data;
> + void __iomem *data_addr = ap->ioaddr.data_addr;
> + unsigned int words = buflen >> 1, i;
> + u16 *temp_addr = (u16 *)buf;
> +
> + if (rw == READ) {
{} not needed.
> + for (i = 0; i < words; i++, temp_addr++) {
> + wait_for_host_ready(info);
> + *temp_addr = __raw_readw(data_addr);
> + wait_for_host_ready(info);
> + *temp_addr = __raw_readw(info->ide_addr
> + + S3C_ATA_PIO_RDATA);
> + }
> + } else {
{} not needed.
> + for (i = 0; i < words; i++, temp_addr++) {
> + wait_for_host_ready(info);
> + writel(*temp_addr, data_addr);
> + }
> + }
Well, if this is pere CF case, 'buflen' can't be odd, but otherwise
you should handle that case...
> +
> + return words << 1;
> +}
> +
> +static struct scsi_host_template pata_s3c_sht = {
> + ATA_PIO_SHT(DRV_NAME),
> +};
> +
> +static struct ata_port_operations pata_s3c_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .sff_check_status = pata_s3c_check_status,
Since simple iowrite8() isn't enough in your case, you also need to
override sff_dev_select(), sff_check_altstatus(), and sff_set_devctl()
methods...
> + .sff_tf_load = pata_s3c_tf_load,
> + .sff_tf_read = pata_s3c_tf_read,
> + .sff_data_xfer = pata_s3c_data_xfer,
> + .sff_exec_command = pata_s3c_exec_command,
> + .qc_prep = ata_noop_qc_prep,
> + .set_piomode = pata_s3c_set_piomode,
> +};
> +
> +static struct ata_port_operations pata_s5p_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .qc_prep = ata_noop_qc_prep,
> + .set_piomode = pata_s3c_set_piomode,
> +};
[...]
> +static void pata_s3c_setup_timing(struct s3c_ide_info *info)
> +{
> + uint t1, t2, teoc, i;
> +
> + uint pio_t1[5] = { 70, 50, 30, 30, 25 };
Could use ata_timing_find_mode() here to get the mode timings,
intead of duplicating them from libata-ocre.c...
> + uint pio_t2[5] = { 290, 290, 290, 80, 70 };
Note that those active times are for command cycles, not for data ones.
> + uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
What timing is this? :-O
> +
> + ulong cycle_time = (uint) (1000000000 / clk_get_rate(info->clk));
> +
> + for (i = 0; i < 5; i++) {
> + t1 = (pio_t1[i] / cycle_time) & 0x0f;
> + t2 = (pio_t2[i] / cycle_time) & 0xff;
Could use ata_timing_compute() here.
> + teoc = (pio_teoc[i] / cycle_time) & 0xff;
> + piotime[i] = (teoc << 12) | (t2 << 4) | t1;
> + }
> +}
> +
> +static void pata_s3c_hwinit(struct s3c_ide_info *info,
> + struct s3c_ide_platdata *pdata)
> +{
> + /* Select true-ide as the internal operating mode*/
> + if (pdata && (pdata->cfg_mode))
> + pdata->cfg_mode(info->sfr_addr);
> +
> + switch (info->cpu_type) {
> + case TYPE_S3C6400:
> + /* Configure as big endian and enable the i/f*/
Put space before */, please.
> +static int __devinit pata_s3c_probe(struct platform_device *pdev)
> +{
> + struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
> + struct device *dev = &pdev->dev;
> + struct s3c_ide_info *info;
> + struct resource *res;
> + struct ata_port *ap;
> + struct ata_host *host;
> + enum s3c_cpu_type cpu_type;
> + int ret;
> +
> + cpu_type = platform_get_device_id(pdev)->driver_data;
> +
> + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> + if (!info) {
> + dev_err(dev, "failed to allocate memory for device data\n");
> + return -ENOMEM;
> + }
> +
> + info->irq = platform_get_irq(pdev, 0);
> + if (info->irq < 0) {
> + dev_err(dev, "could not obtain irq number\n");
> + ret = -ENODEV;
> + goto release_device_mem;
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (res == NULL) {
> + dev_err(dev, "failed to get mem resource\n");
> + ret = -ENODEV;
> + goto release_device_mem;
> + }
> +
> + info->ide_addr = devm_ioremap(dev,
> + res->start, res->end - res->start + 1);
> + if (!info->ide_addr) {
> + dev_err(dev, "failed to map IO base address\n");
> + ret = -ENOMEM;
> + goto release_mem;
> + }
> +
> + info->clk = clk_get(&pdev->dev, "cfcon");
> + if (IS_ERR(info->clk)) {
> + dev_err(dev, "failed to get access to cf controller clock\n");
> + ret = PTR_ERR(info->clk);
> + info->clk = NULL;
> + goto unmap;
> + }
> +
> + if (clk_enable(info->clk)) {
Can it really fail?
> + dev_err(dev, "failed to enable clock source.\n");
> + goto clkerr;
> + }
> +
> + /* init ata host */
> + host = ata_host_alloc(dev, 1);
> + if (!host) {
> + dev_err(dev, "failed to allocate ide host\n");
> + ret = -ENOMEM;
> + goto stop_clk;
> + }
> +
> + ap = host->ports[0];
> + ap->flags |= ATA_FLAG_MMIO;
> + ap->pio_mask = ATA_PIO4;
> +
> + if (cpu_type == TYPE_S3C6400) {
> + ap->ops = &pata_s3c_port_ops;
> + info->sfr_addr = info->ide_addr + 0x1800;
> + info->ide_addr = info->ide_addr + 0x1900;
> + info->fifo_status_reg = 0x94;
> + } else if (cpu_type == TYPE_S5PC100) {
> + ap->ops = &pata_s5p_port_ops;
> + info->sfr_addr = info->ide_addr + 0x1800;
> + info->ide_addr = info->ide_addr + 0x1900;
Does make sense to assign those before *if*.
> + info->fifo_status_reg = 0x84;
> + } else {
> + ap->ops = &pata_s5p_port_ops;
You don't assign 'info->ide_addr' here but you'll need it in
pata_s3c_tune_chipset() which will be called thru pata_s5p_port_ops!
> + info->fifo_status_reg = 0x84;
> + }
> +
> + info->cpu_type = cpu_type;
> +
> + if (!(info->irq)) {
Parens not needed around 'info->irq'.
> + ap->flags |= ATA_FLAG_PIO_POLLING;
> + ata_port_desc(ap, "no IRQ, using PIO polling\n");
> + }
> +
> + ap->ioaddr.cmd_addr = info->ide_addr + S3C_ATA_CMD;
> + ap->ioaddr.data_addr = info->ide_addr + S3C_ATA_PIO_DTR;
> + ap->ioaddr.error_addr = info->ide_addr + S3C_ATA_PIO_FED;
> + ap->ioaddr.feature_addr = info->ide_addr + S3C_ATA_PIO_FED;
> + ap->ioaddr.nsect_addr = info->ide_addr + S3C_ATA_PIO_SCR;
> + ap->ioaddr.lbal_addr = info->ide_addr + S3C_ATA_PIO_LLR;
> + ap->ioaddr.lbam_addr = info->ide_addr + S3C_ATA_PIO_LMR;
> + ap->ioaddr.lbah_addr = info->ide_addr + S3C_ATA_PIO_LHR;
> + ap->ioaddr.device_addr = info->ide_addr + S3C_ATA_PIO_DVR;
> + ap->ioaddr.status_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> + ap->ioaddr.command_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> + ap->ioaddr.altstatus_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> + ap->ioaddr.ctl_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> +
> +
Extra newline?
> + ata_port_desc(ap, "mmio cmd 0x%llx ",
> + (unsigned long long)res->start);
> +
> + host->private_data = info;
> +
> + /* Calculates timing parameters for PIO mode */
> + pata_s3c_setup_timing(info);
You could do it right in pata_s3c_tune_chipset() -- no need to
precalculate the timings.
> + if (pdata && (pdata->setup_gpio))
Prens not needed around 'pdata->setup_gpio'.
> + pdata->setup_gpio();
> +
> + /* Set endianness and enable the interface */
> + pata_s3c_hwinit(info, pdata);
> +
> + return ata_host_activate(host, info->irq ? info->irq : 0,
This ?: doesn't make sense, just pass 'info->irq'.
> + info->irq ? pata_s3c_irq : NULL,
> + IRQF_DISABLED, &pata_s3c_sht);
> +
> + dev_set_drvdata(&pdev->dev, host);
Could use platform_set_drvdata(pdev, host)...
> +
> +stop_clk:
> + clk_disable(info->clk);
> +clkerr:
> + clk_put(info->clk);
> +unmap:
> + devm_iounmap(dev, info->ide_addr);
devm_ioremap() should "look after itself", so no explicait call
should be needed, if I don't mistake...
> +release_mem:
> + release_mem_region(res->start, res->end - res->start + 1);
But you didn't call request_mem_region()!
> +release_device_mem:
> + kfree(info);
> +return ret;
> +}
> +
> +static int __devexit pata_s3c_remove(struct platform_device *pdev)
> +{
> + struct ata_host *host = dev_get_drvdata(&pdev->dev);
Could use platform_get_drvdata(pdev)...
> + struct s3c_ide_info *info;
> + struct resource *res;
> +
> + if (!host)
> + return 0;
> + info = host->private_data;
> +
> + ata_host_detach(host);
> +
> + devm_iounmap(&pdev->dev, info->ide_addr);
> + clk_disable(info->clk);
> + clk_put(info->clk);
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + release_mem_region(res->start, res->end - res->start + 1);
Use resource_size(). Also, you don't call request_mem_region().
> + kfree(info);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +static int pata_s3c_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> + struct ata_host *host = dev_get_drvdata(&pdev->dev);
Could use platform_get_drvdata(pdev)...
> + if (host)
> + return ata_host_suspend(host, state);
> + else
> + return 0;
> +}
> +
> +static int pata_s3c_resume(struct platform_device *pdev)
> +{
> + struct ata_host *host = dev_get_drvdata(&pdev->dev);
Could use platform_get_drvdata(pdev)...
MBR, Sergei
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 10:17 ` Sergei Shtylyov
@ 2010-06-02 2:42 ` Kukjin Kim
2010-06-02 9:51 ` Sergei Shtylyov
0 siblings, 1 reply; 24+ messages in thread
From: Kukjin Kim @ 2010-06-02 2:42 UTC (permalink / raw)
To: linux-arm-kernel
Sergei Shtylyov wrote:
>
> Hello.
>
Hi :-)
> Kukjin Kim wrote:
>
> > From: Abhilash Kesavan <a.kesavan@samsung.com>
>
> > Adds support for the Samsung PATA controller. This driver is based on the
> > Libata subsystem and references the earlier patches sent for IDE
subsystem.
>
> > Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> > Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
>
> > diff --git a/drivers/ata/pata_samsung.c b/drivers/ata/pata_samsung.c
> > new file mode 100644
> > index 0000000..14381e4
> > --- /dev/null
> > +++ b/drivers/ata/pata_samsung.c
> > @@ -0,0 +1,591 @@
> [...]
> > +static void pata_s3c_tune_chipset(struct s3c_ide_info *info, u8
ide_mode)
> > +{
> > + ulong ata_cfg = readl(info->ide_addr + S3C_ATA_CFG);
> > +
> > + /* IORDY is enabled for modes > PIO2 */
> > + if (XFER_PIO_0 <= ide_mode && ide_mode <= XFER_PIO_4) {
> > +
> > + switch (ide_mode) {
> > + case XFER_PIO_0:
> > + case XFER_PIO_1:
> > + case XFER_PIO_2:
> > + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
>
> Useless parens.
>
OK
> > + break;
> > + case XFER_PIO_3:
> > + case XFER_PIO_4:
> > + ata_cfg |= S3C_ATA_CFG_IORDYEN;
>
> IORDY should be controlled by ata_id_pio_need_iordy(), not by mode
> number. PIO2 also can have IODRY enabled.
>
Will use ata_id_pio_need_iordy().
> > + break;
> > + }
> > +
> > + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> > + writel(piotime[ide_mode - XFER_PIO_0],
> > + info->ide_addr + S3C_ATA_PIO_TIME);
> > + } else {
> > + /* Default to PIO0 */
> > + ata_cfg &= (~S3C_ATA_CFG_IORDYEN);
> > + writel(ata_cfg, info->ide_addr + S3C_ATA_CFG);
> > + writel(piotime[0], info->ide_addr + S3C_ATA_PIO_TIME);
>
> If you don't support DMA modes or modes higher than PIO4 (PIO5 and
> PIO6 would have been good for CF though), just do nothing.
>
OK
> > + }
> > +}
> > +
> > +static void
> > +pata_s3c_set_piomode(struct ata_port *ap, struct ata_device *adev)
> > +{
> > + struct s3c_ide_info *info = ap->host->private_data;
> > +
> > + /* Configure IORDY based on PIO mode and also set the timing value */
> > + pata_s3c_tune_chipset(info, adev->pio_mode);
>
> Don't see why you need a separate function for that. Maybe in
> preparation to UDMA support?
>
That was it..but will remove pata_s3c_set_piomode() and call
pata_s3c_tune_chipset() directly.
> > +/*
> > + * Writes to one of the task file registers.
> > + */
> > +static void ata_outb(struct ata_host *host, u8 addr, void __iomem *reg)
> > +{
> > + struct s3c_ide_info *info = host->private_data;
> > +
> > + wait_for_host_ready(info);
> > + __raw_writeb(addr, reg);
>
> You should use write?() or __raw_write?() consistently...
>
OK
> > +/*
> > + * pata_s3c_tf_load - send taskfile registers to host controller
> > + */
> > +static void pata_s3c_tf_load(struct ata_port *ap,
> > + const struct ata_taskfile *tf)
> > +{
> > + struct ata_ioports *ioaddr = &ap->ioaddr;
> > + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
> > +
> > + if (tf->ctl != ap->last_ctl) {
> > + if (ioaddr->ctl_addr)
>
> This register does exist and you assign ioaddr->ctl_addr in
> pata_s3c_probe(), hence the check is pointless.
>
Will remove the check.
> > + ata_outb(ap->host, tf->ctl, ioaddr->ctl_addr);
> > + ap->last_ctl = tf->ctl;
> > + ata_wait_idle(ap);
> > + }
> > +
> > + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
> > + WARN_ON_ONCE(!ioaddr->ctl_addr);
>
> You don't need this either.
>
OK
> > +/*
> > + * pata_s3c_tf_read - input device's ATA taskfile shadow registers
> > + */
> > +static void pata_s3c_tf_read(struct ata_port *ap, struct ata_taskfile
*tf)
> > +{
> > + struct ata_ioports *ioaddr = &ap->ioaddr;
> > +
> > + tf->command = ata_sff_check_status(ap);
>
> But you have overriden this method, so ata_sff_check_status()
> shouldn't work!
>
OK
> > + tf->feature = ata_inb(ap->host, ioaddr->error_addr);
> > + tf->nsect = ata_inb(ap->host, ioaddr->nsect_addr);
> > + tf->lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> > + tf->lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> > + tf->lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> > + tf->device = ata_inb(ap->host, ioaddr->device_addr);
> > +
> > + if (tf->flags & ATA_TFLAG_LBA48) {
> > + if (likely(ioaddr->ctl_addr)) {
>
> Not just likely, it's always true. Emilinate the check please.
>
OK
> > + iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
> > + tf->hob_feature = ata_inb(ap->host,
ioaddr->error_addr);
> > + tf->hob_nsect = ata_inb(ap->host,
ioaddr->nsect_addr);
> > + tf->hob_lbal = ata_inb(ap->host, ioaddr->lbal_addr);
> > + tf->hob_lbam = ata_inb(ap->host, ioaddr->lbam_addr);
> > + tf->hob_lbah = ata_inb(ap->host, ioaddr->lbah_addr);
> > + iowrite8(tf->ctl, ioaddr->ctl_addr);
> > + ap->last_ctl = tf->ctl;
> > + } else
> > + WARN_ON_ONCE(1);
>
> Not needed.
>
OK
> > +/*
> > + * pata_s3c_data_xfer - Transfer data by PIO
> > + */
> > +unsigned int pata_s3c_data_xfer(struct ata_device *dev, unsigned char
*buf,
> > + unsigned int buflen, int rw)
> > +{
> > + struct ata_port *ap = dev->link->ap;
> > + struct s3c_ide_info *info = ap->host->private_data;
> > + void __iomem *data_addr = ap->ioaddr.data_addr;
> > + unsigned int words = buflen >> 1, i;
> > + u16 *temp_addr = (u16 *)buf;
> > +
> > + if (rw == READ) {
>
> {} not needed.
>
OK
> > + for (i = 0; i < words; i++, temp_addr++) {
> > + wait_for_host_ready(info);
> > + *temp_addr = __raw_readw(data_addr);
> > + wait_for_host_ready(info);
> > + *temp_addr = __raw_readw(info->ide_addr
> > + + S3C_ATA_PIO_RDATA);
> > + }
> > + } else {
>
> {} not needed.
>
OK
> > + for (i = 0; i < words; i++, temp_addr++) {
> > + wait_for_host_ready(info);
> > + writel(*temp_addr, data_addr);
> > + }
> > + }
>
> Well, if this is pere CF case, 'buflen' can't be odd, but otherwise
> you should handle that case...
>
OK
> > +
> > + return words << 1;
> > +}
> > +
> > +static struct scsi_host_template pata_s3c_sht = {
> > + ATA_PIO_SHT(DRV_NAME),
> > +};
> > +
> > +static struct ata_port_operations pata_s3c_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .sff_check_status = pata_s3c_check_status,
>
> Since simple iowrite8() isn't enough in your case, you also need to
> override sff_dev_select(), sff_check_altstatus(), and sff_set_devctl()
> methods...
>
Will add these overrides.
> > + .sff_tf_load = pata_s3c_tf_load,
> > + .sff_tf_read = pata_s3c_tf_read,
> > + .sff_data_xfer = pata_s3c_data_xfer,
> > + .sff_exec_command = pata_s3c_exec_command,
> > + .qc_prep = ata_noop_qc_prep,
> > + .set_piomode = pata_s3c_set_piomode,
> > +};
> > +
> > +static struct ata_port_operations pata_s5p_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .qc_prep = ata_noop_qc_prep,
> > + .set_piomode = pata_s3c_set_piomode,
> > +};
>
> [...]
>
> > +static void pata_s3c_setup_timing(struct s3c_ide_info *info)
> > +{
> > + uint t1, t2, teoc, i;
> > +
> > + uint pio_t1[5] = { 70, 50, 30, 30, 25 };
>
> Could use ata_timing_find_mode() here to get the mode timings,
> intead of duplicating them from libata-ocre.c...
>
> > + uint pio_t2[5] = { 290, 290, 290, 80, 70 };
>
> Note that those active times are for command cycles, not for data ones.
>
OK
> > + uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
>
> What timing is this? :-O
>
Should have been t2i rec.
> > +
> > + ulong cycle_time = (uint) (1000000000 / clk_get_rate(info->clk));
> > +
> > + for (i = 0; i < 5; i++) {
> > + t1 = (pio_t1[i] / cycle_time) & 0x0f;
> > + t2 = (pio_t2[i] / cycle_time) & 0xff;
>
> Could use ata_timing_compute() here.
>
Will re-use the timing parameters and ata_timing_compute(),
ata_timing_find_mode() from libata-core.c
> > + teoc = (pio_teoc[i] / cycle_time) & 0xff;
> > + piotime[i] = (teoc << 12) | (t2 << 4) | t1;
> > + }
> > +}
> > +
> > +static void pata_s3c_hwinit(struct s3c_ide_info *info,
> > + struct s3c_ide_platdata *pdata)
> > +{
> > + /* Select true-ide as the internal operating mode*/
> > + if (pdata && (pdata->cfg_mode))
> > + pdata->cfg_mode(info->sfr_addr);
> > +
> > + switch (info->cpu_type) {
> > + case TYPE_S3C6400:
> > + /* Configure as big endian and enable the i/f*/
>
> Put space before */, please.
>
OK
> > +static int __devinit pata_s3c_probe(struct platform_device *pdev)
> > +{
> > + struct s3c_ide_platdata *pdata = pdev->dev.platform_data;
> > + struct device *dev = &pdev->dev;
> > + struct s3c_ide_info *info;
> > + struct resource *res;
> > + struct ata_port *ap;
> > + struct ata_host *host;
> > + enum s3c_cpu_type cpu_type;
> > + int ret;
> > +
> > + cpu_type = platform_get_device_id(pdev)->driver_data;
> > +
> > + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
> > + if (!info) {
> > + dev_err(dev, "failed to allocate memory for device data\n");
> > + return -ENOMEM;
> > + }
> > +
> > + info->irq = platform_get_irq(pdev, 0);
> > + if (info->irq < 0) {
> > + dev_err(dev, "could not obtain irq number\n");
> > + ret = -ENODEV;
> > + goto release_device_mem;
> > + }
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + if (res == NULL) {
> > + dev_err(dev, "failed to get mem resource\n");
> > + ret = -ENODEV;
> > + goto release_device_mem;
> > + }
> > +
> > + info->ide_addr = devm_ioremap(dev,
> > + res->start, res->end - res->start + 1);
> > + if (!info->ide_addr) {
> > + dev_err(dev, "failed to map IO base address\n");
> > + ret = -ENOMEM;
> > + goto release_mem;
> > + }
> > +
> > + info->clk = clk_get(&pdev->dev, "cfcon");
> > + if (IS_ERR(info->clk)) {
> > + dev_err(dev, "failed to get access to cf controller
clock\n");
> > + ret = PTR_ERR(info->clk);
> > + info->clk = NULL;
> > + goto unmap;
> > + }
> > +
> > + if (clk_enable(info->clk)) {
>
> Can it really fail?
>
Will remove it.
> > + dev_err(dev, "failed to enable clock source.\n");
> > + goto clkerr;
> > + }
> > +
> > + /* init ata host */
> > + host = ata_host_alloc(dev, 1);
> > + if (!host) {
> > + dev_err(dev, "failed to allocate ide host\n");
> > + ret = -ENOMEM;
> > + goto stop_clk;
> > + }
> > +
> > + ap = host->ports[0];
> > + ap->flags |= ATA_FLAG_MMIO;
> > + ap->pio_mask = ATA_PIO4;
> > +
> > + if (cpu_type == TYPE_S3C6400) {
> > + ap->ops = &pata_s3c_port_ops;
> > + info->sfr_addr = info->ide_addr + 0x1800;
> > + info->ide_addr = info->ide_addr + 0x1900;
> > + info->fifo_status_reg = 0x94;
> > + } else if (cpu_type == TYPE_S5PC100) {
> > + ap->ops = &pata_s5p_port_ops;
> > + info->sfr_addr = info->ide_addr + 0x1800;
> > + info->ide_addr = info->ide_addr + 0x1900;
>
> Does make sense to assign those before *if*.
>
Offsets not required for S5PV210/S5PC110.
> > + info->fifo_status_reg = 0x84;
> > + } else {
> > + ap->ops = &pata_s5p_port_ops;
>
> You don't assign 'info->ide_addr' here but you'll need it in
> pata_s3c_tune_chipset() which will be called thru pata_s5p_port_ops!
>
The address received at ioremap() is enough for S5PV210/S5PC110..no offset
needed.
> > + info->fifo_status_reg = 0x84;
> > + }
> > +
> > + info->cpu_type = cpu_type;
> > +
> > + if (!(info->irq)) {
>
> Parens not needed around 'info->irq'.
>
OK
> > + ap->flags |= ATA_FLAG_PIO_POLLING;
> > + ata_port_desc(ap, "no IRQ, using PIO polling\n");
> > + }
> > +
> > + ap->ioaddr.cmd_addr = info->ide_addr + S3C_ATA_CMD;
> > + ap->ioaddr.data_addr = info->ide_addr + S3C_ATA_PIO_DTR;
> > + ap->ioaddr.error_addr = info->ide_addr + S3C_ATA_PIO_FED;
> > + ap->ioaddr.feature_addr = info->ide_addr + S3C_ATA_PIO_FED;
> > + ap->ioaddr.nsect_addr = info->ide_addr + S3C_ATA_PIO_SCR;
> > + ap->ioaddr.lbal_addr = info->ide_addr + S3C_ATA_PIO_LLR;
> > + ap->ioaddr.lbam_addr = info->ide_addr + S3C_ATA_PIO_LMR;
> > + ap->ioaddr.lbah_addr = info->ide_addr + S3C_ATA_PIO_LHR;
> > + ap->ioaddr.device_addr = info->ide_addr + S3C_ATA_PIO_DVR;
> > + ap->ioaddr.status_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> > + ap->ioaddr.command_addr = info->ide_addr + S3C_ATA_PIO_CSD;
> > + ap->ioaddr.altstatus_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> > + ap->ioaddr.ctl_addr = info->ide_addr + S3C_ATA_PIO_DAD;
> > +
> > +
>
> Extra newline?
>
Yes..will remove it.
> > + ata_port_desc(ap, "mmio cmd 0x%llx ",
> > + (unsigned long long)res->start);
> > +
> > + host->private_data = info;
> > +
> > + /* Calculates timing parameters for PIO mode */
> > + pata_s3c_setup_timing(info);
>
> You could do it right in pata_s3c_tune_chipset() -- no need to
> precalculate the timings.
>
Will move it.
> > + if (pdata && (pdata->setup_gpio))
>
> Prens not needed around 'pdata->setup_gpio'.
>
OK
> > + pdata->setup_gpio();
> > +
> > + /* Set endianness and enable the interface */
> > + pata_s3c_hwinit(info, pdata);
> > +
> > + return ata_host_activate(host, info->irq ? info->irq : 0,
>
> This ?: doesn't make sense, just pass 'info->irq'.
>
OK
> > + info->irq ? pata_s3c_irq : NULL,
> > + IRQF_DISABLED, &pata_s3c_sht);
> > +
> > + dev_set_drvdata(&pdev->dev, host);
>
> Could use platform_set_drvdata(pdev, host)...
>
OK
> > +
> > +stop_clk:
> > + clk_disable(info->clk);
> > +clkerr:
> > + clk_put(info->clk);
> > +unmap:
> > + devm_iounmap(dev, info->ide_addr);
>
> devm_ioremap() should "look after itself", so no explicait call
> should be needed, if I don't mistake...
>
OK
> > +release_mem:
> > + release_mem_region(res->start, res->end - res->start + 1);
>
> But you didn't call request_mem_region()!
>
I didn't..will remove.
> > +release_device_mem:
> > + kfree(info);
> > +return ret;
> > +}
> > +
> > +static int __devexit pata_s3c_remove(struct platform_device *pdev)
> > +{
> > + struct ata_host *host = dev_get_drvdata(&pdev->dev);
>
> Could use platform_get_drvdata(pdev)...
>
OK
> > + struct s3c_ide_info *info;
> > + struct resource *res;
> > +
> > + if (!host)
> > + return 0;
> > + info = host->private_data;
> > +
> > + ata_host_detach(host);
> > +
> > + devm_iounmap(&pdev->dev, info->ide_addr);
> > + clk_disable(info->clk);
> > + clk_put(info->clk);
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + release_mem_region(res->start, res->end - res->start + 1);
>
> Use resource_size(). Also, you don't call request_mem_region().
>
OK
> > + kfree(info);
> > +
> > + return 0;
> > +}
> > +
> > +#ifdef CONFIG_PM
> > +static int pata_s3c_suspend(struct platform_device *pdev, pm_message_t
state)
> > +{
> > + struct ata_host *host = dev_get_drvdata(&pdev->dev);
>
> Could use platform_get_drvdata(pdev)...
>
OK
> > + if (host)
> > + return ata_host_suspend(host, state);
> > + else
> > + return 0;
> > +}
> > +
> > +static int pata_s3c_resume(struct platform_device *pdev)
> > +{
> > + struct ata_host *host = dev_get_drvdata(&pdev->dev);
>
> Could use platform_get_drvdata(pdev)...
>
OK
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-06-02 2:42 ` Kukjin Kim
@ 2010-06-02 9:51 ` Sergei Shtylyov
2010-06-03 0:25 ` Kukjin Kim
0 siblings, 1 reply; 24+ messages in thread
From: Sergei Shtylyov @ 2010-06-02 9:51 UTC (permalink / raw)
To: linux-arm-kernel
Hello.
Kukjin Kim wrote:
>>> From: Abhilash Kesavan <a.kesavan@samsung.com>
>>> Adds support for the Samsung PATA controller. This driver is based on the
>>> Libata subsystem and references the earlier patches sent for IDE subsystem.
Where I those I wonder? :-)
It's a pity they didn't get accepted.
>>> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
>>> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
[...]
>>> + for (i = 0; i < words; i++, temp_addr++) {
>>> + wait_for_host_ready(info);
>>> + writel(*temp_addr, data_addr);
>>> + }
>>> + }
>> Well, if this is pere CF case, 'buflen' can't be odd, but otherwise
I meant to type "pure". :-)
>> you should handle that case...
>>> + uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
>> What timing is this? :-O
> Should have been t2i rec.
If it's t2i timing, it is incorrect for the first 3 PIO modes.
>>> + if (cpu_type == TYPE_S3C6400) {
>>> + ap->ops = &pata_s3c_port_ops;
>>> + info->sfr_addr = info->ide_addr + 0x1800;
>>> + info->ide_addr = info->ide_addr + 0x1900;
>>> + info->fifo_status_reg = 0x94;
>>> + } else if (cpu_type == TYPE_S5PC100) {
>>> + ap->ops = &pata_s5p_port_ops;
>>> + info->sfr_addr = info->ide_addr + 0x1800;
>>> + info->ide_addr = info->ide_addr + 0x1900;
>> Does make sense to assign those before *if*.
> Offsets not required for S5PV210/S5PC110.
pata_s3c_tune_chipset() certainly requires them.
>>> + info->fifo_status_reg = 0x84;
>>> + } else {
>>> + ap->ops = &pata_s5p_port_ops;
>> You don't assign 'info->ide_addr' here but you'll need it in
>> pata_s3c_tune_chipset() which will be called thru pata_s5p_port_ops!
> The address received at ioremap() is enough for S5PV210/S5PC110..no offset
> needed.
I only have to restate that pata_s3c_tune_chipset() does use
'info->ide_addr'. Maybe you shouldn't install this method for S5PV210/S5PC110?
Or do you mean thgat offset of 0 will work?
>>> +release_mem:
>>> + release_mem_region(res->start, res->end - res->start + 1);
>> But you didn't call request_mem_region()!
> I didn't..will remove.
But you should call request_mem_region() in one or another form...
MBR, Sergei
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-06-02 9:51 ` Sergei Shtylyov
@ 2010-06-03 0:25 ` Kukjin Kim
0 siblings, 0 replies; 24+ messages in thread
From: Kukjin Kim @ 2010-06-03 0:25 UTC (permalink / raw)
To: linux-arm-kernel
Sergei Shtylyov wrote:
>
> Hello.
Hi ;-)
> Kukjin Kim wrote:
>
> >>> From: Abhilash Kesavan <a.kesavan@samsung.com>
> >>> Adds support for the Samsung PATA controller. This driver is based on
the
> >>> Libata subsystem and references the earlier patches sent for IDE
subsystem.
>
> Where I those I wonder? :-)
> It's a pity they didn't get accepted.
>
Was told that that only new libata based drivers would be accepted.
> >>> Signed-off-by: Abhilash Kesavan <a.kesavan@samsung.com>
> >>> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
>
> [...]
>
> >>> + for (i = 0; i < words; i++, temp_addr++) {
> >>> + wait_for_host_ready(info);
> >>> + writel(*temp_addr, data_addr);
> >>> + }
> >>> + }
>
> >> Well, if this is pere CF case, 'buflen' can't be odd, but otherwise
>
> I meant to type "pure". :-)
>
considering CF in true-ide mode..should I still add the check?
> >> you should handle that case...
>
> >>> + uint pio_teoc[5] = { 240, 43, 10, 70, 25 };
>
> >> What timing is this? :-O
>
> > Should have been t2i rec.
>
> If it's t2i timing, it is incorrect for the first 3 PIO modes.
>
Should have been (240, 93, 40, 70, 25)
> >>> + if (cpu_type == TYPE_S3C6400) {
> >>> + ap->ops = &pata_s3c_port_ops;
> >>> + info->sfr_addr = info->ide_addr + 0x1800;
> >>> + info->ide_addr = info->ide_addr + 0x1900;
> >>> + info->fifo_status_reg = 0x94;
> >>> + } else if (cpu_type == TYPE_S5PC100) {
> >>> + ap->ops = &pata_s5p_port_ops;
> >>> + info->sfr_addr = info->ide_addr + 0x1800;
> >>> + info->ide_addr = info->ide_addr + 0x1900;
>
> >> Does make sense to assign those before *if*.
>
> > Offsets not required for S5PV210/S5PC110.
>
> pata_s3c_tune_chipset() certainly requires them.
>
yes..but for V210/C110 just the ioremapped info->ide_addr with 0 offset is
enough.
> >>> + info->fifo_status_reg = 0x84;
> >>> + } else {
> >>> + ap->ops = &pata_s5p_port_ops;
>
> >> You don't assign 'info->ide_addr' here but you'll need it in
> >> pata_s3c_tune_chipset() which will be called thru pata_s5p_port_ops!
>
> > The address received at ioremap() is enough for S5PV210/S5PC110..no
offset
> > needed.
>
> I only have to restate that pata_s3c_tune_chipset() does use
> 'info->ide_addr'. Maybe you shouldn't install this method for
S5PV210/S5PC110?
> Or do you mean thgat offset of 0 will work?
>
V210/C110 requires 0 offset as compared to 6410 and C100 which require
0x1800.
> >>> +release_mem:
> >>> + release_mem_region(res->start, res->end - res->start + 1);
>
> >> But you didn't call request_mem_region()!
>
> > I didn't..will remove.
>
> But you should call request_mem_region() in one or another form...
>
OK..will request mem_region() before ioremap()..and then the release_mem's
should be fine.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 8:22 ` [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver Kukjin Kim
` (2 preceding siblings ...)
2010-05-27 10:17 ` Sergei Shtylyov
@ 2010-05-27 21:52 ` Tejun Heo
2010-06-02 2:46 ` Kukjin Kim
3 siblings, 1 reply; 24+ messages in thread
From: Tejun Heo @ 2010-05-27 21:52 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On 05/27/2010 10:22 AM, Kukjin Kim wrote:
> From: Abhilash Kesavan <a.kesavan@samsung.com>
>
> Adds support for the Samsung PATA controller. This driver is based on the
> Libata subsystem and references the earlier patches sent for IDE subsystem.
Just one small thing.
> +static struct ata_port_operations pata_s3c_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .sff_check_status = pata_s3c_check_status,
> + .sff_tf_load = pata_s3c_tf_load,
> + .sff_tf_read = pata_s3c_tf_read,
> + .sff_data_xfer = pata_s3c_data_xfer,
> + .sff_exec_command = pata_s3c_exec_command,
> + .qc_prep = ata_noop_qc_prep,
> + .set_piomode = pata_s3c_set_piomode,
> +};
> +
> +static struct ata_port_operations pata_s5p_port_ops = {
> + .inherits = &ata_sff_port_ops,
> + .qc_prep = ata_noop_qc_prep,
> + .set_piomode = pata_s3c_set_piomode,
> +};
You don't need to override .qc_prep to ata_noop_qc_prep() and can you
please base the patch against the current libata-dev#upstream?
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 4/4] pata_samsung: Add Samsung PATA controller driver
2010-05-27 21:52 ` Tejun Heo
@ 2010-06-02 2:46 ` Kukjin Kim
0 siblings, 0 replies; 24+ messages in thread
From: Kukjin Kim @ 2010-06-02 2:46 UTC (permalink / raw)
To: linux-arm-kernel
Tejun Heo wrote:
>
> Hello,
>
> On 05/27/2010 10:22 AM, Kukjin Kim wrote:
> > From: Abhilash Kesavan <a.kesavan@samsung.com>
> >
> > Adds support for the Samsung PATA controller. This driver is based on the
> > Libata subsystem and references the earlier patches sent for IDE
subsystem.
>
> Just one small thing.
>
> > +static struct ata_port_operations pata_s3c_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .sff_check_status = pata_s3c_check_status,
> > + .sff_tf_load = pata_s3c_tf_load,
> > + .sff_tf_read = pata_s3c_tf_read,
> > + .sff_data_xfer = pata_s3c_data_xfer,
> > + .sff_exec_command = pata_s3c_exec_command,
> > + .qc_prep = ata_noop_qc_prep,
> > + .set_piomode = pata_s3c_set_piomode,
> > +};
> > +
> > +static struct ata_port_operations pata_s5p_port_ops = {
> > + .inherits = &ata_sff_port_ops,
> > + .qc_prep = ata_noop_qc_prep,
> > + .set_piomode = pata_s3c_set_piomode,
> > +};
>
> You don't need to override .qc_prep to ata_noop_qc_prep() and can you
> please base the patch against the current libata-dev#upstream?
>
Will remove the override and rebase the new patches against upstream branch.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 24+ messages in thread