Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 3/6] ARM: davinci: da850: changed SRAM allocator to shared ram.
From: Matt Porter @ 2012-10-03 14:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349276133-26408-1-git-send-email-mporter@ti.com>

From: Subhasish Ghosh <subhasish@mistralsolutions.com>

This patch modifies the sram allocator to allocate memory
from the DA8XX shared RAM.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
[rebased onto consolidated SRAM patches]
Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
[rebased to mainline as consolidated SRAM patches were dropped]
Signed-off-by: Matt Porter <mporter@ti.com>
---
 arch/arm/mach-davinci/da850.c              |    4 ++--
 arch/arm/mach-davinci/include/mach/da8xx.h |    1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index b4b324f..d8d69de 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -1081,8 +1081,8 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
 	.gpio_irq		= IRQ_DA8XX_GPIO0,
 	.serial_dev		= &da8xx_serial_device,
 	.emac_pdata		= &da8xx_emac_pdata,
-	.sram_dma		= DA8XX_ARM_RAM_BASE,
-	.sram_len		= SZ_8K,
+	.sram_dma		= DA8XX_SHARED_RAM_BASE,
+	.sram_len		= SZ_128K,
 };
 
 void __init da850_init(void)
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index c9ee723..20553cf 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -68,6 +68,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_AEMIF_CS2_BASE	0x60000000
 #define DA8XX_AEMIF_CS3_BASE	0x62000000
 #define DA8XX_AEMIF_CTL_BASE	0x68000000
+#define DA8XX_SHARED_RAM_BASE	0x80000000
 #define DA8XX_ARM_RAM_BASE	0xffff0000
 
 void __init da830_init(void);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 2/6] ARM: davinci: da850-dm646x: remove the SRAM_VIRT iotable entry
From: Matt Porter @ 2012-10-03 14:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349276133-26408-1-git-send-email-mporter@ti.com>

From: Ben Gardiner <bengardiner@nanometrics.ca>

The sram regions defined for da850-dm646x in their iotable entries are also
defined in their davinci_soc_info's.

Remove this duplicate information which is now uneccessary since sram
init will ioremap the regions defined by their davinci_soc_info's.

Since this removal completely removes all uses of SRAM_VIRT, also remove
the SRAM_VIRT definition.

Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
Tested-by: Matt Porter <mporter@ti.com>
---
 arch/arm/mach-davinci/da850.c               |    6 ------
 arch/arm/mach-davinci/dm355.c               |    6 ------
 arch/arm/mach-davinci/dm365.c               |    6 ------
 arch/arm/mach-davinci/dm644x.c              |    6 ------
 arch/arm/mach-davinci/dm646x.c              |    6 ------
 arch/arm/mach-davinci/include/mach/common.h |    2 --
 6 files changed, 32 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 6676dee..b4b324f 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -713,12 +713,6 @@ static struct map_desc da850_io_desc[] = {
 		.length		= DA8XX_CP_INTC_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(DA8XX_ARM_RAM_BASE),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE
-	},
 };
 
 static u32 da850_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE };
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index a255434..b49c3b7 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -758,12 +758,6 @@ static struct map_desc dm355_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00010000),
-		.length		= SZ_32K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 /* Contents of JTAG ID register used to identify exact cpu type */
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index b680c83..6c39805 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -985,12 +985,6 @@ static struct map_desc dm365_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00010000),
-		.length		= SZ_32K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 static struct resource dm365_ks_resources[] = {
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 0755d46..f8aaa7d 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -795,12 +795,6 @@ static struct map_desc dm644x_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00008000),
-		.length		= SZ_16K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 /* Contents of JTAG ID register used to identify exact cpu type */
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 97c0f8e..ac7b431 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -756,12 +756,6 @@ static struct map_desc dm646x_io_desc[] = {
 		.length		= IO_SIZE,
 		.type		= MT_DEVICE
 	},
-	{
-		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(0x00010000),
-		.length		= SZ_32K,
-		.type		= MT_MEMORY_NONCACHED,
-	},
 };
 
 /* Contents of JTAG ID register used to identify exact cpu type */
diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
index bdc4aa8..046c723 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -104,8 +104,6 @@ int davinci_pm_init(void);
 static inline int davinci_pm_init(void) { return 0; }
 #endif
 
-/* standard place to map on-chip SRAMs; they *may* support DMA */
-#define SRAM_VIRT	0xfffe0000
 #define SRAM_SIZE	SZ_128K
 
 #endif /* __ARCH_ARM_MACH_DAVINCI_COMMON_H */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 1/6] ARM: davinci: sram: ioremap the davinci_soc_info specified sram regions
From: Matt Porter @ 2012-10-03 14:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349276133-26408-1-git-send-email-mporter@ti.com>

From: Ben Gardiner <bengardiner@nanometrics.ca>

The current davinci init sets up SRAM in iotables. There has been an observed
failure to boot a da850 with 128K specified in the iotable.

Make the davinci sram allocator -- now based on RMK's consolidated SRAM
support -- do an ioremap of the region specified by the entries in
davinci_soc_info before registering with gen_pool_add_virt().

This commit breaks runtime of davinci boards since the regions that
the sram init is now trying to ioremap have been iomapped by their
iotable entries. The iotable entries will be removed in the patches
to come.

Signed-off-by: Ben Gardiner <bengardiner@nanometrics.ca>
[rebased to mainline as the consolidated SRAM support was dropped]
Signed-off-by: Matt Porter <mporter@ti.com>
---
 arch/arm/mach-davinci/sram.c |   17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-davinci/sram.c b/arch/arm/mach-davinci/sram.c
index db0f778..0e8ca4f 100644
--- a/arch/arm/mach-davinci/sram.c
+++ b/arch/arm/mach-davinci/sram.c
@@ -10,6 +10,7 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/genalloc.h>
 
 #include <mach/common.h>
@@ -32,7 +33,7 @@ void *sram_alloc(size_t len, dma_addr_t *dma)
 		return NULL;
 
 	if (dma)
-		*dma = dma_base + (vaddr - SRAM_VIRT);
+		*dma = gen_pool_virt_to_phys(sram_pool, vaddr);
 	return (void *)vaddr;
 
 }
@@ -53,8 +54,10 @@ EXPORT_SYMBOL(sram_free);
  */
 static int __init sram_init(void)
 {
+	phys_addr_t phys = davinci_soc_info.sram_dma;
 	unsigned len = davinci_soc_info.sram_len;
 	int status = 0;
+	void *addr;
 
 	if (len) {
 		len = min_t(unsigned, len, SRAM_SIZE);
@@ -62,8 +65,16 @@ static int __init sram_init(void)
 		if (!sram_pool)
 			status = -ENOMEM;
 	}
-	if (sram_pool)
-		status = gen_pool_add(sram_pool, SRAM_VIRT, len, -1);
+
+	if (sram_pool) {
+		addr = ioremap(phys, len);
+		if (!addr)
+			return -ENOMEM;
+		if((status = gen_pool_add_virt(sram_pool, (unsigned)addr,
+					       phys, len, -1)))
+			iounmap(addr);
+	}
+
 	WARN_ON(status < 0);
 	return status;
 }
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 0/6] uio_pruss cleanup and platform support
From: Matt Porter @ 2012-10-03 14:55 UTC (permalink / raw)
  To: linux-arm-kernel

Changes since v2:
	- Dropped AM33xx/OMAP support from series.
	- Changed the DA850 L3 RAM gen_pool support to be based
	  on a previous Davinci SRAM series from Subhasish Ghosh
	  and Ben Gardiner.
	
Changes since v1:
	- Replaced uio_pruss private SRAM API use with genalloc
	- Added DA850 platform device and clock support
	- Added DA850 L3 RAM gen_pool support
	- Split out DT binding

This series enables uio_pruss on DA850 and removes use of the
private SRAM API by the driver. The driver previously was not
enabled by any platform and the private SRAM API was accessing
an invalid SRAM bank.

Ben Gardiner (2):
  ARM: davinci: sram: ioremap the davinci_soc_info specified sram
    regions
  ARM: davinci: da850-dm646x: remove the SRAM_VIRT iotable entry

Matt Porter (3):
  ARM: davinci: add platform hook to fetch the SRAM pool
  ARM: davinci: Add support for PRUSS on DA850
  uio: uio_pruss: replace private SRAM API with genalloc

Subhasish Ghosh (1):
  ARM: davinci: da850: changed SRAM allocator to shared ram.

 arch/arm/mach-davinci/board-da850-evm.c     |   12 +++++
 arch/arm/mach-davinci/da850.c               |   17 +++----
 arch/arm/mach-davinci/devices-da8xx.c       |   66 +++++++++++++++++++++++++++
 arch/arm/mach-davinci/dm355.c               |    6 ---
 arch/arm/mach-davinci/dm365.c               |    6 ---
 arch/arm/mach-davinci/dm644x.c              |    6 ---
 arch/arm/mach-davinci/dm646x.c              |    6 ---
 arch/arm/mach-davinci/include/mach/common.h |    2 -
 arch/arm/mach-davinci/include/mach/da8xx.h  |    3 ++
 arch/arm/mach-davinci/include/mach/sram.h   |    3 ++
 arch/arm/mach-davinci/sram.c                |   22 +++++++--
 drivers/uio/Kconfig                         |    1 +
 drivers/uio/uio_pruss.c                     |   24 +++++++---
 include/linux/platform_data/uio_pruss.h     |    3 +-
 14 files changed, 132 insertions(+), 45 deletions(-)

-- 
1.7.9.5

^ permalink raw reply

* [PATCH 4/4] mtd: nand: omap2: Add data correction support
From: Philip, Avinash @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349274589-11389-1-git-send-email-avinashphilip@ti.com>

ELM module can be used for error correction of BCH 4 & 8 bit. Also
support read & write page in one shot by adding custom read_page &
write_page methods. This helps in optimizing code.

New structure member "is_elm_used" is added to know the status of
whether the ELM module is used for error correction or not.

Note:
ECC layout of BCH8 uses 14 bytes for 512 byte of data to make compatible
with RBL ECC layout, even though the requirement was only 13 byte. This
results a common ecc layout across RBL, U-boot & Linux.

Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
---
:100644 100644 af511a9... 8fd6ddb... M	drivers/mtd/nand/omap2.c
:100644 100644 1a68c1e... 5b7054e... M	include/linux/platform_data/mtd-nand-omap2.h
 drivers/mtd/nand/omap2.c                     |  359 +++++++++++++++++++++++---
 include/linux/platform_data/mtd-nand-omap2.h |    1 +
 2 files changed, 328 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index af511a9..8fd6ddb 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -30,6 +30,7 @@
 #include <plat/dma.h>
 #include <plat/gpmc.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
+#include <linux/platform_data/elm.h>
 
 #define	DRIVER_NAME	"omap2-nand"
 #define	OMAP_NAND_TIMEOUT_MS	5000
@@ -114,6 +115,12 @@
 #define BCH8_MAX_ERROR		8	/* upto 8 bit coorectable */
 #define BCH4_MAX_ERROR		4	/* upto 4 bit correctable */
 
+#define SECTOR_BYTES		512
+/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
+#define BCH4_BIT_PAD		4
+#define BCH8_ECC_MAX		((SECTOR_BYTES + BCH8_ECC_OOB_BYTES) * 8)
+#define BCH4_ECC_MAX		((SECTOR_BYTES + BCH4_SIZE) * 8)
+
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
 /* Define some generic bad / good block scan pattern which are used
@@ -153,6 +160,8 @@ struct omap_nand_info {
 #ifdef CONFIG_MTD_NAND_OMAP_BCH
 	struct bch_control             *bch;
 	struct nand_ecclayout           ecclayout;
+	bool				is_elm_used;
+	struct device			*elm_dev;
 #endif
 };
 
@@ -892,6 +901,138 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
 	return stat;
 }
 
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+/**
+ * omap_elm_correct_data - corrects page data area in case error reported
+ * @mtd:	MTD device structure
+ * @dat:	page data
+ * @read_ecc:	ecc read from nand flash
+ * @calc_ecc:	ecc read from HW ECC registers
+ *
+ * Check the read ecc vector from OOB area to see the page is flashed.
+ * If flashed, check any error reported by checking calculated ecc vector.
+ * For non error page, calculated ecc will be zero. For error pages,
+ * a non-zero valid syndrome polynomial reported in calculated ecc vector.
+ * Pass this non-zero syndrome polynomial to 'elm_decode_bch_error_page'
+ * with elm error vector updated for error reported sectors.
+ * On returning from this function, elm error vector updated with
+ * - number of correctable errors, error location if correctable.
+ * - if pages are non-correctable, updated with elm error vector
+ *   error uncorrectable.
+ */
+static int omap_elm_correct_data(struct mtd_info *mtd, u_char *dat,
+				u_char *read_ecc, u_char *calc_ecc)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+			mtd);
+	int eccsteps = info->nand.ecc.steps;
+	int i , j, stat = 0;
+	int eccsize, eccflag, size;
+	struct elm_errorvec err_vec[ERROR_VECTOR_MAX];
+	u_char *ecc_vec = calc_ecc;
+	enum bch_ecc type;
+	bool is_error_reported = false;
+
+	/* initialize elm error vector to zero */
+	memset(err_vec, 0, sizeof(err_vec));
+	if (info->nand.ecc.strength == BCH8_MAX_ERROR) {
+		size = BCH8_SIZE;
+		eccsize = BCH8_ECC_OOB_BYTES;
+		type = BCH8_ECC;
+	} else {
+		size = BCH4_SIZE;
+		eccsize = BCH4_SIZE;
+		type = BCH4_ECC;
+	}
+
+	for (i = 0; i < eccsteps ; i++) {
+		eccflag = 0;	/* initialize eccflag */
+
+		for (j = 0; (j < eccsize); j++) {
+			if (read_ecc[j] != 0xFF) {
+				eccflag = 1;	/* data area is flashed */
+				break;
+			}
+		}
+
+		/* check calculated ecc if data area is flashed */
+		if (eccflag == 1) {
+			eccflag = 0;
+			/*
+			 * check any error reported, in case of error
+			 * non zero ecc reported.
+			 */
+			for (j = 0; (j < eccsize); j++) {
+				if (calc_ecc[j] != 0) {
+					/* non zero ecc, error present */
+					eccflag = 1;
+					break;
+				}
+			}
+		}
+
+		/* update elm error vector */
+		if (eccflag == 1) {
+			err_vec[i].error_reported = true;
+			is_error_reported = true;
+		}
+
+		/* update the ecc vector */
+		calc_ecc = calc_ecc + size;
+		read_ecc = read_ecc + size;
+	}
+
+	/* Check if any error reported */
+	if (!is_error_reported)
+		return 0;
+
+	/* decode BCH error using ELM module */
+	elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec);
+
+	for (i = 0; i < eccsteps; i++) {
+		if (err_vec[i].error_reported) {
+			for (j = 0; j < err_vec[i].error_count; j++) {
+				u32 bit_pos, byte_pos, error_max, pos;
+
+				if (type == BCH8_ECC)
+					error_max = BCH8_ECC_MAX;
+				else
+					error_max = BCH4_ECC_MAX;
+
+				if (info->nand.ecc.strength == BCH8_MAX_ERROR)
+					pos = err_vec[i].error_loc[j];
+				else
+					/* add 4 to take care 4 bit padding */
+					pos = err_vec[i].error_loc[j] +
+						BCH4_BIT_PAD;
+
+				/* calculate bit position of error */
+				bit_pos = pos % 8;
+				/* calculate byte position of error */
+				byte_pos = (error_max - pos - 1) / 8;
+
+				if (pos < error_max)
+					dat[byte_pos] ^= 1 << bit_pos;
+				/* else, not interested to correct ecc */
+			}
+
+			/* update number of correctable errors */
+			stat += err_vec[i].error_count;
+		}
+
+		/* update page data with sector size */
+		dat += info->nand.ecc.size;
+	}
+
+	for (i = 0; i < eccsteps; i++)
+		/* return error if uncorrectable error present */
+		if (err_vec[i].error_uncorrectable)
+			return -EINVAL;
+
+	return stat;
+}
+#endif
+
 /**
  * omap_calcuate_ecc - Generate non-inverted ECC bytes.
  * @mtd: MTD device structure
@@ -1039,14 +1180,45 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
 
 	nerrors = info->nand.ecc.strength;
 	dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+	if (info->is_elm_used) {
+		/*
+		 * Program GPMC to perform correction on (steps * 512) byte
+		 * sector at a time.
+		 */
+		gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width,
+				info->nand.ecc.steps, nerrors);
+		return;
+	}
+#endif
 	/*
-	 * Program GPMC to perform correction on one 512-byte sector at a time.
-	 * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
-	 * gives a slight (5%) performance gain (but requires additional code).
+	 * Program GPMC to perform correction on one 512-byte sector at
+	 * a time.
 	 */
-	(void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors);
+	(void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1,
+				nerrors);
 }
 
+
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+/**
+ * omap3_calculate_ecc_bch - Generate bytes of ECC bytes
+ * @mtd:	MTD device structure
+ * @dat:	The pointer to data on which ecc is computed
+ * @ecc_code:	The ecc_code buffer
+ *
+ * support reading og BCH4/8 ecc vectors for the page
+ */
+static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat,
+				    u_char *ecc_code)
+{
+	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
+			mtd);
+
+	return gpmc_calculate_ecc_bch(info->gpmc_cs, dat, ecc_code);
+}
+#endif
+
 /**
  * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes
  * @mtd: MTD device structure
@@ -1121,6 +1293,90 @@ static void omap3_free_bch(struct mtd_info *mtd)
 	}
 }
 
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+/**
+ * omap_write_page_bch - BCH ecc based write page function for entire page
+ * @mtd:		mtd info structure
+ * @chip:		nand chip info structure
+ * @buf:		data buffer
+ * @oob_required:	must write chip->oob_poi to OOB
+ *
+ * Custom write page method evolved to support multi sector writing in one shot
+ */
+static int omap_write_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
+				  const uint8_t *buf, int oob_required)
+{
+	int i;
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
+	uint32_t *eccpos = chip->ecc.layout->eccpos;
+
+	/*
+	 * setting ecc vector with zero to support RBL compatibility.
+	 * RBL requires 14 byte of ecc with 14 byte as zero
+	 * even though BCH8 requires only 13 byte of ecc bytes.
+	 */
+	memset(ecc_calc, 0x0, chip->ecc.total);
+	chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->ecc.calculate(mtd, buf, &ecc_calc[0]);
+
+	for (i = 0; i < chip->ecc.total; i++)
+		chip->oob_poi[eccpos[i]] = ecc_calc[i];
+
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+	return 0;
+}
+
+/**
+ * omap_read_page_bch - BCH ecc based page read function for entire page
+ * @mtd:		mtd info structure
+ * @chip:		nand chip info structure
+ * @buf:		buffer to store read data
+ * @oob_required:	caller requires OOB data read to chip->oob_poi
+ * @page:		page number to read
+ *
+ * For BCH ecc scheme, GPMC used for syndrome calculation and ELM module
+ * used for error correction.
+ * Custom method evolved to support ELM error correction. On reading page
+ * data area is read along with OOB data with ecc engine enabled. ecc vector
+ * updated after read of OOB data. For non error pages ecc vector reported as
+ * zero.
+ */
+static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
+				uint8_t *buf, int oob_required, int page)
+{
+	uint8_t *ecc_calc = chip->buffers->ecccalc;
+	uint8_t *ecc_code = chip->buffers->ecccode;
+	uint32_t *eccpos = chip->ecc.layout->eccpos;
+	uint8_t *oob = &chip->oob_poi[eccpos[0]];
+	uint32_t oob_pos = mtd->writesize + chip->ecc.layout->eccpos[0];
+	int stat;
+
+	/* enable GPMC ecc engine */
+	chip->ecc.hwctl(mtd, NAND_ECC_READ);
+	/* read data */
+	chip->read_buf(mtd, buf, mtd->writesize);
+
+	/* read oob bytes */
+	chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, -1);
+	chip->read_buf(mtd, oob, chip->ecc.total);
+
+	/* calculate ecc bytes */
+	chip->ecc.calculate(mtd, buf, ecc_calc);
+
+	memcpy(ecc_code, &chip->oob_poi[eccpos[0]], chip->ecc.total);
+
+	stat = chip->ecc.correct(mtd, buf, ecc_code, ecc_calc);
+
+	if (stat < 0)
+		mtd->ecc_stats.failed++;
+	else
+		mtd->ecc_stats.corrected += stat;
+
+	return 0;
+}
+#endif
+
 /**
  * omap3_init_bch - Initialize BCH ECC
  * @mtd: MTD device structure
@@ -1146,35 +1402,62 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 		goto fail;
 	}
 
-	/* initialize GPMC BCH engine */
-	ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
-	if (ret)
-		goto fail;
-
-	/* software bch library is only used to detect and locate errors */
-	info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
-	if (!info->bch)
-		goto fail;
+	info->nand.ecc.size = 512;
+	info->nand.ecc.hwctl = omap3_enable_hwecc_bch;
+	info->nand.ecc.mode = NAND_ECC_HW;
+	info->nand.ecc.strength = hw_errors;
 
-	info->nand.ecc.size    = 512;
-	info->nand.ecc.hwctl   = omap3_enable_hwecc_bch;
-	info->nand.ecc.correct = omap3_correct_data_bch;
-	info->nand.ecc.mode    = NAND_ECC_HW;
+	if (info->is_elm_used && (mtd->writesize <= 4096)) {
+		enum bch_ecc bch_type;
 
-	/*
-	 * The number of corrected errors in an ecc block that will trigger
-	 * block scrubbing defaults to the ecc strength (4 or 8).
-	 * Set mtd->bitflip_threshold here to define a custom threshold.
-	 */
+		if (hw_errors == BCH8_MAX_ERROR) {
+			bch_type = BCH8_ECC;
+			info->nand.ecc.bytes = BCH8_SIZE;
+		} else {
+			bch_type = BCH4_ECC;
+			info->nand.ecc.bytes = BCH4_SIZE;
+		}
 
-	if (max_errors == 8) {
-		info->nand.ecc.strength  = 8;
-		info->nand.ecc.bytes     = 13;
-		info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
+		info->nand.ecc.correct = omap_elm_correct_data;
+		info->nand.ecc.calculate = omap3_calculate_ecc_bch;
+		info->nand.ecc.read_page = omap_read_page_bch;
+		info->nand.ecc.write_page = omap_write_page_bch;
+		info->elm_dev = elm_request(bch_type);
+		if (!info->elm_dev) {
+			pr_err("Request to elm module failed\n");
+			goto fail;
+		}
 	} else {
-		info->nand.ecc.strength  = 4;
-		info->nand.ecc.bytes     = 7;
-		info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
+
+		/* initialize GPMC BCH engine */
+		ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
+		if (ret)
+			goto fail;
+
+		/*
+		 * software bch library is only used to detect and
+		 * locateerrors
+		 */
+		info->bch = init_bch(13, max_errors,
+				0x201b /* hw polynomial */);
+		if (!info->bch)
+			goto fail;
+
+		info->nand.ecc.correct = omap3_correct_data_bch;
+
+		/*
+		 * The number of corrected errors in an ecc block that will
+		 * trigger block scrubbing defaults to the ecc strength (4 or 8)
+		 * Set mtd->bitflip_threshold here to define a custom threshold.
+		 */
+
+		if (max_errors == 8) {
+			info->nand.ecc.bytes = 13;
+			info->nand.ecc.calculate = omap3_calculate_ecc_bch8;
+		} else {
+			info->nand.ecc.bytes = 7;
+			info->nand.ecc.calculate = omap3_calculate_ecc_bch4;
+		}
 	}
 
 	pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors);
@@ -1190,7 +1473,7 @@ fail:
  */
 static int omap3_init_bch_tail(struct mtd_info *mtd)
 {
-	int i, steps;
+	int i, steps, offset;
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
 	struct nand_ecclayout *layout = &info->ecclayout;
@@ -1212,11 +1495,20 @@ static int omap3_init_bch_tail(struct mtd_info *mtd)
 		goto fail;
 	}
 
+	/* ECC layout compatible with RBL for BCH8 */
+	if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
+		offset = 2;
+	else
+		offset = mtd->oobsize - layout->eccbytes;
 	/* put ecc bytes at oob tail */
 	for (i = 0; i < layout->eccbytes; i++)
-		layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i;
+		layout->eccpos[i] = offset + i;
+
+	if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE))
+		layout->oobfree[0].offset = 2 + layout->eccbytes * steps;
+	else
+		layout->oobfree[0].offset = 2;
 
-	layout->oobfree[0].offset = 2;
 	layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
 	info->nand.ecc.layout = layout;
 
@@ -1279,6 +1571,9 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 
 	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+	info->is_elm_used	= pdata->is_elm_used;
+#endif
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 1a68c1e..5b7054e 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -28,6 +28,7 @@ struct omap_nand_platform_data {
 	int			devsize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
+	bool			is_elm_used;
 };
 
 /* minimum size for IO mapping */
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 3/4] ARM: OMAP2: gpmc: Add support for BCH ECC scheme
From: Philip, Avinash @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349274589-11389-1-git-send-email-avinashphilip@ti.com>

Add support for BCH ECC scheme to gpmc driver and also enabling multi
sector read/write. This helps in doing single shot NAND page read and
write.

ECC engine configurations
BCH 4 bit support
1. write => ECC engine configured in wrap mode 6 and with ecc_size0 as 32.
2. read  => ECC engine configured in wrap mode 1 and with ecc_size0 as
13 and ecc_size1 as 1.

BCH 8 bit support
1. write => ECC engine configured in wrap mode 6 and with ecc_size0 as 32.
2. read  => ECC engine configured in wrap mode 1 and with ecc_size0 as
26 and ecc_size1 as 2.

Note: For BCH8 ECC bytes set to 14 to make compatible with RBL.

Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
---
:100644 100644 72428bd... c9bc3cf... M	arch/arm/mach-omap2/gpmc.c
:100644 100644 2e6e259... c916510... M	arch/arm/plat-omap/include/plat/gpmc.h
 arch/arm/mach-omap2/gpmc.c             |  120 +++++++++++++++++++++++++++++---
 arch/arm/plat-omap/include/plat/gpmc.h |    1 +
 2 files changed, 112 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 72428bd..c9bc3cf 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
@@ -83,6 +84,18 @@
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
 
+/* GPMC ecc engine settings for read */
+#define BCH_WRAPMODE_1		1	/* BCH wrap mode 6 */
+#define BCH8R_ECC_SIZE0		0x1a	/* ecc_size0 = 26 */
+#define BCH8R_ECC_SIZE1		0x2	/* ecc_size1 = 2 */
+#define BCH4R_ECC_SIZE0		0xd	/* ecc_size0 = 13 */
+#define BCH4R_ECC_SIZE1		0x1	/* ecc_size1 = 1 4bit padding in BCH4 */
+
+/* GPMC ecc engine settings for write */
+#define BCH_WRAPMODE_6		6	/* BCH wrap mode 6 */
+#define BCH_ECC_SIZE0		0x0	/* ecc_size0 = 0, no oob protection */
+#define BCH_ECC_SIZE1		0x20	/* ecc_size1 = 32 */
+
 /* XXX: Only NAND irq has been considered,currently these are the only ones used
  */
 #define	GPMC_NR_IRQ		2
@@ -1119,7 +1132,8 @@ EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch);
 int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
 			  int nerrors)
 {
-	unsigned int val;
+	unsigned int val, wr_mode;
+	unsigned int ecc_size1, ecc_size0;
 
 	/* check if ecc module is in use */
 	if (gpmc_ecc_used != -EINVAL)
@@ -1130,18 +1144,35 @@ int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
 	/* clear ecc and enable bits */
 	gpmc_write_reg(GPMC_ECC_CONTROL, 0x1);
 
-	/*
-	 * When using BCH, sector size is hardcoded to 512 bytes.
-	 * Here we are using wrapping mode 6 both for reading and writing, with:
-	 *  size0 = 0  (no additional protected byte in spare area)
-	 *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
-	 */
-	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12));
+	/*  When using BCH, sector size is hard coded to 512 bytes. */
+	if ((mode == NAND_ECC_READ) && (nsectors != 1)) {
+		/*
+		 * Here we are using wrapping mode 1 for reading, for
+		 * supporting multi sector reading.
+		 * Read mode, ECC engine enabled for valid ecc_size0 nibbles
+		 * & disabled for ecc_size1 nibbles.
+		 */
+		ecc_size0 = (nerrors == 8) ? BCH8R_ECC_SIZE0 : BCH4R_ECC_SIZE0;
+		ecc_size1 = (nerrors == 8) ? BCH8R_ECC_SIZE1 : BCH4R_ECC_SIZE1;
+		wr_mode = BCH_WRAPMODE_1;
+	} else {
+		/*
+		 * Here we are using wrapping mode 6 for writing,
+		 * ECC engine enabled for valid ecc_size0 nibbles
+		 * & disabled for ecc_size1 nibbles.
+		 */
+		ecc_size0 = BCH_ECC_SIZE0;
+		ecc_size1 = BCH_ECC_SIZE1;
+		wr_mode = BCH_WRAPMODE_6;
+	}
+
+	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (ecc_size1 << 22) |
+			(ecc_size0 << 12));
 
 	/* BCH configuration */
 	val = ((1                        << 16) | /* enable BCH */
 	       (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
-	       (0x06                     <<  8) | /* wrap mode = 6 */
+	       (wr_mode                  <<  8) | /* wrap mode = 6 or 1 */
 	       (dev_width                <<  7) | /* bus width */
 	       (((nsectors-1) & 0x7)     <<  4) | /* number of sectors */
 	       (cs                       <<  1) | /* ECC CS */
@@ -1154,6 +1185,77 @@ int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
 EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch);
 
 /**
+ * gpmc_calculate_ecc_bch	- Generate ecc bytes per block of 512 data bytes for entire page
+ * @cs:  chip select number
+ * @dat: The pointer to data on which ECC is computed
+ * @ecc: The ECC output buffer
+ */
+int gpmc_calculate_ecc_bch(int cs, const u_char *dat, u_char *ecc)
+{
+	int i, eccbchtsel;
+	u32 nsectors, reg, bch_val1, bch_val2, bch_val3, bch_val4;
+
+	if (gpmc_ecc_used != cs)
+		return -EINVAL;
+
+	/* read number of sectors for ecc to be calculated */
+	nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1;
+	/*
+	 * find BCH scheme used
+	 * 0 -> BCH4
+	 * 1 -> BCH8
+	 */
+	eccbchtsel = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 12) & 0x3);
+
+	/* update ecc bytes for entire page */
+	for (i = 0; i < nsectors; i++) {
+
+		reg = GPMC_ECC_BCH_RESULT_0 + 16 * i;
+
+		/* Read hw-computed remainder */
+		bch_val1 = gpmc_read_reg(reg + 0);
+		bch_val2 = gpmc_read_reg(reg + 4);
+		if (eccbchtsel) {
+			bch_val3 = gpmc_read_reg(reg + 8);
+			bch_val4 = gpmc_read_reg(reg + 12);
+		}
+
+		if (eccbchtsel) {
+			/* BCH8 ecc scheme */
+			*ecc++ = (bch_val4 & 0xFF);
+			*ecc++ = ((bch_val3 >> 24) & 0xFF);
+			*ecc++ = ((bch_val3 >> 16) & 0xFF);
+			*ecc++ = ((bch_val3 >> 8) & 0xFF);
+			*ecc++ = (bch_val3 & 0xFF);
+			*ecc++ = ((bch_val2 >> 24) & 0xFF);
+			*ecc++ = ((bch_val2 >> 16) & 0xFF);
+			*ecc++ = ((bch_val2 >> 8) & 0xFF);
+			*ecc++ = (bch_val2 & 0xFF);
+			*ecc++ = ((bch_val1 >> 24) & 0xFF);
+			*ecc++ = ((bch_val1 >> 16) & 0xFF);
+			*ecc++ = ((bch_val1 >> 8) & 0xFF);
+			*ecc++ = (bch_val1 & 0xFF);
+			/* 14th byte of ecc not used */
+			*ecc++ = 0;
+		} else {
+			/* BCH4 ecc scheme */
+			*ecc++ = ((bch_val2 >> 12) & 0xFF);
+			*ecc++ = ((bch_val2 >> 4) & 0xFF);
+			*ecc++ = (((bch_val2 & 0xF) << 4) |
+					((bch_val1 >> 28) & 0xF));
+			*ecc++ = ((bch_val1 >> 20) & 0xFF);
+			*ecc++ = ((bch_val1 >> 12) & 0xFF);
+			*ecc++ = ((bch_val1 >> 4) & 0xFF);
+			*ecc++ = ((bch_val1 & 0xF) << 4);
+		}
+	}
+
+	gpmc_ecc_used = -EINVAL;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch);
+
+/**
  * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes
  * @cs:  chip select number
  * @dat: The pointer to data on which ecc is computed
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 2e6e259..c916510 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -185,6 +185,7 @@ int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
 			  int nerrors);
 int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc);
 int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc);
+int gpmc_calculate_ecc_bch(int cs, const u_char *dat, u_char *ecc);
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #endif
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 2/4] mtd: devices: elm: Add support for ELM error correction
From: Philip, Avinash @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349274589-11389-1-git-send-email-avinashphilip@ti.com>

Platforms containing the ELM module can be used to correct errors
reported by BCH 4, 8 & 16 bit ECC scheme. For now only 4 & 8 bit
support is added.

Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
---
:000000 100644 0000000... b88ee83... A	Documentation/devicetree/bindings/mtd/elm.txt
:100644 100644 395733a... 0f6a94b... M	drivers/mtd/devices/Makefile
:000000 100644 0000000... 802b572... A	drivers/mtd/devices/elm.c
:000000 100644 0000000... eb53163... A	include/linux/platform_data/elm.h
 Documentation/devicetree/bindings/mtd/elm.txt |   18 +
 drivers/mtd/devices/Makefile                  |    4 +-
 drivers/mtd/devices/elm.c                     |  440 +++++++++++++++++++++++++
 include/linux/platform_data/elm.h             |   60 ++++
 4 files changed, 521 insertions(+), 1 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/elm.txt b/Documentation/devicetree/bindings/mtd/elm.txt
new file mode 100644
index 0000000..b88ee83
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/elm.txt
@@ -0,0 +1,18 @@
+Error location module
+
+Required properties:
+- compatible: Must be "ti,elm"
+- reg: physical base address and size of the registers map.
+- interrupts: Interrupt number for the elm.
+- interrupt-parent: The parent interrupt controller
+
+Optional properties:
+- ti,hwmods: Name of the hwmod associated to the elm
+
+Example:
+elm: elm at 0 {
+	compatible	= "ti,elm";
+	reg = <0x48080000 0x2000>;
+	interrupt-parent = <&intc>;
+	interrupts = <4>;
+};
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 395733a..0f6a94b 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,8 +17,10 @@ obj-$(CONFIG_MTD_LART)		+= lart.o
 obj-$(CONFIG_MTD_BLOCK2MTD)	+= block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
+obj-$(CONFIG_MTD_NAND_OMAP2)	+= elm.o
 obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_BCM47XXSFLASH)	+= bcm47xxsflash.o
 
-CFLAGS_docg3.o			+= -I$(src)
\ No newline at end of file
+
+CFLAGS_docg3.o			+= -I$(src)
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
new file mode 100644
index 0000000..802b572
--- /dev/null
+++ b/drivers/mtd/devices/elm.c
@@ -0,0 +1,440 @@
+/*
+ * Error Location Module
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_data/elm.h>
+
+#define ELM_IRQSTATUS			0x018
+#define ELM_IRQENABLE			0x01c
+#define ELM_LOCATION_CONFIG		0x020
+#define ELM_PAGE_CTRL			0x080
+#define ELM_SYNDROME_FRAGMENT_0		0x400
+#define ELM_SYNDROME_FRAGMENT_6		0x418
+#define ELM_LOCATION_STATUS		0x800
+#define ELM_ERROR_LOCATION_0		0x880
+
+/* ELM Interrupt Status Register */
+#define INTR_STATUS_PAGE_VALID		BIT(8)
+
+/* ELM Interrupt Enable Register */
+#define INTR_EN_PAGE_MASK		BIT(8)
+
+/* ELM Location Configuration Register */
+#define ECC_BCH_LEVEL_MASK		0x3
+
+/* ELM syndrome */
+#define ELM_SYNDROME_VALID		BIT(16)
+
+/* ELM_LOCATION_STATUS Register */
+#define ECC_CORRECTABLE_MASK		BIT(8)
+#define ECC_NB_ERRORS_MASK		0x1f
+
+/* ELM_ERROR_LOCATION_0-15 Registers */
+#define ECC_ERROR_LOCATION_MASK		0x1fff
+
+#define ELM_ECC_SIZE			0x7ff
+
+#define SYNDROME_FRAGMENT_REG_SIZE	0x40
+#define ERROR_LOCATION_SIZE		0x100
+#define MAX_BCH_ELM_ERROR		16
+#define ELM_FRAGMENT_REG		7
+
+typedef u32 syn_t[ELM_FRAGMENT_REG];
+typedef u32 elm_error_t[MAX_BCH_ELM_ERROR];
+
+struct elm_info {
+	struct device *dev;
+	void __iomem *elm_base;
+	struct completion elm_completion;
+	struct list_head list;
+	enum bch_ecc bch_type;
+};
+
+static LIST_HEAD(elm_devices);
+
+static void elm_write_reg(void *offset, u32 val)
+{
+	writel(val, offset);
+}
+
+static u32 elm_read_reg(void *offset)
+{
+	return readl(offset);
+}
+
+/**
+ * elm_config - Configure ELM module
+ * @info:	elm info
+ */
+static void elm_config(struct elm_info *info)
+{
+	u32 reg_val;
+
+	reg_val = (info->bch_type & ECC_BCH_LEVEL_MASK) | (ELM_ECC_SIZE << 16);
+	elm_write_reg(info->elm_base + ELM_LOCATION_CONFIG, reg_val);
+}
+
+/**
+ * elm_configure_page_mode - Enable/Disable page mode
+ * @info:	elm info
+ * @index:	index number of syndrome fragment vector
+ * @enable:	enable/disable flag for page mode
+ *
+ * Enable page mode for syndrome fragment index
+ */
+static void elm_configure_page_mode(struct elm_info *info, int index,
+		bool enable)
+{
+	u32 reg_val;
+
+	reg_val = elm_read_reg(info->elm_base + ELM_PAGE_CTRL);
+	if (enable)
+		reg_val |= BIT(index);	/* enable page mode */
+	else
+		reg_val &= ~BIT(index);	/* disable page mode */
+
+	elm_write_reg(info->elm_base + ELM_PAGE_CTRL, reg_val);
+}
+
+static void rearrange_bch4(u8 *syndrome)
+{
+	/*
+	 * BCH4 has 52 bit used for ecc, but OOB stored with
+	 * nibble 0 appended, removes appended 0 nibble
+	 */
+	u64 *dst = (u64 *)syndrome;
+	*dst >>= 4;
+}
+
+/**
+ * elm_reverse_eccdata - Reverse ecc data
+ * @info:	elm info
+ * @ecc_data:	buffer for calculated ecc
+ * @syndrome:	buffer for syndrome polynomial
+ *
+ * ecc_data has to be reversed for syndrome vector
+ */
+static void elm_reverse_eccdata(struct elm_info *info, u8 *ecc_data,
+		u8 *syndrome)
+{
+	int i;
+	int bch_size = info->bch_type ? BCH8_ECC_OOB_BYTES : BCH4_SIZE;
+
+	for (i = 0; i < bch_size; i++)
+		syndrome[bch_size - 1 - i] = ecc_data[i];
+
+	/*
+	 * syndrome polynomial to be rearranged for BCH 4 ecc scheme as 52
+	 * bits being used and 4 bits being appended in syndrome vector
+	 */
+	if (info->bch_type == BCH4_ECC)
+		rearrange_bch4(syndrome);
+}
+
+/**
+ * elm_load_syndrome - Load ELM syndrome reg
+ * @info:	elm info
+ * @index:	syndrome fragment index
+ * @syndrome:	Syndrome polynomial
+ *
+ * Load syndrome fragment registers with syndrome polynomial
+ */
+static void elm_load_syndrome(struct elm_info *info, int index, u8 *syndrome)
+{
+	int i;
+	int max = info->bch_type ? BCH8_SYNDROME_SIZE : BCH4_SYNDROME_SIZE;
+	void *syn_frag_base = info->elm_base + ELM_SYNDROME_FRAGMENT_0;
+	syn_t *syn_fragment;
+	u32 reg_val;
+
+	elm_configure_page_mode(info, index, true);
+	syn_fragment = syn_frag_base + SYNDROME_FRAGMENT_REG_SIZE * index;
+
+	for (i = 0; i < max; i++) {
+		reg_val = syndrome[0] | syndrome[1] << 8 | syndrome[2] << 16 |
+			syndrome[3] << 24;
+		elm_write_reg(*syn_fragment + i, reg_val);
+		/* Update syndrome polynomial pointer */
+		syndrome += 4;
+	}
+}
+
+/**
+ * elm_start_processing - start elm syndrome processing
+ * @info:	elm info
+ * @err_vec:	elm error vectors
+ *
+ * Set syndrome valid bit for syndrome fragment registers for which
+ * elm syndrome fragment registers are loaded. This enables elm module
+ * to start processing syndrome vectors.
+ */
+static void elm_start_processing(struct elm_info *info,
+		struct elm_errorvec *err_vec)
+{
+	int i;
+	void *offset;
+	u32 reg_val;
+
+	/*
+	 * Set syndrome vector valid so that ELM module will process it for
+	 * vectors error is reported
+	 */
+	for (i = 0; i < ERROR_VECTOR_MAX; i++) {
+		if (err_vec[i].error_reported) {
+			offset = info->elm_base + ELM_SYNDROME_FRAGMENT_6 + i *
+				SYNDROME_FRAGMENT_REG_SIZE;
+			reg_val = elm_read_reg(offset);
+			reg_val |= ELM_SYNDROME_VALID;
+			elm_write_reg(offset, reg_val);
+		}
+	}
+}
+
+/**
+ * elm_error_correction - locate correctable error position
+ * @info:	elm info
+ * @err_vec:	elm error vectors
+ *
+ * On completion of processing by elm module, error location status
+ * register updated with correctable/uncorrectable error information.
+ * In case of correctable errors, number of errors located from
+ * elm location status register & read the these many positions from
+ * elm error location register.
+ */
+static void elm_error_correction(struct elm_info *info,
+		struct elm_errorvec *err_vec)
+{
+	int i, j, errors = 0;
+	void *err_loc_base = info->elm_base + ELM_ERROR_LOCATION_0;
+	elm_error_t *err_loc;
+	void *offset;
+	u32 reg_val;
+
+	for (i = 0; i < ERROR_VECTOR_MAX; i++) {
+		/* check error reported */
+		if (err_vec[i].error_reported) {
+			offset = info->elm_base + ELM_LOCATION_STATUS +
+				i * ERROR_LOCATION_SIZE;
+			reg_val = elm_read_reg(offset);
+			/* check correctable error or not */
+			if (reg_val & ECC_CORRECTABLE_MASK) {
+				err_loc = err_loc_base +
+					i * ERROR_LOCATION_SIZE;
+				/* read count of correctable errors */
+				err_vec[i].error_count = reg_val &
+					ECC_NB_ERRORS_MASK;
+
+				/* update the error locations in error vector */
+				for (j = 0; j < err_vec[i].error_count; j++) {
+
+					reg_val = elm_read_reg(*err_loc + j);
+					err_vec[i].error_loc[j] = reg_val &
+						ECC_ERROR_LOCATION_MASK;
+				}
+
+				errors += err_vec[i].error_count;
+			} else {
+				err_vec[i].error_uncorrectable++;
+			}
+
+			/* clearing interrupts for processed error vectors */
+			elm_write_reg(info->elm_base + ELM_IRQSTATUS, BIT(i));
+
+			/* disable page mode */
+			elm_configure_page_mode(info, i, false);
+		}
+	}
+
+	return;
+}
+
+/**
+ * elm_decode_bch_error_page - Locate error position
+ * @info:	elm info
+ * @ecc_calc:	calculated ECC bytes from GPMC
+ * @err_vec:	elm error vectors
+ *
+ * Called with one or greater reported and is vectors with error reported
+ * is updated in err_vec[].error_reported
+ */
+void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
+		struct elm_errorvec *err_vec)
+{
+	int i;
+	u8 syndrome[BCH_MAX_ECC_BYTES_PER_SECTOR] = {0}, *syn_p;
+	struct elm_info *info = dev_get_drvdata(dev);
+	u32 reg_val;
+
+	/* enable page mode interrupt */
+	reg_val = elm_read_reg(info->elm_base + ELM_IRQSTATUS);
+	elm_write_reg(info->elm_base + ELM_IRQSTATUS,
+			reg_val & INTR_STATUS_PAGE_VALID);
+	elm_write_reg(info->elm_base + ELM_IRQENABLE, INTR_EN_PAGE_MASK);
+
+	syn_p = syndrome;
+	for (i = 0; i < ERROR_VECTOR_MAX; i++) {
+		if (err_vec[i].error_reported) {
+			elm_reverse_eccdata(info, ecc_calc, syn_p);
+			elm_load_syndrome(info, i, syn_p);
+		}
+
+		ecc_calc += info->bch_type ? BCH8_SIZE : BCH4_SIZE;
+		syn_p += OOB_SECTOR_SIZE;
+	}
+
+	elm_start_processing(info, err_vec);
+
+	/*
+	 * In case of error reported, wait for ELM module to finish
+	 * locating error correction
+	 */
+	wait_for_completion(&info->elm_completion);
+
+	/* disable page mode interrupt */
+	reg_val = elm_read_reg(info->elm_base + ELM_IRQENABLE);
+	elm_write_reg(info->elm_base + ELM_IRQENABLE,
+			reg_val & ~INTR_EN_PAGE_MASK);
+	elm_error_correction(info, err_vec);
+}
+EXPORT_SYMBOL(elm_decode_bch_error_page);
+
+static irqreturn_t elm_isr(int this_irq, void *dev_id)
+{
+	u32 reg_val;
+	struct elm_info *info = dev_id;
+
+	reg_val = elm_read_reg(info->elm_base + ELM_IRQSTATUS);
+
+	/* all error vectors processed */
+	if (reg_val & INTR_STATUS_PAGE_VALID) {
+		elm_write_reg(info->elm_base + ELM_IRQSTATUS,
+				reg_val & INTR_STATUS_PAGE_VALID);
+		complete(&info->elm_completion);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+struct device *elm_request(enum bch_ecc bch_type)
+{
+	struct elm_info *info;
+
+	list_for_each_entry(info, &elm_devices, list) {
+		if (info && info->dev) {
+				info->bch_type = bch_type;
+				elm_config(info);
+				return info->dev;
+		}
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(elm_request);
+
+static int __devinit elm_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct resource *res, *irq;
+	struct elm_info *info;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	info->dev = &pdev->dev;
+
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "no irq resource defined\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		return -ENODEV;
+	}
+
+
+	info->elm_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!info->elm_base)
+		return -EADDRNOTAVAIL;
+
+
+	ret = devm_request_irq(&pdev->dev, irq->start, elm_isr, 0,
+			pdev->name, info);
+	if (ret) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", irq->start);
+		return ret;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+	if (pm_runtime_get_sync(&pdev->dev)) {
+		ret = -EINVAL;
+		pm_runtime_disable(&pdev->dev);
+		dev_err(&pdev->dev, "can't enable clock\n");
+		return ret;
+	}
+
+	init_completion(&info->elm_completion);
+	INIT_LIST_HEAD(&info->list);
+	list_add(&info->list, &elm_devices);
+	platform_set_drvdata(pdev, info);
+	return ret;
+}
+
+static int __devexit elm_remove(struct platform_device *pdev)
+{
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+
+#ifdef CONFIG_OF
+static const struct of_device_id elm_of_match[] = {
+	{ .compatible = "ti,elm" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, elm_of_match);
+#endif
+
+static struct platform_driver elm_driver = {
+	.driver		= {
+		.name	= "elm",
+		.of_match_table = of_match_ptr(elm_of_match),
+		.owner	= THIS_MODULE,
+	},
+	.probe		= elm_probe,
+	.remove		= __devexit_p(elm_remove),
+};
+
+module_platform_driver(elm_driver);
+
+MODULE_DESCRIPTION("ELM driver for BCH error correction");
+MODULE_AUTHOR("Texas Instruments");
+MODULE_ALIAS("platform: elm");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
new file mode 100644
index 0000000..eb53163
--- /dev/null
+++ b/include/linux/platform_data/elm.h
@@ -0,0 +1,60 @@
+/*
+ * BCH Error Location Module
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ELM_H
+#define __ELM_H
+
+enum bch_ecc {
+	BCH4_ECC = 0,
+	BCH8_ECC,
+	BCH16_ECC,
+};
+
+/* ELM support 8 error syndrome process */
+#define ERROR_VECTOR_MAX		8
+#define OOB_SECTOR_SIZE			16
+
+#define BCH_MAX_ECC_BYTES_PER_SECTOR	(OOB_SECTOR_SIZE * ERROR_VECTOR_MAX)
+
+#define BCH8_ECC_OOB_BYTES		13
+/* RBL requires 14 byte even though BCH8 uses only 13 byte */
+#define BCH8_SIZE			(BCH8_ECC_OOB_BYTES + 1)
+#define BCH4_SIZE			7
+
+#define	BCH8_SYNDROME_SIZE		4	/* 13 bytes of ecc */
+#define	BCH4_SYNDROME_SIZE		2	/* 7 bytes of ecc */
+
+/**
+ * struct elm_errorvec - error vector for elm
+ * @error_reported:		set true for vectors error is reported
+ *
+ * @error_count:		number of correctable errors in the sector
+ * @error_uncorrectable:	number of uncorrectable errors
+ * @error_loc:			buffer for error location
+ *
+ */
+struct elm_errorvec {
+	bool error_reported;
+	int error_count;
+	int error_uncorrectable;
+	int error_loc[ERROR_VECTOR_MAX];
+};
+
+void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
+		struct elm_errorvec *err_vec);
+struct device *elm_request(enum bch_ecc bch_type);
+#endif /* __ELM_H */
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 1/4] mtd: nand: omap2: Update nerrors using ecc.strength
From: Philip, Avinash @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349274589-11389-1-git-send-email-avinashphilip@ti.com>

Update number of errors using nand ecc strength.
Also add macro definitions BCH8_ERROR_MAX & BCH4_ERROR_MAX

Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
---
:100644 100644 5b31386... af511a9... M	drivers/mtd/nand/omap2.c
 drivers/mtd/nand/omap2.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5b31386..af511a9 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -111,6 +111,9 @@
 #define	ECCCLEAR			0x100
 #define	ECC1				0x1
 
+#define BCH8_MAX_ERROR		8	/* upto 8 bit coorectable */
+#define BCH4_MAX_ERROR		4	/* upto 4 bit correctable */
+
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
 /* Define some generic bad / good block scan pattern which are used
@@ -1034,7 +1037,7 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
 						   mtd);
 	struct nand_chip *chip = mtd->priv;
 
-	nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
+	nerrors = info->nand.ecc.strength;
 	dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
 	/*
 	 * Program GPMC to perform correction on one 512-byte sector at a time.
@@ -1129,13 +1132,14 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
 #ifdef CONFIG_MTD_NAND_OMAP_BCH8
-	const int hw_errors = 8;
+	const int hw_errors = BCH8_MAX_ERROR;
 #else
-	const int hw_errors = 4;
+	const int hw_errors = BCH4_MAX_ERROR;
 #endif
 	info->bch = NULL;
 
-	max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? 8 : 4;
+	max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ?
+		BCH8_MAX_ERROR : BCH4_MAX_ERROR;
 	if (max_errors != hw_errors) {
 		pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported",
 		       max_errors, hw_errors);
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 0/4] mtd: nand: OMAP: Add support to use ELM as error correction module
From: Philip, Avinash @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

Adds support to use ELM as BCH 4 & 8 bit error correction module and
adds support for single shot read_page and write_page functions

Platforms containing the ELM module can be used to correct errors
reported by BCH 4, 8 & 16 bit ECC scheme. For now only 4 & 8 bit
support is added.

BCH 4 & 8 bit error detection support is already available in mainline
kernel and works with software error correction.

This series is based on top of [1] &[2]

1. linux-next/master
2. linux-omap-dt/for_3.7/dts_part2

Nand driver tested for BCH 4 & 8 bit error correction per sector.
This being tested by introducing bit errors at multiple sectors inside page.

Philip, Avinash (4):
  mtd: nand: omap2: Update nerrors using ecc.strength
  mtd: devices: elm: Add support for ELM error correction
  ARM: OMAP2: gpmc: Add support for BCH ECC scheme
  mtd: nand: omap2: Add data correction support

 arch/arm/mach-omap2/gpmc.c                   |  120 +++++++-
 arch/arm/plat-omap/include/plat/gpmc.h       |    1 +
 drivers/mtd/devices/Makefile                 |    4 +-
 drivers/mtd/devices/elm.c                    |  446 ++++++++++++++++++++++++++
 drivers/mtd/nand/omap2.c                     |  368 +++++++++++++++++++--
 include/linux/platform_data/elm.h            |   64 ++++
 include/linux/platform_data/mtd-nand-omap2.h |    1 +
 7 files changed, 958 insertions(+), 46 deletions(-)
 create mode 100644 drivers/mtd/devices/elm.c
 create mode 100644 include/linux/platform_data/elm.h

^ permalink raw reply

* [PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
From: Mark Brown @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPDyKFrQ9UhEc_jEKdR=J8T-NUxsYQHB-yMh2vTyxJ+y+R38Og@mail.gmail.com>

On Wed, Oct 03, 2012 at 04:28:34PM +0200, Ulf Hansson wrote:

> I will do a resend and include some explanation for the reverts in the
> "cover-letter".

It'd be good if the explanation could be in the commit logs so that
people reading history can understand things.

^ permalink raw reply

* [PATCH 2/2] ARM: OMAP: SmartReflex: pass device dependent data via platform data
From: Kevin Hilman @ 2012-10-03 14:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349271133-18458-1-git-send-email-j-pihet@ti.com>

jean.pihet at newoldbits.com writes:

> From: Jean Pihet <j-pihet@ti.com>
>
> Remove the device dependent code (ex. cpu_is_xxx()) and settings
> from the driver code and instead pass them via the platform
> data. This allows a clean separation of the driver code and the platform
> code, as required by the move of the platform header files to
> include/linux/platform_data.
>
> Note about the smartreflex functional clocks: the smartreflex fclks
> are derived from sys_clk and are named "smartreflex.%d". Since the
> smartreflex device names and the functional clock names are identical
> the device driver code uses them to control the functional clocks.

Thanks for adding this part.

One more nit below, then please resend this patch as a combined series
with the "align fclk names" patch.  (note: The previous patch 1 from this
series I've queued separately as a fix for v3.7-rc.  )

> Signed-off-by: Jean Pihet <j-pihet@ti.com>
> ---
>  arch/arm/mach-omap2/sr_device.c   |   13 +++++++++++++
>  drivers/power/avs/smartreflex.c   |   38 +++++++++----------------------------
>  include/linux/power/smartreflex.h |   14 ++++++++++++--
>  3 files changed, 34 insertions(+), 31 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
> index cbeae56..06de443 100644
> --- a/arch/arm/mach-omap2/sr_device.c
> +++ b/arch/arm/mach-omap2/sr_device.c
> @@ -121,6 +121,19 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
>  	sr_data->senn_mod = 0x1;
>  	sr_data->senp_mod = 0x1;
>  
> +	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
> +		sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
> +		sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
> +		sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
> +		if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
> +			sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
> +			sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
> +		} else {
> +			sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
> +			sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
> +		}
> +	}
> +
>  	sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
>  	if (IS_ERR(sr_data->voltdm)) {
>  		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
> diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
> index 24768a2..829467f 100644
> --- a/drivers/power/avs/smartreflex.c
> +++ b/drivers/power/avs/smartreflex.c
> @@ -133,14 +133,11 @@ static void sr_set_clk_length(struct omap_sr *sr)
>  	struct clk *sys_ck;
>  	u32 sys_clk_speed;
>  
> -	if (cpu_is_omap34xx())
> -		sys_ck = clk_get(NULL, "sys_ck");
> -	else
> -		sys_ck = clk_get(NULL, "sys_clkin_ck");
> +	sys_ck = clk_get(&sr->pdev->dev, "fck");

nit: since this isn't the sys_clk anymore, could you s/sys_ck/fck/  ?

Thanks,

Kevin

^ permalink raw reply

* [PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
From: Ulf Hansson @ 2012-10-03 14:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121003135556.GE4360@opensource.wolfsonmicro.com>

Hi Mark,

I will do a resend and include some explanation for the reverts in the
"cover-letter".

Kind regards
Ulf Hansson

On 3 October 2012 15:55, Mark Brown <broonie@opensource.wolfsonmicro.com> wrote:
> On Wed, Oct 03, 2012 at 03:43:16PM +0200, Ulf Hansson wrote:
>
>> Heard from Linus Walleij that you Mark has been helping out merging
>> spi patches, did not know that when sending out this series. Anyway,
>> do you guys see any issues merging this?
>
>> [PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
>> [PATCH 2/3] Revert "spi/pl022: enable runtime PM"
>> [PATCH 3/3] spi: spi-pl022: Minor simplification for runtime pm
>
> If someone could send the patches I'll take a look...  some explanation
> as to why we're reverting things would be helpful.

^ permalink raw reply

* [PATCH v7 1/3] watchdog: at91sam9_wdt: add device tree
From: Fabio Porcedda @ 2012-10-03 14:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121002200753.GA12565@lunn.ch>

On Tue, Oct 2, 2012 at 10:07 PM, Andrew Lunn <andrew@lunn.ch> wrote:
>> Date: Tue,  2 Oct 2012 18:01:00 +0200
>> From: Fabio Porcedda <fabio.porcedda@gmail.com>
>> To: Wim Van Sebroeck <wim@iguana.be>, linux-watchdog at vger.kernel.org,
>>         linux-arm-kernel at lists.infradead.org, Nicolas Ferre
>>         <nicolas.ferre@atmel.com>, Jean-Christophe PLAGNIOL-VILLARD
>>         <plagnioj@jcrosoft.com>, Andrew Victor <linux@maxim.org.za>
>> Cc: devicetree-discuss at lists.ozlabs.org
>> Subject: [PATCH v7 1/3] watchdog: at91sam9_wdt: add device tree
>>         support
>> Message-ID:
>>         <1349193662-23482-2-git-send-email-fabio.porcedda@gmail.com>
>>
>> Tested on an at91sam9260 board (evk-pro3)
>>
>> Signed-off-by: Fabio Porcedda <fabio.porcedda@gmail.com>
>> +++ b/drivers/watchdog/at91sam9_wdt.c
>> @@ -32,6 +32,7 @@
>>  #include <linux/timer.h>
>>  #include <linux/bitops.h>
>>  #include <linux/uaccess.h>
>> +#include <linux/of.h>
>>
>>  #include "at91sam9_wdt.h"
>>
>> > @@ -302,11 +303,21 @@ static int __exit at91wdt_remove(struct platform_device *pdev)
>>         return res;
>>  }
>>
>> +#if defined(CONFIG_OF)
>> +static const struct of_device_id at91_wdt_dt_ids[] = {
>> +       { .compatible = "atmel,at91sam9260-wdt" },
>> +       { /* sentinel */ }
>> +};
>
> Hi Fabio
>
> You are missing __devinitdata.

Thank you, Andrew.
I'll add __initconst, because it's const and use platform_driver_probe.

Best regards
-- 
Fabio Porcedda

^ permalink raw reply

* [alsa-devel] [PATCH 0/3] ASoC: Davinci: McASP: add support new McASP IP Variant
From: Daniel Mack @ 2012-10-03 14:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1BAFE6F6C881BF42822005164F1491C33EA99DA8@DBDE01.ent.ti.com>

On 03.10.2012 14:57, Hebbar, Gururaja wrote:
> On Wed, Oct 03, 2012 at 16:46:39, Daniel Mack wrote:
>> On 03.10.2012 09:16, Hebbar, Gururaja wrote:
>>> On Wed, Oct 03, 2012 at 03:58:45, Daniel Mack wrote:
>>>> On 31.08.2012 14:50, Hebbar, Gururaja wrote:
>>>>> The OMAP2+ variant of McASP is different from Davinci variant w.r.to some
>>>>> register offset and missing generic SRAM APIs support
>>>>>
>>>>> Changes
>>>>> - Add new MCASP_VERSION_3 to identify new variant. New DT compatible
>>>>>   "ti,omap2-mcasp-audio" to identify version 3 controller.
>>>>> - The register offsets are handled depending on the version.
>>>>> - Provide a config option to indicate missing SRAM API support.
>>>>
>>>> Could you give some insight which hardware this was tested on? I'm
>>>> trying to get this up and running on a AM33xx board, and the patches
>>>> look all reasonable to me. My problem is that I can't make the DMA
>>>> engine move forward, I fail to receive a single interrupt on this
>>>> peripheral after the stream starts. I will continue searching for the
>>>> reason of this tomorrow, but maybe you can give me some hint by
>>>> explaining your setup?
>>>>
>>>> Note that I'm using your patches together with Matt's from this series:
>>>>
>>>>   https://github.com/ohporter/linux/tree/edma-dmaengine-am33xx-rfc-v1
>>>>
>>>> ... but it doesn't work without those either.
>>>
>>>
>>> When I started working on adding DT support to McASP driver, Matt Porter 
>>> EDMA port was not yet ready. 
>>>
>>> So 
>>> 1. I took existing edma driver from AM335x Arago release [1] (driver + edma 
>>>    device init). 
>>> 2. Added this to Vaibhav's Local (linux-next + AM335x patches) tree [2] 
>>>
>>> 3. Added DT support to McASP driver.
>>>
>>> I tested this on AM335x EVM board. 
>>
>> Hmm, so I think there's a tiny bit missing for the EDMA conversion on DT
>> kernels.
>>
>>> If you need the code, I can share it as a patch (I will send the patch as a 
>>> private mail since the patch is huge).
>>
>> Please do :) Or just push your entire tree somewhere.
> 
> I have pushed the code at below git repo
> Repo :https://github.com/hvaibhav/am335x-linux
> Branch : am335x-upstream-staging-audio
> 
> This includes 
> 1. (linux-next + AM335x patches)
> 2. McASP DT conversion
> 3. EDMA hack
> 4. AM335x audio specific DT blobs
> 5. Am335x dma DT blobs [hack]

Ha, that 5th point was what I was missing, in particular these DMA
offset matching bits. Thanks a lot! I'll get back to you soon with some
patches for the mcasp driver.


Daniel

^ permalink raw reply

* [PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
From: Mark Brown @ 2012-10-03 13:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPDyKFo5-UeUe7PkxCBMnRziWh+eSC_ZjJ0pKhcBkHUkFdSH+w@mail.gmail.com>

On Wed, Oct 03, 2012 at 03:43:16PM +0200, Ulf Hansson wrote:

> Heard from Linus Walleij that you Mark has been helping out merging
> spi patches, did not know that when sending out this series. Anyway,
> do you guys see any issues merging this?

> [PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
> [PATCH 2/3] Revert "spi/pl022: enable runtime PM"
> [PATCH 3/3] spi: spi-pl022: Minor simplification for runtime pm

If someone could send the patches I'll take a look...  some explanation
as to why we're reverting things would be helpful.

^ permalink raw reply

* [RESEND][PATCH] ASoC: ams-delta: Convert to use snd_soc_register_card()
From: Janusz Krzysztofik @ 2012-10-03 13:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1582731.dIkBtAuyKn@vclass>

Mark,
Please note we have an Ack from Tony.
http://mailman.alsa-project.org/pipermail/alsa-devel/2012-September/055493.html

Thanks,
Janusz

---
Subject: Re: [PATCH] ASoC: ams-delta: Convert to use snd_soc_register_card()
Date: niedziela, 16 wrze?nia 2012, 13:44:23
From: Tony Lindgren <tony@atomide.com>
To: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>, Liam Girdwood <lrg@ti.com>, linux-omap at vger.kernel.org, linux-arm-kernel at lists.infradead.org, alsa-devel at alsa-project.org

* Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> [120916 12:18]:
> 
> Tony,
> Please give your ack on the arch/arm/mach-omap1 bits if acceptable. I
> believe there should be no merge conflicts if this change goes through
> sound/soc.

Yes looks good to me:

Acked-by: Tony Lindgren <tony@atomide.com>

^ permalink raw reply

* [PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
From: Ulf Hansson @ 2012-10-03 13:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348831266-16721-2-git-send-email-ulf.hansson@stericsson.com>

Hi Mark and Grant,

Heard from Linus Walleij that you Mark has been helping out merging
spi patches, did not know that when sending out this series. Anyway,
do you guys see any issues merging this?

[PATCH 1/3] Revert "spi/pl022: fix spi-pl022 pm enable at probe"
[PATCH 2/3] Revert "spi/pl022: enable runtime PM"
[PATCH 3/3] spi: spi-pl022: Minor simplification for runtime pm

Kind regards
Ulf Hansson

On 28 September 2012 13:21, Ulf Hansson <ulf.hansson@stericsson.com> wrote:
> From: Ulf Hansson <ulf.hansson@linaro.org>
>
> This reverts commit 6887237cd7da904184dab2750504040c68f3a080.
>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>  drivers/spi/spi-pl022.c |    1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
> index f8568b4..3f2f36c 100644
> --- a/drivers/spi/spi-pl022.c
> +++ b/drivers/spi/spi-pl022.c
> @@ -2188,6 +2188,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
>         printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
>                adev->res.start, pl022->virtbase);
>
> +       pm_runtime_enable(dev);
>         pm_runtime_resume(dev);
>
>         pl022->clk = clk_get(&adev->dev, NULL);
> --
> 1.7.10
>

^ permalink raw reply

* [PATCH] [ARM] Build failure CONFIG_ARCH_KIRKWOOD_DT relies on CACHE_FEROCEON_L2
From: Jason Cooper @ 2012-10-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121002175002.GD23733@obsidianresearch.com>

On Tue, Oct 02, 2012 at 11:50:02AM -0600, Jason Gunthorpe wrote:
> On Mon, Oct 01, 2012 at 07:31:58AM -0700, Olof Johansson wrote:
> 
> > Ah. diff took out the #else in the middle and I didn't look at the
> > file. Obviously correct as-is.
> > 
> > In some other places we choose to put the ifdef outside the function
> > and provide a static inline stub in the header file instead. Either
> > way works fine though.
> 
> I don't actually expect anyone will run CONFIG_ARCH_KIRKWOOD_DT
> without CACHE_FEROCEON_L2 - I had thought about just forcing kconfig
> to include CACHE_FEROCEON_L2, but figured there was some reason they
> were separate.. 
> 
> Is there anything further I should do to get this patch upstream?

nope, it's in the queue.

thx,

Jason.

^ permalink raw reply

* [PATCH 2/2] ARM: OMAP: SmartReflex: pass device dependent data via platform data
From: jean.pihet at newoldbits.com @ 2012-10-03 13:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1348496201-6378-3-git-send-email-j-pihet@ti.com>

From: Jean Pihet <j-pihet@ti.com>

Remove the device dependent code (ex. cpu_is_xxx()) and settings
from the driver code and instead pass them via the platform
data. This allows a clean separation of the driver code and the platform
code, as required by the move of the platform header files to
include/linux/platform_data.

Note about the smartreflex functional clocks: the smartreflex fclks
are derived from sys_clk and are named "smartreflex.%d". Since the
smartreflex device names and the functional clock names are identical
the device driver code uses them to control the functional clocks.

Signed-off-by: Jean Pihet <j-pihet@ti.com>
---
 arch/arm/mach-omap2/sr_device.c   |   13 +++++++++++++
 drivers/power/avs/smartreflex.c   |   38 +++++++++----------------------------
 include/linux/power/smartreflex.h |   14 ++++++++++++--
 3 files changed, 34 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index cbeae56..06de443 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -121,6 +121,19 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
 	sr_data->senn_mod = 0x1;
 	sr_data->senp_mod = 0x1;
 
+	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+		sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
+		sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+		sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
+		if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
+			sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+			sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+		} else {
+			sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+			sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+		}
+	}
+
 	sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
 	if (IS_ERR(sr_data->voltdm)) {
 		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
index 24768a2..829467f 100644
--- a/drivers/power/avs/smartreflex.c
+++ b/drivers/power/avs/smartreflex.c
@@ -133,14 +133,11 @@ static void sr_set_clk_length(struct omap_sr *sr)
 	struct clk *sys_ck;
 	u32 sys_clk_speed;
 
-	if (cpu_is_omap34xx())
-		sys_ck = clk_get(NULL, "sys_ck");
-	else
-		sys_ck = clk_get(NULL, "sys_clkin_ck");
+	sys_ck = clk_get(&sr->pdev->dev, "fck");
 
 	if (IS_ERR(sys_ck)) {
-		dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
-			__func__);
+		dev_err(&sr->pdev->dev, "%s: unable to get smartreflex fck %s\n",
+				__func__, dev_name(&sr->pdev->dev));
 		return;
 	}
 
@@ -170,28 +167,6 @@ static void sr_set_clk_length(struct omap_sr *sr)
 	}
 }
 
-static void sr_set_regfields(struct omap_sr *sr)
-{
-	/*
-	 * For time being these values are defined in smartreflex.h
-	 * and populated during init. May be they can be moved to board
-	 * file or pmic specific data structure. In that case these structure
-	 * fields will have to be populated using the pdata or pmic structure.
-	 */
-	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		sr->err_weight = OMAP3430_SR_ERRWEIGHT;
-		sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
-		sr->accum_data = OMAP3430_SR_ACCUMDATA;
-		if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) {
-			sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
-			sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
-		} else {
-			sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
-			sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
-		}
-	}
-}
-
 static void sr_start_vddautocomp(struct omap_sr *sr)
 {
 	if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
@@ -924,8 +899,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	sr_info->nvalue_count = pdata->nvalue_count;
 	sr_info->senn_mod = pdata->senn_mod;
 	sr_info->senp_mod = pdata->senp_mod;
+	sr_info->err_weight = pdata->err_weight;
+	sr_info->err_maxlimit = pdata->err_maxlimit;
+	sr_info->accum_data = pdata->accum_data;
+	sr_info->senn_avgweight = pdata->senn_avgweight;
+	sr_info->senp_avgweight = pdata->senp_avgweight;
 	sr_info->autocomp_active = false;
 	sr_info->ip_type = pdata->ip_type;
+
 	sr_info->base = ioremap(mem->start, resource_size(mem));
 	if (!sr_info->base) {
 		dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
@@ -937,7 +918,6 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 		sr_info->irq = irq->start;
 
 	sr_set_clk_length(sr_info);
-	sr_set_regfields(sr_info);
 
 	list_add(&sr_info->node, &sr_list);
 
diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h
index 4a496eb..c0f44c2 100644
--- a/include/linux/power/smartreflex.h
+++ b/include/linux/power/smartreflex.h
@@ -260,8 +260,13 @@ struct omap_sr_nvalue_table {
  *
  * @name:		instance name
  * @ip_type:		Smartreflex IP type.
- * @senp_mod:		SENPENABLE value for the sr
- * @senn_mod:		SENNENABLE value for sr
+ * @senp_mod:		SENPENABLE value of the sr CONFIG register
+ * @senn_mod:		SENNENABLE value for sr CONFIG register
+ * @err_weight		ERRWEIGHT value of the sr ERRCONFIG register
+ * @err_maxlimit	ERRMAXLIMIT value of the sr ERRCONFIG register
+ * @accum_data		ACCUMDATA value of the sr CONFIG register
+ * @senn_avgweight	SENNAVGWEIGHT value of the sr AVGWEIGHT register
+ * @senp_avgweight	SENPAVGWEIGHT value of the sr AVGWEIGHT register
  * @nvalue_count:	Number of distinct nvalues in the nvalue table
  * @enable_on_init:	whether this sr module needs to enabled at
  *			boot up or not.
@@ -274,6 +279,11 @@ struct omap_sr_data {
 	int				ip_type;
 	u32				senp_mod;
 	u32				senn_mod;
+	u32				err_weight;
+	u32				err_maxlimit;
+	u32				accum_data;
+	u32				senn_avgweight;
+	u32				senp_avgweight;
 	int				nvalue_count;
 	bool				enable_on_init;
 	struct omap_sr_nvalue_table	*nvalue_table;
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/2] ARM: OMAP: SmartReflex: pass device dependent data via platform data
From: Jean Pihet @ 2012-10-03 13:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <877gr87bxj.fsf@deeprootsystems.com>

Hi Kevin,

On Wed, Oct 3, 2012 at 12:21 AM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> Hi Jean,
>
> Jean Pihet <jean.pihet@newoldbits.com> writes:
>
>> Remove the device dependent settings (cpu_is_xxx(), IP fck etc.)
>> from the driver code and pass them instead via the platform
>> data.
>> This allows a clean separation of the driver code and the platform
>> code, as required by the move of the platform header files to
>> include/linux/platform_data.
>>
>> Signed-off-by: Jean Pihet <j-pihet@ti.com>
>
> Could you make pdata change and the clock change should be two different
> patches?  Also, your previous patch to align SR clock names should be
> combined with the changes made here.
>
> Some comments on the clock change below...
>
>> ---
>>  arch/arm/mach-omap2/sr_device.c   |   13 ++++++++++++
>>  drivers/power/avs/smartreflex.c   |   40 ++++++++++--------------------------
>>  include/linux/power/smartreflex.h |   14 +++++++++++-
>>  3 files changed, 36 insertions(+), 31 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
>> index d033a65..2885a77 100644
>> --- a/arch/arm/mach-omap2/sr_device.c
>> +++ b/arch/arm/mach-omap2/sr_device.c
>> @@ -122,6 +122,19 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
>>       sr_data->senn_mod = 0x1;
>>       sr_data->senp_mod = 0x1;
>>
>> +     if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
>> +             sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
>> +             sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
>> +             sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
>> +             if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
>> +                     sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
>> +                     sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
>> +             } else {
>> +                     sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
>> +                     sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
>> +             }
>> +     }
>> +
>>       sr_data->voltdm = voltdm_lookup(sr_dev_attr->sensor_voltdm_name);
>>       if (IS_ERR(sr_data->voltdm)) {
>>               pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
>> diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
>> index 92f6728..7c03c90 100644
>> --- a/drivers/power/avs/smartreflex.c
>> +++ b/drivers/power/avs/smartreflex.c
>> @@ -128,17 +128,16 @@ static irqreturn_t sr_interrupt(int irq, void *data)
>>
>>  static void sr_set_clk_length(struct omap_sr *sr)
>>  {
>> +     char fck_name[16]; /* "smartreflex.0" fits in 16 chars */
>>       struct clk *sys_ck;
>>       u32 sys_clk_speed;
>>
>> -     if (cpu_is_omap34xx())
>> -             sys_ck = clk_get(NULL, "sys_ck");
>> -     else
>> -             sys_ck = clk_get(NULL, "sys_clkin_ck");
>> +     sprintf(fck_name, "smartreflex.%d", sr->srid);
>
> hmm, isn't this the same as dev_name(&sr->pdev.dev) ?
Yes. Atfer the previous patch "ARM: OMAP: hwmod: align the SmartReflex
fck names" there is a direct mapping between the device name and the
IP functional clock. Note: the mapping is based on the order of the
hwmod entries and so it is important not to move them around.

> Combined with your earlier patch to align clock names, this should just
> be:
>
>         sys_ck = clk_get(&sr->pdev.dev, "fck");
Great! That works great and the code is much more elegant.

> Also note that you've changed this from sys_clk to the SR functional
> clock, which seems to be the same clock on 34xx and 44xx, but that change
> should be clearly documented in the changelog.
Ok.

Updated patch in a bit.

>
> Kevin

Thanks for reviewing,
Jean

^ permalink raw reply

* [alsa-devel] [PATCH 0/3] ASoC: Davinci: McASP: add support new McASP IP Variant
From: Hebbar, Gururaja @ 2012-10-03 12:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <506C1E97.1070700@gmail.com>

On Wed, Oct 03, 2012 at 16:46:39, Daniel Mack wrote:
> On 03.10.2012 09:16, Hebbar, Gururaja wrote:
> > On Wed, Oct 03, 2012 at 03:58:45, Daniel Mack wrote:
> >> On 31.08.2012 14:50, Hebbar, Gururaja wrote:
> >>> The OMAP2+ variant of McASP is different from Davinci variant w.r.to some
> >>> register offset and missing generic SRAM APIs support
> >>>
> >>> Changes
> >>> - Add new MCASP_VERSION_3 to identify new variant. New DT compatible
> >>>   "ti,omap2-mcasp-audio" to identify version 3 controller.
> >>> - The register offsets are handled depending on the version.
> >>> - Provide a config option to indicate missing SRAM API support.
> >>
> >> Could you give some insight which hardware this was tested on? I'm
> >> trying to get this up and running on a AM33xx board, and the patches
> >> look all reasonable to me. My problem is that I can't make the DMA
> >> engine move forward, I fail to receive a single interrupt on this
> >> peripheral after the stream starts. I will continue searching for the
> >> reason of this tomorrow, but maybe you can give me some hint by
> >> explaining your setup?
> >>
> >> Note that I'm using your patches together with Matt's from this series:
> >>
> >>   https://github.com/ohporter/linux/tree/edma-dmaengine-am33xx-rfc-v1
> >>
> >> ... but it doesn't work without those either.
> > 
> > 
> > When I started working on adding DT support to McASP driver, Matt Porter 
> > EDMA port was not yet ready. 
> > 
> > So 
> > 1. I took existing edma driver from AM335x Arago release [1] (driver + edma 
> >    device init). 
> > 2. Added this to Vaibhav's Local (linux-next + AM335x patches) tree [2] 
> > 
> > 3. Added DT support to McASP driver.
> > 
> > I tested this on AM335x EVM board. 
> 
> Hmm, so I think there's a tiny bit missing for the EDMA conversion on DT
> kernels.
> 
> > If you need the code, I can share it as a patch (I will send the patch as a 
> > private mail since the patch is huge).
> 
> Please do :) Or just push your entire tree somewhere.

I have pushed the code at below git repo
Repo :https://github.com/hvaibhav/am335x-linux
Branch : am335x-upstream-staging-audio

This includes 
1. (linux-next + AM335x patches)
2. McASP DT conversion
3. EDMA hack
4. AM335x audio specific DT blobs
5. Am335x dma DT blobs [hack]

Kindly let me know if you need any more details.

> 
> 
> Thanks,
> Daniel
> 
> 


Regards, 
Gururaja

^ permalink raw reply

* [PATCH v2] leds: leds-gpio: adopt pinctrl support
From: Linus Walleij @ 2012-10-03 12:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <331ABD5ECB02734CA317220B2BBEABC13EA3F22E@DBDE01.ent.ti.com>

On Wed, Oct 3, 2012 at 12:52 PM, AnilKumar, Chimata <anilkumar@ti.com> wrote:
> On Tue, Oct 02, 2012 at 01:29:37, Linus Walleij wrote:

>> This is what we're doing for ux500 and should be a good model.
>
> I have looked into this, but not seen any named modes.

OK maybe it's not easy to find. If you look into:
arch/arm/mach-ux500/board-mop500-pins.c
you find our work in progress. Note that this is not (yet)
using device tree. (We want to migrate all our pinctrl
stuff first, then do DT.)

So for example this macro:

#define DB8500_PIN(pin,conf,dev) \
        PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf)

Will define a config for the "default" mode for a certain
pin.

This:

#define DB8500_PIN_SLEEP(pin, conf, dev) \
        PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
                            pin, conf)

Will mutatis mutandis define a "sleep" mode for a pin.

Sorry for the macros. We'll get rid of them in the DT.
(Now that Stephen has patched in preprocessing it will
even look good.)

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] ARM: ux500: add DB serial number to entropy pool
From: Linus Walleij @ 2012-10-03 12:29 UTC (permalink / raw)
  To: linux-arm-kernel

From: Linus Walleij <linus.walleij@linaro.org>

This throws the DB (digital baseband, ASIC) serial number, process
type etc into the entropy pool by way of the device_add_randomness()
call. This should make every device have a unique pool state upon
boot.

Cc: Theodore Tso <tytso@mit.edu>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/cpu-db8500.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index bcdfe6b..50202a1 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -17,6 +17,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/platform_data/usb-musb-ux500.h>
+#include <linux/random.h>
 
 #include <asm/pmu.h>
 #include <asm/mach/map.h>
@@ -24,7 +26,6 @@
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
-#include <linux/platform_data/usb-musb-ux500.h>
 #include <mach/db8500-regs.h>
 
 #include "devices-db8500.h"
@@ -187,6 +188,8 @@ static const char *db8500_read_soc_id(void)
 {
 	void __iomem *uid = __io_address(U8500_BB_UID_BASE);
 
+	/* Throw these device-specific numbers into the entropy pool */
+	add_device_randomness(uid, 0x14);
 	return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x",
 			 readl((u32 *)uid+1),
 			 readl((u32 *)uid+1), readl((u32 *)uid+2),
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH 3/3] serial: omap: Remove the hardcode serial_omap_console_ports array.
From: Shubhrajyoti D @ 2012-10-03 11:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349265278-27763-1-git-send-email-shubhrajyoti@ti.com>

Currently the array serial_omap_console_ports is hard coded to 4.
Make it depend on the maximum uart count.
Post to [cfc55bc ARM: OMAP2+: serial: Change MAX_HSUART_PORTS to 6]
the max ports is 6.

Cc: AnilKumar Ch <anilkumar@ti.com>
Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
---
 drivers/tty/serial/omap-serial.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index caf49a6..478383d 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1077,7 +1077,7 @@ out:
 
 #ifdef CONFIG_SERIAL_OMAP_CONSOLE
 
-static struct uart_omap_port *serial_omap_console_ports[4];
+static struct uart_omap_port *serial_omap_console_ports[OMAP_MAX_HSUART_PORTS];
 
 static struct uart_driver serial_omap_reg;
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 2/3] serial: omap: Remove the default setting of special character
From: Shubhrajyoti D @ 2012-10-03 11:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349265278-27763-1-git-send-email-shubhrajyoti@ti.com>

Special character detect enable if enabled by default.Received data
comparison with XOFF2 data happens by default.

tty provides only XOFF1 no X0FF2 is provided so no need
to enable check for XOFF2.

Keeping this enabled might give some slow transfers due to dummy xoff2
comparison with xoff2 reset value.

Since not all want the XOFF2 support lets not enable it by
default.

Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
---
 drivers/tty/serial/omap-serial.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index fd0fb8c..caf49a6 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -702,11 +702,7 @@ serial_omap_configure_xonxoff
 	serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
-	/* Enable special char function UARTi.EFR_REG[5] and
-	 * load the new software flow control mode IXON or IXOFF
-	 * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
-	 */
-	serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
+
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
 
 	serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
-- 
1.7.5.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox