Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 01/13] mfd: pruss mfd driver.
From: Subhasish Ghosh @ 2011-02-11 14:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297435892-28278-1-git-send-email-subhasish@mistralsolutions.com>

This patch adds the pruss MFD driver and associated include files.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 drivers/mfd/Kconfig                     |   10 +
 drivers/mfd/Makefile                    |    1 +
 drivers/mfd/da8xx_pru.c                 |  446 +++++++++++++++++++++++++++++++
 include/linux/mfd/pruss/da8xx_pru.h     |  122 +++++++++
 include/linux/mfd/pruss/da8xx_prucore.h |   74 +++++
 5 files changed, 653 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/da8xx_pru.c
 create mode 100644 include/linux/mfd/pruss/da8xx_pru.h
 create mode 100644 include/linux/mfd/pruss/da8xx_prucore.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fd01836..6c437df 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -81,6 +81,16 @@ config MFD_DM355EVM_MSP
 	  boards.  MSP430 firmware manages resets and power sequencing,
 	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
 
+config MFD_DA8XX_PRUSS
+	tristate "Texas Instruments DA8XX PRUSS support"
+	depends on ARCH_DAVINCI && ARCH_DAVINCI_DA850
+	select MFD_CORE
+	help
+	    This driver provides support api's for the programmable
+		realtime unit (PRU) present on TI's da8xx processors. It
+		provides basic read, write, config, enable, disable
+		routines to facilitate devices emulated on it.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a54e2c7..670d6b0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
 obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
 
 obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
+obj-$(CONFIG_MFD_DA8XX_PRUSS)	+= da8xx_pru.o
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
 
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
diff --git a/drivers/mfd/da8xx_pru.c b/drivers/mfd/da8xx_pru.c
new file mode 100644
index 0000000..f7868a4
--- /dev/null
+++ b/drivers/mfd/da8xx_pru.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mfd/pruss/da8xx_prucore.h>
+#include <linux/mfd/pruss/da8xx_pru.h>
+#include <linux/mfd/core.h>
+#include <linux/io.h>
+#include <mach/da8xx.h>
+
+struct da8xx_pruss {
+	struct device *dev;
+	struct resource *res;
+	struct clk *clk;
+	u32 clk_freq;
+	void __iomem *ioaddr;
+};
+
+u32 pruss_get_clk_freq(struct device *dev)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+
+	return pruss->clk_freq;
+}
+EXPORT_SYMBOL(pruss_get_clk_freq);
+
+u32 pruss_disable(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+	u32 temp_reg;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* Disable PRU0  */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
+		__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
+		__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+		/* Reset PRU0 */
+		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+				&h_pruss->CONTROL);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* Disable PRU1 */
+		h_pruss = (da8xx_prusscore_regs)
+		((u32) pruss->ioaddr + 0x7800);
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
+		__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		temp_reg = (temp_reg &
+				~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
+				((DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE <<
+				DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
+				DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
+		__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+		/* Reset PRU1 */
+		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL, &h_pruss->CONTROL);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_disable);
+
+u32 pruss_enable(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* Reset PRU0 */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+			&h_pruss->CONTROL);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* Reset PRU1  */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7800);
+		__raw_writel(DA8XX_PRUCORE_CONTROL_RESETVAL,
+			&h_pruss->CONTROL);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_enable);
+
+/* Load the specified PRU with code */
+u32 pruss_load(struct device *dev, u8 pruss_num,
+			u32 *pruss_code, u32 code_size_in_words)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pruss_iram;
+	u32 i;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		pruss_iram = (u32 *) ((u32) pruss->ioaddr + 0x8000);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		pruss_iram = (u32 *) ((u32) pruss->ioaddr + 0xc000);
+	} else
+		return -EINVAL;
+
+	pruss_enable(dev, pruss_num);
+
+	/* Copy dMAX code to its instruction RAM  */
+	for (i = 0; i < code_size_in_words; i++) {
+		__raw_writel(pruss_code[i], (pruss_iram + i));
+	}
+	return 0;
+}
+EXPORT_SYMBOL(pruss_load);
+
+u32 pruss_run(struct device *dev, u8 pruss_num)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+
+	u32 temp_reg;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* DA8XX_PRUCORE_0_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* DA8XX_PRUCORE_1_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7800);
+	} else
+		return -EINVAL;
+
+	/* Enable dMAX, let it execute the code we just copied */
+	temp_reg = __raw_readl(&h_pruss->CONTROL);
+	temp_reg = (temp_reg &
+			~DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK) |
+			((DA8XX_PRUCORE_CONTROL_COUNTENABLE_ENABLE <<
+			DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT) &
+			DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK);
+	__raw_writel(temp_reg, &h_pruss->CONTROL);
+
+	temp_reg = __raw_readl(&h_pruss->CONTROL);
+	temp_reg = (temp_reg &
+			~DA8XX_PRUCORE_CONTROL_ENABLE_MASK) |
+			((DA8XX_PRUCORE_CONTROL_ENABLE_ENABLE <<
+			DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT) &
+			DA8XX_PRUCORE_CONTROL_ENABLE_MASK);
+	__raw_writel(temp_reg, &h_pruss->CONTROL);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_run);
+
+u32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	da8xx_prusscore_regs h_pruss;
+	u32 temp_reg;
+	u32 cnt = timeout;
+
+	if (pruss_num == DA8XX_PRUCORE_0) {
+		/* DA8XX_PRUCORE_0_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7000);
+	} else if (pruss_num == DA8XX_PRUCORE_1) {
+		/* DA8XX_PRUCORE_1_REGS; */
+		h_pruss = (da8xx_prusscore_regs)
+			((u32) pruss->ioaddr + 0x7800);
+	} else
+		return -EINVAL;
+
+	while (cnt--) {
+		temp_reg = __raw_readl(&h_pruss->CONTROL);
+		if (((temp_reg & DA8XX_PRUCORE_CONTROL_RUNSTATE_MASK) >>
+				DA8XX_PRUCORE_CONTROL_RUNSTATE_SHIFT) ==
+					DA8XX_PRUCORE_CONTROL_RUNSTATE_HALT)
+			break;
+	}
+	if (cnt == 0)
+		return -EBUSY;
+
+	return 0;
+}
+EXPORT_SYMBOL(pruss_wait_for_halt);
+
+s16 pruss_writeb(struct device *dev, u32 u32offset,
+		u8 *pu8datatowrite, u16 u16bytestowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u8 *pu8addresstowrite;
+	u16 u16loop;
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu8addresstowrite = (u8 *) (u32offset);
+
+	for (u16loop = 0; u16loop < u16bytestowrite; u16loop++)
+		__raw_writeb(*pu8datatowrite++, pu8addresstowrite++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writeb);
+
+s16 pruss_readb(struct device *dev, u32 u32offset,
+		u8 *pu8datatoread, u16 u16bytestoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u8 *pu8addresstoread;
+	u16 u16loop;
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu8addresstoread = (u8 *) (u32offset);
+
+	for (u16loop = 0; u16loop < u16bytestoread; u16loop++)
+		*pu8datatoread++ = __raw_readb(pu8addresstoread++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readb);
+
+s16 pruss_writel(struct device *dev, u32 u32offset,
+		u32 *pu32datatowrite, s16 u16wordstowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pu32addresstowrite;
+	s16 u16loop;
+
+	/* TODO: Get all the driver API's fixed */
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu32addresstowrite = (u32 *)(u32offset);
+
+	for (u16loop = 0; u16loop < u16wordstowrite; u16loop++)
+		__raw_writel(*pu32datatowrite++, pu32addresstowrite++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writel);
+
+s16 pruss_readl(struct device *dev, u32 u32offset,
+		u32 *pu32datatoread, s16 u16wordstoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pu32addresstoread;
+	s16 u16loop;
+
+	/* TODO: Get all the driver API's fixed */
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu32addresstoread = (u32 *)(u32offset);
+
+	for (u16loop = 0; u16loop < u16wordstoread; u16loop++)
+		*pu32datatoread++ = __raw_readl(pu32addresstoread++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readl);
+
+s16 pruss_writew(struct device *dev, u32 u32offset,
+		u16 *pu16datatowrite, s16 u16wordstowrite)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pu32addresstowrite;
+	s16 u16loop;
+
+	/* TODO: Get all the driver API's fixed */
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu32addresstowrite = (u32 *)(u32offset);
+
+	for (u16loop = 0; u16loop < u16wordstowrite; u16loop++) {
+		__raw_writew(*(pu16datatowrite++), (pu32addresstowrite++));
+	}
+	return 0;
+}
+EXPORT_SYMBOL(pruss_writew);
+
+s16 pruss_readw(struct device *dev, u32 u32offset,
+			u16 *pu16datatoread, s16 u16wordstoread)
+{
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev->parent);
+	u32 *pu32addresstoread;
+	s16 u16loop;
+
+	/* TODO: Get all the driver API's fixed */
+	u32offset = (u32)pruss->ioaddr + u32offset;
+	pu32addresstoread = (u32 *)(u32offset);
+
+	for (u16loop = 0; u16loop < u16wordstoread; u16loop++)
+		*pu16datatoread++ = __raw_readw(pu32addresstoread++);
+	return 0;
+}
+EXPORT_SYMBOL(pruss_readw);
+
+static int pruss_mfd_add_devices(struct platform_device *pdev)
+{
+	struct da8xx_pruss_devices *dev_data = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct mfd_cell cell;
+	u32 err, count;
+
+	for (count = 0; (dev_data + count)->dev_name != NULL; count++) {
+		memset(&cell, 0, sizeof(struct mfd_cell));
+		cell.id			= count;
+		cell.name		= (dev_data + count)->dev_name;
+		cell.platform_data	= (dev_data + count)->pdata;
+		cell.data_size		= (dev_data + count)->pdata_size;
+
+		err = mfd_add_devices(dev, 0, &cell, 1, NULL, 0);
+		if (err) {
+			dev_err(dev, "cannot add mfd cells\n");
+			return err;
+		}
+	}
+	return err;
+}
+
+static int __devinit da8xx_pruss_probe(struct platform_device *pdev)
+{
+	struct da8xx_pruss *pruss_dev = NULL;
+	u32 err;
+
+	pruss_dev = kzalloc(sizeof(struct da8xx_pruss), GFP_KERNEL);
+	if (!pruss_dev)
+		return -ENOMEM;
+
+	pruss_dev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pruss_dev->res) {
+		dev_err(&pdev->dev,
+		"unable to get pruss memory resources!\n");
+		err = -ENODEV;
+		goto probe_exit_kfree;
+	}
+
+	if (!request_mem_region(pruss_dev->res->start, resource_size(pruss_dev->res),
+		dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "pruss memory region already claimed!\n");
+		err = -EBUSY;
+		goto probe_exit_kfree;
+	}
+
+	pruss_dev->ioaddr = ioremap(pruss_dev->res->start,
+	resource_size(pruss_dev->res));
+	if (!pruss_dev->ioaddr) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		err = -ENOMEM;
+		goto probe_exit_free_region;
+	}
+
+	pruss_dev->clk = clk_get(NULL, "pruss");
+	if (IS_ERR(pruss_dev->clk)) {
+		dev_err(&pdev->dev, "no clock available: pruss\n");
+		err = -ENODEV;
+		pruss_dev->clk = NULL;
+		goto probe_exit_iounmap;
+	}
+
+	clk_enable(pruss_dev->clk);
+	pruss_dev->clk_freq = clk_get_rate(pruss_dev->clk);
+
+	err = pruss_mfd_add_devices(pdev);
+	if (err)
+		goto probe_exit_clock;
+
+	platform_set_drvdata(pdev, pruss_dev);
+	pruss_dev->dev = &pdev->dev;
+	return 0;
+
+probe_exit_clock:
+	clk_put(pruss_dev->clk);
+	clk_disable(pruss_dev->clk);
+probe_exit_iounmap:
+	iounmap(pruss_dev->ioaddr);
+probe_exit_free_region:
+	release_mem_region(pruss_dev->res->start, resource_size(pruss_dev->res));
+probe_exit_kfree:
+	kfree(pruss_dev);
+	return err;
+}
+
+static int __devexit da8xx_pruss_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct da8xx_pruss *pruss = dev_get_drvdata(dev);
+
+	mfd_remove_devices(dev);
+	clk_disable(pruss->clk);
+	clk_put(pruss->clk);
+	iounmap(pruss->ioaddr);
+	release_mem_region(pruss->res->start, resource_size(pruss->res));
+	kfree(pruss);
+	dev_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver da8xx_pruss_driver = {
+	.probe	= da8xx_pruss_probe,
+	.remove	= __devexit_p(da8xx_pruss_remove),
+	.driver	= {
+		.name	= "da8xx_pruss",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init da8xx_pruss_init(void)
+{
+	return platform_driver_register(&da8xx_pruss_driver);
+}
+module_init(da8xx_pruss_init);
+
+static void __exit da8xx_pruss_exit(void)
+{
+	platform_driver_unregister(&da8xx_pruss_driver);
+}
+module_exit(da8xx_pruss_exit);
+
+MODULE_DESCRIPTION("Programmable Realtime Unit (PRU) Driver");
+MODULE_AUTHOR("Subhasish Ghosh");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/pruss/da8xx_pru.h b/include/linux/mfd/pruss/da8xx_pru.h
new file mode 100644
index 0000000..68d8421
--- /dev/null
+++ b/include/linux/mfd/pruss/da8xx_pru.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Jitendra Kumar <jitendra@mistralsolutions.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _PRUSS_H_
+#define _PRUSS_H_
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include "da8xx_prucore.h"
+
+#define PRUSS_NUM0			DA8XX_PRUCORE_0
+#define PRUSS_NUM1			DA8XX_PRUCORE_1
+
+#define PRUSS_PRU0_BASE_ADDRESS		0
+#define PRUSS_INTC_BASE_ADDRESS		(PRUSS_PRU0_BASE_ADDRESS + 0x4000)
+#define PRUSS_INTC_GLBLEN		(PRUSS_INTC_BASE_ADDRESS + 0x10)
+#define PRUSS_INTC_GLBLNSTLVL		(PRUSS_INTC_BASE_ADDRESS + 0x1C)
+#define PRUSS_INTC_STATIDXSET		(PRUSS_INTC_BASE_ADDRESS + 0x20)
+#define PRUSS_INTC_STATIDXCLR		(PRUSS_INTC_BASE_ADDRESS + 0x24)
+#define PRUSS_INTC_ENIDXSET		(PRUSS_INTC_BASE_ADDRESS + 0x28)
+#define PRUSS_INTC_ENIDXCLR		(PRUSS_INTC_BASE_ADDRESS + 0x2C)
+#define PRUSS_INTC_HSTINTENIDXSET	(PRUSS_INTC_BASE_ADDRESS + 0x34)
+#define PRUSS_INTC_HSTINTENIDXCLR	(PRUSS_INTC_BASE_ADDRESS + 0x38)
+#define PRUSS_INTC_GLBLPRIIDX		(PRUSS_INTC_BASE_ADDRESS + 0x80)
+#define PRUSS_INTC_STATSETINT0		(PRUSS_INTC_BASE_ADDRESS + 0x200)
+#define PRUSS_INTC_STATSETINT1		(PRUSS_INTC_BASE_ADDRESS + 0x204)
+#define PRUSS_INTC_STATCLRINT0		(PRUSS_INTC_BASE_ADDRESS + 0x280)
+#define PRUSS_INTC_STATCLRINT1		(PRUSS_INTC_BASE_ADDRESS + 0x284)
+#define PRUSS_INTC_ENABLESET0		(PRUSS_INTC_BASE_ADDRESS + 0x300)
+#define PRUSS_INTC_ENABLESET1		(PRUSS_INTC_BASE_ADDRESS + 0x304)
+#define PRUSS_INTC_ENABLECLR0		(PRUSS_INTC_BASE_ADDRESS + 0x380)
+#define PRUSS_INTC_ENABLECLR1		(PRUSS_INTC_BASE_ADDRESS + 0x384)
+#define PRUSS_INTC_CHANMAP0		(PRUSS_INTC_BASE_ADDRESS + 0x400)
+#define PRUSS_INTC_CHANMAP1		(PRUSS_INTC_BASE_ADDRESS + 0x404)
+#define PRUSS_INTC_CHANMAP2		(PRUSS_INTC_BASE_ADDRESS + 0x408)
+#define PRUSS_INTC_CHANMAP3		(PRUSS_INTC_BASE_ADDRESS + 0x40C)
+#define PRUSS_INTC_CHANMAP4		(PRUSS_INTC_BASE_ADDRESS + 0x410)
+#define PRUSS_INTC_CHANMAP5		(PRUSS_INTC_BASE_ADDRESS + 0x414)
+#define PRUSS_INTC_CHANMAP6		(PRUSS_INTC_BASE_ADDRESS + 0x418)
+#define PRUSS_INTC_CHANMAP7		(PRUSS_INTC_BASE_ADDRESS + 0x41C)
+#define PRUSS_INTC_CHANMAP8		(PRUSS_INTC_BASE_ADDRESS + 0x420)
+#define PRUSS_INTC_CHANMAP9		(PRUSS_INTC_BASE_ADDRESS + 0x424)
+#define PRUSS_INTC_CHANMAP10		(PRUSS_INTC_BASE_ADDRESS + 0x428)
+#define PRUSS_INTC_CHANMAP11		(PRUSS_INTC_BASE_ADDRESS + 0x42C)
+#define PRUSS_INTC_CHANMAP12		(PRUSS_INTC_BASE_ADDRESS + 0x430)
+#define PRUSS_INTC_CHANMAP13		(PRUSS_INTC_BASE_ADDRESS + 0x434)
+#define PRUSS_INTC_CHANMAP14		(PRUSS_INTC_BASE_ADDRESS + 0x438)
+#define PRUSS_INTC_CHANMAP15		(PRUSS_INTC_BASE_ADDRESS + 0x43C)
+#define PRUSS_INTC_HOSTMAP0		(PRUSS_INTC_BASE_ADDRESS + 0x800)
+#define PRUSS_INTC_HOSTMAP1		(PRUSS_INTC_BASE_ADDRESS + 0x804)
+#define PRUSS_INTC_HOSTMAP2		(PRUSS_INTC_BASE_ADDRESS + 0x808)
+#define PRUSS_INTC_POLARITY0		(PRUSS_INTC_BASE_ADDRESS + 0xD00)
+#define PRUSS_INTC_POLARITY1		(PRUSS_INTC_BASE_ADDRESS + 0xD04)
+#define PRUSS_INTC_TYPE0		(PRUSS_INTC_BASE_ADDRESS + 0xD80)
+#define PRUSS_INTC_TYPE1		(PRUSS_INTC_BASE_ADDRESS + 0xD84)
+#define PRUSS_INTC_HOSTINTEN		(PRUSS_INTC_BASE_ADDRESS + 0x1500)
+#define PRUSS_INTC_HOSTINTLVL_MAX	9
+
+#define PRU_INTC_CHAN_123_HOST		(0x03020100)
+#define PRU_INTC_CHAN_4567_HOST		(0x07060504)
+#define PRU_INTC_CHAN_89_HOST		(0x00000908)
+
+#define PRU_INTC_CHAN_0_SYSEVT_31	(0x00000000)
+#define PRU_INTC_CHAN_12_SYSEVT		(0x02020100)
+#define PRU_INTC_CHAN_34_SYSEVT_36_39	(0x04040303)
+#define PRU_INTC_CHAN_56_SYSEVT_40_43	(0x06060505)
+#define PRU_INTC_CHAN_78_SYSEVT_44_47	(0x08080707)
+#define PRU_INTC_CHAN_9_SYSEVT_48_49	(0x00010909)
+#define PRU_INTC_CHAN_0123_SYSEVT_32_35	(0x03020100)
+#define PRU_INTC_CHAN_4567_SYSEVT_36_39	(0x07060504)
+#define PRU_INTC_CHAN_8923_SYSEVT_40_43	(0x03020908)
+#define PRU_INTC_CHAN_4567_SYSEVT_44_47	(0x07060504)
+
+struct da8xx_pruss_devices {
+	const char *dev_name;
+	void *pdata;
+	size_t pdata_size;
+	int (*setup)(void);
+};
+
+u32 pruss_get_clk_freq(struct device *dev);
+
+u32 pruss_enable(struct device *dev, u8 pruss_num);
+
+u32 pruss_load(struct device *dev, u8 pruss_num, u32 *pruss_code,
+			u32 code_size_in_words);
+
+u32 pruss_run(struct device *dev, u8 pruss_num);
+
+u32 pruss_wait_for_halt(struct device *dev, u8 pruss_num, u32 timeout);
+
+u32 pruss_disable(struct device *dev, u8 pruss_num);
+
+s16 pruss_writeb(struct device *dev, u32 u32offset,
+			u8 *pu8datatowrite, u16 u16wordstowrite);
+
+s16 pruss_readb(struct device *dev, u32 u32offset,
+			u8 *pu8datatoread, u16 u16wordstoread);
+
+s16 pruss_readl(struct device *dev, u32 u32offset,
+			u32 *pu32datatoread, s16 s16wordstoread);
+
+s16 pruss_writel(struct device *dev, u32 u32offset,
+			u32 *pu32datatoread, s16 s16wordstoread);
+
+s16 pruss_writew(struct device *dev, u32 u32offset,
+			u16 *u16datatowrite, s16 u16wordstowrite);
+
+s16 pruss_readw(struct device *dev, u32 u32offset,
+			u16 *pu32datatoread, s16 u16wordstoread);
+#endif	/* End _PRUSS_H_ */
diff --git a/include/linux/mfd/pruss/da8xx_prucore.h b/include/linux/mfd/pruss/da8xx_prucore.h
new file mode 100644
index 0000000..81f2ff9
--- /dev/null
+++ b/include/linux/mfd/pruss/da8xx_prucore.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ * Author: Jitendra Kumar <jitendra@mistralsolutions.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _DA8XX_PRUCORE_H_
+#define _DA8XX_PRUCORE_H_
+
+#include <linux/types.h>
+
+#define DA8XX_PRUCORE_0		(0)
+#define DA8XX_PRUCORE_1		(1)
+
+#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_MASK			(0xFFFF0000u)
+#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_SHIFT			(0x00000010u)
+#define DA8XX_PRUCORE_CONTROL_PCRESETVAL_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_MASK			(0x00008000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_SHIFT			(0x0000000Fu)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_RESETVAL			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_HALT			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_RUNSTATE_RUN			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_MASK			(0x00000100u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_SHIFT			(0x00000008u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_FREERUN		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SINGLESTEP_SINGLE			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_MASK			(0x00000008u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_SHIFT			(0x00000003u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_DISABLE		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_COUNTENABLE_ENABLE		(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_MASK			(0x00000004u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_SHIFT			(0x00000002u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_RESETVAL			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_NOTASLEEP		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SLEEPING_ASLEEP			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_MASK			(0x00000002u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_SHIFT			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_RESETVAL			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_DISABLE			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_ENABLE_ENABLE			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_MASK			(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_SHIFT			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_RESETVAL		(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_RESET			(0x00000000u)
+#define DA8XX_PRUCORE_CONTROL_SOFTRESET_OUT_OF_RESET		(0x00000001u)
+#define DA8XX_PRUCORE_CONTROL_RESETVAL				(0x00000000u)
+
+typedef struct {
+	u32 CONTROL;
+	u32 STATUS;
+	u32 WAKEUP;
+	u32 CYCLECNT;
+	u32 STALLCNT;
+	u8  RSVD0[12];
+	u32 CONTABBLKIDX0;
+	u32 CONTABBLKIDX1;
+	u32 CONTABPROPTR0;
+	u32 CONTABPROPTR1;
+	u8  RSVD1[976];
+	u32 INTGPR[32];
+	u32 INTCTER[32];
+} *da8xx_prusscore_regs;
+
+#endif
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH v2 00/13] pruss mfd drivers
From: Subhasish Ghosh @ 2011-02-11 14:51 UTC (permalink / raw)
  To: linux-arm-kernel


                           PRUSS Functional Block Diagram
               /----------------------------------------------------\
               |                                                    |
               |                      |------|                      |
     32GPO<------->PRU CORE-0 <------>|      |<------> DRAM 0       |
     30GPI<------->(4KB IRAM)         |  S   |       (512 Bytes)    |
               |                      |      |                      |
     32GPO<------->PRU CORE-1 <------>|  C   |<------> DRAM 1       |
     30GPI<------->(4KB IRAM)         |      |       (512 Bytes)    |
               |                      |  R   |                      |
               |                      |      |                      |
 Ints to ARM/  |    Interrupt <------>|      |-------------------------> Master I/F (to SCR2)
 DSP INTC <------->Controller         |      |<------------------------- Slave I/F (from SCR2)
 Events from   |     (INTC)           |------|                      |
 Periph + PRUs |                                                    |
               \----------------------------------------------------/

Programmable Realtime Unit (PRU) is basically a 32-bit RISC
processor available within TI's DA8XX SOCs. It consists of local
instruction and data RAM and also has access to SOC resources
via a Switched Central Resource (SCR).

There are two PRU's available within DA8XX SOC's PRUSS, hence providing
two execution cores. Devices/Protocols can be emulated on these utilizing
either both or only one of the PRUs independently.

The rational behind the MFD driver being the fact that multiple devices can
be implemented on the cores independently.
It's also possible, as in our case, to implement a single device on both
the PRU's resulting in improved load sharing.

A detailed description is also available here:
http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit_Subsystem

version 2:
==========
* added pruss TTY Soft-UART driver.
* added pruss Soft-UART board and platform changes.
* fixed previous review comments.
* reordered patch sequence.

version 1:
==========
* added pruss mfd driver.
* added pruss mfd board and platform changes.
* added pruss SocketCAN driver.
* added pruss SocketCAN board and platform changes.
* added pruss SocketCAN GPIOs.
* added previous review comments.

Subhasish Ghosh (13):
  mfd: pruss mfd driver.
  da850: pruss platform specific additions.
  da850: pruss board specific additions.
  mfd: pruss CAN private data.
  da850: pruss CAN platform specific additions.
  da850: pruss CAN board specific additions.
  da850: pruss CAN platform specific changes for gpios.
  da850: pruss CAN board specific changes for gpios.
  can: pruss CAN driver.
  mfd: pruss SUART private data.
  da850: pruss SUART board specific additions.
  da850: pruss SUART platform specific additions.
  tty: pruss SUART driver

 arch/arm/mach-davinci/board-da850-evm.c            |  105 +
 arch/arm/mach-davinci/da850.c                      |   12 +
 arch/arm/mach-davinci/devices-da8xx.c              |   76 +
 arch/arm/mach-davinci/include/mach/da8xx.h         |    2 +
 arch/arm/mach-davinci/include/mach/mux.h           |    5 +
 drivers/mfd/Kconfig                                |   10 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/da8xx_pru.c                            |  446 ++++
 drivers/net/can/Kconfig                            |    1 +
 drivers/net/can/Makefile                           |    1 +
 drivers/net/can/da8xx_pruss/Kconfig                |   73 +
 drivers/net/can/da8xx_pruss/Makefile               |    7 +
 drivers/net/can/da8xx_pruss/pruss_can.c            |  758 +++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.c        | 1227 ++++++++++
 drivers/net/can/da8xx_pruss/pruss_can_api.h        |  290 +++
 drivers/tty/serial/Kconfig                         |    2 +
 drivers/tty/serial/Makefile                        |    1 +
 drivers/tty/serial/da8xx_pruss/Kconfig             |   19 +
 drivers/tty/serial/da8xx_pruss/Makefile            |    9 +
 drivers/tty/serial/da8xx_pruss/pruss_suart.c       | 1014 +++++++++
 drivers/tty/serial/da8xx_pruss/pruss_suart_api.c   | 2350 ++++++++++++++++++++
 drivers/tty/serial/da8xx_pruss/pruss_suart_api.h   |  345 +++
 drivers/tty/serial/da8xx_pruss/pruss_suart_board.h |   58 +
 drivers/tty/serial/da8xx_pruss/pruss_suart_err.h   |   48 +
 drivers/tty/serial/da8xx_pruss/pruss_suart_mcasp.h |  526 +++++
 drivers/tty/serial/da8xx_pruss/pruss_suart_regs.h  |  153 ++
 drivers/tty/serial/da8xx_pruss/pruss_suart_utils.c |  384 ++++
 drivers/tty/serial/da8xx_pruss/pruss_suart_utils.h |   63 +
 include/linux/mfd/pruss/da8xx_pru.h                |  131 ++
 include/linux/mfd/pruss/da8xx_prucore.h            |   74 +
 include/linux/serial_core.h                        |    2 +
 31 files changed, 8193 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/da8xx_pru.c
 create mode 100644 drivers/net/can/da8xx_pruss/Kconfig
 create mode 100644 drivers/net/can/da8xx_pruss/Makefile
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.c
 create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.h
 create mode 100644 drivers/tty/serial/da8xx_pruss/Kconfig
 create mode 100644 drivers/tty/serial/da8xx_pruss/Makefile
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart.c
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_api.c
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_api.h
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_board.h
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_err.h
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_mcasp.h
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_regs.h
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_utils.c
 create mode 100644 drivers/tty/serial/da8xx_pruss/pruss_suart_utils.h
 create mode 100644 include/linux/mfd/pruss/da8xx_pru.h
 create mode 100644 include/linux/mfd/pruss/da8xx_prucore.h

-- 
1.7.2.3

^ permalink raw reply

* MMC quirks relating to performance/lifetime.
From: Arnd Bergmann @ 2011-02-11 14:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110211144139.GC3920@ucw.cz>

On Friday 11 February 2011, Pavel Machek wrote:
> Hi!
> 
> > I'm not sure if this is the best place to bring this up, but Russel's
> > name is on a fair share of drivers/mmc code, and there does seem to be
> > quite a bit of MMC-related discussions. Excuse me in advance if this
> > isn't the right forum :-).
> > 
> > Certain MMC vendors (maybe even quite a bit of them) use a pretty
> > rigid buffering scheme when it comes to handling writes. There is
> > usually a buffer A for random accesses, and a buffer B for sequential
> > accesses. For certain Toshiba parts, it looks like buffer A is 8KB
> > wide, with buffer B being 4MB wide, and all accesses larger than 8KB
> > effectively equating to 4MB accesses. Worse, consecutive small (8k)
> > writes are treated as one large sequential access, once again ending
> > up in buffer B, thus necessitating out-of-order writing to work around
> > this.
> 
> Hmmmm, I somehow assumed MMCs would be much more cleverr than this.

No, these devices are incredibly stupid, or extremely optimized to
a specific use case (writing large video files to FAT32), depending on how
you look at them.

> > reorders) them? The thresholds would then be adjustable as
> > module/kernel parameters based on manfid. I'm asking because I have a
> > patch now, but its ugly and hardcoded against a specific manufacturer.
> 
> How big is performance difference?

Several orders of magnitude. It is very easy to get a card that can write
12 MB/s into a case where it writes no more than 30 KB/s, doing only
things that happen frequently with ext3.

	Arnd

^ permalink raw reply

* ARM: relocation out of range (when loading a module)
From: Russell King - ARM Linux @ 2011-02-11 14:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTimW9zQ3EcEo8+gcxnS72Wa9VZELvrqdY+jP0B7W@mail.gmail.com>

On Fri, Feb 11, 2011 at 02:25:28PM +0000, Dave Martin wrote:
>  if we can also move the initramfs somewhere less obstructive in the
> future, then so much the better.

This may do it, and it might even work.  Not particularly well tested
yet.  It'd be loads easier if we didn't have to worry about XIP.

 arch/arm/kernel/etm.c         |    2 +-
 arch/arm/kernel/smp.c         |    4 +-
 arch/arm/kernel/vmlinux.lds.S |  133 +++++++++++++++++++++-------------------
 arch/arm/mm/init.c            |    2 +-
 4 files changed, 74 insertions(+), 67 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 11db628..ca477d2 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -114,7 +114,7 @@ static int trace_start(struct tracectx *t)
 		return -EFAULT;
 	}
 
-	etm_setup_address_range(t, 1, (unsigned long)_stext,
+	etm_setup_address_range(t, 1, (unsigned long)_text,
 			(unsigned long)_etext, 0, 0);
 	etm_writel(t, 0, ETMR_TRACEENCTRL2);
 	etm_writel(t, 0, ETMR_TRACESSCTRL);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 4539ebc..8ad77d3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -95,7 +95,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
 #ifndef CONFIG_HOTPLUG_CPU
 		identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
 #endif
-		identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
+		identity_mapping_add(pgd, __pa(_text), __pa(_etext));
 		identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
 	}
 
@@ -143,7 +143,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
 #ifndef CONFIG_HOTPLUG_CPU
 		identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
 #endif
-		identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
+		identity_mapping_del(pgd, __pa(_text), __pa(_etext));
 		identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
 	}
 
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 45b5651..9cd098b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -32,46 +32,98 @@ jiffies = jiffies_64 + 4;
 
 SECTIONS
 {
+	/*
+	 * unwind exit sections must be discarded before the rest of the
+	 * unwind sections get included.
+	 */
+	/DISCARD/ : {
+		*(.ARM.exidx.exit.text)
+		*(.ARM.extab.exit.text)
+		ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+		ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
+#ifndef CONFIG_HOTPLUG
+		*(.ARM.exidx.devexit.text)
+		*(.ARM.extab.devexit.text)
+#endif
+#ifndef CONFIG_MMU
+		*(.fixup)
+		*(__ex_table)
+#endif
+#ifndef CONFIG_SMP_ON_UP
+		*(.alt.smp.init)
+#endif
+	}
+
 #ifdef CONFIG_XIP_KERNEL
 	. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
 #else
 	. = PAGE_OFFSET + TEXT_OFFSET;
 #endif
 
-	.init : {			/* Init code and data		*/
-		_stext = .;
-		_sinittext = .;
-			HEAD_TEXT
-			INIT_TEXT
-		_einittext = .;
+	_text = .;
+	HEAD_TEXT_SECTION
+
+	.text : {			/* Real text segment		*/
+		_stext = .;		/* Text and read-only data	*/
+		__exception_text_start = .;
+		*(.exception.text)
+		__exception_text_end = .;
+		IRQENTRY_TEXT
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+#ifdef CONFIG_MMU
+		*(.fixup)
+#endif
+		*(.gnu.warning)
+		*(.glue_7)
+		*(.glue_7t)
+		. = ALIGN(4);
+		*(.got)			/* Global offset table		*/
+		ARM_CPU_KEEP(PROC_INFO)
+		_etext = .;		/* End of text and rodata section */
+	}
+
+#ifndef CONFIG_XIP_KERNEL
+	. = ALIGN(PAGE_SIZE);
+	__init_begin = .;
+#endif
+	INIT_TEXT_SECTION(0)
+	.init.proc.info : {
 		ARM_CPU_DISCARD(PROC_INFO)
+	}
+	.init.arch.info : {
 		__arch_info_begin = .;
 			*(.arch.info.init)
 		__arch_info_end = .;
+	}
+	.init.tagtable : {
 		__tagtable_begin = .;
 			*(.taglist.init)
 		__tagtable_end = .;
+	}
 #ifdef CONFIG_SMP_ON_UP
+	.init.smpalt : {
 		__smpalt_begin = .;
 			*(.alt.smp.init)
 		__smpalt_end = .;
+	}
 #endif
-
+	.init.pv_table : {
 		__pv_table_begin = .;
 			*(.pv_table)
 		__pv_table_end = .;
-
+	}
+	.init.data : {
+#ifndef CONFIG_XIP_KERNEL
+		INIT_DATA
+#endif
 		INIT_SETUP(16)
-
 		INIT_CALLS
 		CON_INITCALL
 		SECURITY_INITCALL
 		INIT_RAM_FS
-
-#ifndef CONFIG_XIP_KERNEL
-		__init_begin = _stext;
-		INIT_DATA
-#endif
 	}
 
 	PERCPU(PAGE_SIZE)
@@ -79,49 +131,10 @@ SECTIONS
 #ifndef CONFIG_XIP_KERNEL
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
-#endif
 
-	/*
-	 * unwind exit sections must be discarded before the rest of the
-	 * unwind sections get included.
-	 */
-	/DISCARD/ : {
-		*(.ARM.exidx.exit.text)
-		*(.ARM.extab.exit.text)
-		ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
-		ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
-#ifndef CONFIG_HOTPLUG
-		*(.ARM.exidx.devexit.text)
-		*(.ARM.extab.devexit.text)
+	_data = .;
+	_sdata = .;
 #endif
-#ifndef CONFIG_MMU
-		*(.fixup)
-		*(__ex_table)
-#endif
-	}
-
-	.text : {			/* Real text segment		*/
-		_text = .;		/* Text and read-only data	*/
-			__exception_text_start = .;
-			*(.exception.text)
-			__exception_text_end = .;
-			IRQENTRY_TEXT
-			TEXT_TEXT
-			SCHED_TEXT
-			LOCK_TEXT
-			KPROBES_TEXT
-#ifdef CONFIG_MMU
-			*(.fixup)
-#endif
-			*(.gnu.warning)
-			*(.rodata)
-			*(.rodata.*)
-			*(.glue_7)
-			*(.glue_7t)
-		. = ALIGN(4);
-		*(.got)			/* Global offset table		*/
-			ARM_CPU_KEEP(PROC_INFO)
-	}
 
 	RO_DATA(PAGE_SIZE)
 
@@ -142,8 +155,6 @@ SECTIONS
 	}
 #endif
 
-	_etext = .;			/* End of text and rodata section */
-
 #ifdef CONFIG_XIP_KERNEL
 	__data_loc = ALIGN(4);		/* location in binary */
 	. = PAGE_OFFSET + TEXT_OFFSET;
@@ -153,8 +164,10 @@ SECTIONS
 #endif
 
 	.data : AT(__data_loc) {
+#ifdef CONFIG_XIP_KERNEL
 		_data = .;		/* address in memory */
 		_sdata = .;
+#endif
 
 		/*
 		 * first, the init task union, aligned
@@ -259,12 +272,6 @@ SECTIONS
 
 	/* Default discards */
 	DISCARDS
-
-#ifndef CONFIG_SMP_ON_UP
-	/DISCARD/ : {
-		*(.alt.smp.init)
-	}
-#endif
 }
 
 /*
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index cddd684..9e3c3c3 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -294,7 +294,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 #ifdef CONFIG_XIP_KERNEL
 	memblock_reserve(__pa(_sdata), _end - _sdata);
 #else
-	memblock_reserve(__pa(_stext), _end - _stext);
+	memblock_reserve(__pa(_text), _end - _text);
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (phys_initrd_size &&

^ permalink raw reply related

* MMC quirks relating to performance/lifetime.
From: Pavel Machek @ 2011-02-11 14:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTikh4vfS7SLKAa-aUXhbTxcHzYHmBuaXj1qHHYN9@mail.gmail.com>

Hi!

> I'm not sure if this is the best place to bring this up, but Russel's
> name is on a fair share of drivers/mmc code, and there does seem to be
> quite a bit of MMC-related discussions. Excuse me in advance if this
> isn't the right forum :-).
> 
> Certain MMC vendors (maybe even quite a bit of them) use a pretty
> rigid buffering scheme when it comes to handling writes. There is
> usually a buffer A for random accesses, and a buffer B for sequential
> accesses. For certain Toshiba parts, it looks like buffer A is 8KB
> wide, with buffer B being 4MB wide, and all accesses larger than 8KB
> effectively equating to 4MB accesses. Worse, consecutive small (8k)
> writes are treated as one large sequential access, once again ending
> up in buffer B, thus necessitating out-of-order writing to work around
> this.

Hmmmm, I somehow assumed MMCs would be much more cleverr than this.

> reorders) them? The thresholds would then be adjustable as
> module/kernel parameters based on manfid. I'm asking because I have a
> patch now, but its ugly and hardcoded against a specific manufacturer.

How big is performance difference?
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* [PATCH 1/7] mmc: mxs-mmc: add mmc host driver for i.MX23/28
From: Lothar Waßmann @ 2011-02-11 14:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110211221110.GB9289@S2100-06.ap.freescale.net>

Shawn Guo writes:
> Hi Lothar,
> 
> On Tue, Feb 08, 2011 at 12:41:20PM +0100, Lothar Wa?mann wrote:
> > Hi,
> > 
> > Shawn Guo writes:
> > [...]
> > > +static int mxs_mmc_remove(struct platform_device *pdev)
> > > +{
> > > +	struct mmc_host *mmc = platform_get_drvdata(pdev);
> > > +	struct mxs_mmc_host *host = mmc_priv(mmc);
> > > +
> > > +	platform_set_drvdata(pdev, NULL);
> > > +
> > > +	mmc_remove_host(mmc);
> > > +
> > > +	del_timer(&host->timer);
> > > +
> > > +	free_irq(host->irq, host);
> > > +
> > > +	if (host->dmach)
> > > +		dma_release_channel(host->dmach);
> > > +
> > > +	clk_disable(host->clk);
> > > +	clk_put(host->clk);
> > > +
> > > +	iounmap(host->base);
> > > +
> > > +	mmc_free_host(mmc);
> > > +
> > > +	release_mem_region(host->res->start, resource_size(host->res));
> > >
> > When compiled with CONFIG_PAGE_POISON this leads to:
> > |mmc0: card cdef removed
> > |Unable to handle kernel paging request at virtual address 6b6b6b6b
> > |pgd = c6ea4000
> > |[6b6b6b6b] *pgd=00000000
> > |Internal error: Oops: 1 [#1] PREEMPT
> > |last sysfs file: /sys/module/mxs_mmc/refcnt
> > |Modules linked in: mxs_mmc(-) evdev nand nand_ids nand_ecc tsc2007 pca953x
> > |CPU: 0    Not tainted  (2.6.37-karo+ #100)
> > |PC is at mxs_mmc_remove+0x78/0x94 [mxs_mmc]
> > |LR is at mark_held_locks+0x5c/0x84
> > |pc : [<bf03310c>]    lr : [<c0071da0>]    psr: 20000013
> > |sp : c6e33ef8  ip : 6b6b6b6b  fp : be825a38
> > |r10: 00000000  r9 : c6e32000  r8 : c0037888
> > |r7 : 00591700  r6 : c78d24bc  r5 : c6c6ea80  r4 : c6c6ed60
> > |r3 : 6b6b6b6b  r2 : 00000040  r1 : c6d833d0  r0 : c043af18
> > |Flags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
> > |Control: 0005317f  Table: 46ea4000  DAC: 00000015
> > |Process modprobe (pid: 1217, stack limit = 0xc6e32270)
> > |Stack: (0xc6e33ef8 to 0xc6e34000)
> > |3ee0:                                                       c78d2488 bf034100
> > |3f00: c78d24bc c0237034 c78d2488 c0235e68 c78d2488 bf034100 c78d24bc c0235f34
> > |3f20: bf034100 00000080 c045c3e8 c02351c4 bf034138 00000080 c6e33f44 c007de4c
> > |3f40: be82599c 5f73786d 00636d6d 00000000 c01efdf0 c6d830c0 c6d830c0 c03195ec
> > |3f60: 00000001 c6dddbd8 c6e33f7c c0045fc4 c6d830c0 c00377d8 00000001 00000081
> > |3f80: 60000010 c00720d4 be825a2c 00000000 00000001 be825a2c 005916b0 00000001
> > |3fa0: 00000081 c00376c0 be825a2c 005916b0 00591700 00000080 be825994 00000000
> > |3fc0: be825a2c 005916b0 00000001 00000081 00591700 0000c69c 005916bc be825a38
> > |3fe0: 00591520 be8259a0 0000a42c 402aee3c 60000010 00591700 aaaaaaaa aaaaaaaa
> > |[<bf03310c>] (mxs_mmc_remove+0x78/0x94 [mxs_mmc]) from [<c0237034>] (platform_drv_remove+0x18/0x1c)
> > |[<c0237034>] (platform_drv_remove+0x18/0x1c) from [<c0235e68>] (__device_release_driver+0x64/0xa4)
> > |[<c0235e68>] (__device_release_driver+0x64/0xa4) from [<c0235f34>] (driver_detach+0x8c/0xb4)
> > |[<c0235f34>] (driver_detach+0x8c/0xb4) from [<c02351c4>] (bus_remove_driver+0x8c/0xb4)
> > |[<c02351c4>] (bus_remove_driver+0x8c/0xb4) from [<c007de4c>] (sys_delete_module+0x1f4/0x260)
> > |[<c007de4c>] (sys_delete_module+0x1f4/0x260) from [<c00376c0>] (ret_fast_syscall+0x0/0x38)
> > |Code: e1a00005 eb48cd47 e5943008 e59f0014 (e8930006) 
> > |---[ end trace bb06175839554c3b ]---
> > indicating a use_after_free BUG!
> 
> Thanks for catching this.
> 
> > The struct mxs_mmc_host has been already freed here by the
> > preceding mmc_free_host() call. This should be:
> > 	struct resource *res = host->res;
> > ...
> > 	mmc_free_host(mmc);
> > 	release_mem_region(res->start, resource_size(res));
> > 
> How about fixing it like below?
> 
> 	release_mem_region(host->res->start, resource_size(host->res));
> 	mmc_free_host(mmc);
> 
It's also OK. Although I prefer to do the release_mem_region() as the
last action, because the corresponding request_mem_region() is the
first action of the driver.

I still have some more comments:
|static int mxs_mmc_remove(struct platform_device *pdev)
|{
|	struct mmc_host *mmc = platform_get_drvdata(pdev);
|	struct mxs_mmc_host *host = mmc_priv(mmc);
|
|	platform_set_drvdata(pdev, NULL);
This should be done after the driver has been quiesced (i.e. after
free_irq). It's not relevant in this case right now, but cleaner
anyway since some timer or IRQ handler might still be triggered and
call platform_get_drvdata().
If you always care to do the actions in the remove() function in the
opposite order as the corresponding actions in the probe() function
things will usually be in the right order automatically.

|static int mxs_mmc_suspend(struct device *dev)
|{
|	struct mmc_host *mmc = dev_get_drvdata(dev);
|	struct mxs_mmc_host *host = mmc_priv(mmc);
|	int ret = 0;
|
|	if (mmc)
'mmc' cannot be NULL here. And as it has already been dereferenced
by mmc_priv(mmc) above, it makes even less sense to check it here.

|static int mxs_mmc_resume(struct device *dev)
|{
|	struct mmc_host *mmc = dev_get_drvdata(dev);
|	struct mxs_mmc_host *host = mmc_priv(mmc);
|	int ret = 0;
|
|	clk_enable(host->clk);
|
|	if (mmc)
same as above.


Lothar Wa?mann
-- 
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________

^ permalink raw reply

* ARM: relocation out of range (when loading a module)
From: Dave Martin @ 2011-02-11 14:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1102110838430.14920@xanadu.home>

On Fri, Feb 11, 2011 at 1:51 PM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Fri, 11 Feb 2011, Dave Martin wrote:
>
>> On Thu, Feb 10, 2011 at 7:41 PM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> > On Thu, 10 Feb 2011, Russell King - ARM Linux wrote:
>> >
>> >> On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
>> >> > The MMU-less kernel should still favor allocations close to the kernel
>> >> > text for modules, and anything else away from the kernel going
>> >> > downwards.
>> >> >
>> >> > Otherwise a veneer should be created by the module symbol resolver such
>> >> > that if the branch distance to reach, say, printk is too large, then the
>> >> > following code would have to be dynamically generated right next to the
>> >> > module:
>> >> >
>> >> > ? ? ldr ? ? pc, [pc, #-4]
>> >> > ? ? .word ? <far_away_symbol>
>> >> >
>> >> > Then, in your module, you patch the branch relocation for printk so that
>> >> > it branches to the code above instead, and then store the address of
>> >> > printk at the location represented by the .word directive.
>> >>
>> >> What you're suggesting is what we used to do with the old user-space
>> >> module tools, which would've been nice to carry forwards to the new
>> >> module code. ?I never found a way to do it.
>> >>
>> >> The problems:
>> >> 1. Where do you create those veneers?
>> >> 2. How many veneers do you allocate space for?
>> >> 3. How do you determine that you need a veneer?
>> >>
>> >> While you can say "next to the module" for (1), you can only do that at
>> >> the point in time when the space for the module is allocated, and you
>> >> need to know at that point how much space you require.
>> >
>> > You would have to guess of course. ?Having a guess of 1/2 the module
>> > size should be pretty safe. ?So allocating 3/2 the space in
>> > module_alloc(), and then suffice to free the unused portion in
>> > module_finalize().
>> >
>> >> For (2), you could always allocate space for one veneer per symbol present
>> >> in the module, but that's very wasteful.
>> >>
>> >> (3) is almost impossible to know ahead of time as you don't have the
>> >> relocations, realistically you have to allocate one veneer per symbol,
>> >> and as you don't know whether it's a data or code symbol, you'll have
>> >> to allocate one veneer for every symbol in a module.
>> >
>> > I don't think you may know the number of symbols in advance either
>> > anyway.
>>
>> You could probably cook up a good upper bound based on the size of the
>> kernel and the number of symbols in the module: i.e., assume that
>> every undefined symbol in the module needs to be fixed up to point at
>> the most distant symbol in the kernel.
>
> Sure... It is just that the memory allocation is currently done before
> the number of symbols in the module is known. ?Changing that would
> require non trivial changes in the generic module loading code which
> potentially would affect all architectures, and therefore I don't think
> we want to go there.
>
> The other solution would be to determine the number of objects in need
> of a veneer in apply_relocate(), allocate a replacement area for the
> module, copy everything over, and then create the veneers close to the
> module. ?But 1) the second allocation may fail, and 2) this will change
> the distance from the kernel potentially requiring more veneers than
> initially determined, and 3) the generic module code might still have
> pointer references into the old allocation area (didn't check but that
> can be expected). ?That's just too messy.
>
>> For people with normal-sized kernels, this bound will probably work
>> out as zero most of the time (i.e., the current situation). ?For
>> people with big kernels, or when many modules are already loaded, it
>> may work out at 100% -- but that's the price to pay for guaranteed
>> preallocation of the space required for the veneers. ?And anyway, you
>> may really need a substantial chunk of those veneers in such cases.
>
> I still think that compiling modules with -mlong-calls, and making that
> conditional on a kernel config option so only those who need it will
> have it, is the simplest solution. ?Nothing in the kernel code would
> need to be changed.

Yes, this sounds like a reasonable solution for now ... since most
people don't need this turned on anyway, and those that do need it
know who they are.

 if we can also move the initramfs somewhere less obstructive in the
future, then so much the better.

Cheers
---Dave

^ permalink raw reply

* [PATCH 0/5] ARM: Few patches for PM enablement.
From: Santosh Shilimkar @ 2011-02-11 14:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f804b2179a222189b71c9429285de723@mail.gmail.com>

Russell,
> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
> Sent: Friday, February 04, 2011 3:49 PM
> To: Russell King - ARM Linux
> Cc: linux-omap at vger.kernel.org; ccross at android.com;
> catalin.marinas at arm.com; linus.ml.walleij at gmail.com; linux-arm-
> kernel at lists.infradead.org
> Subject: RE: [PATCH 0/5] ARM: Few patches for PM enablement.
>

> ARM: gic: Add hooks for architecture specific extensions
> ARM: gic: Add distributor and interface enable/disable accessory api
I plan to submit below to patches to your patch system.

> ARM: twd: Add context save restore support
> ARM: scu: Move register defines to header file
Alternate for these two are already in you tree, so I drop them.

> ARM: smp: Skip secondary cpu calibration to speed-up boot
This one we still haven't agree. So I postpone this one till you
find any other better way to handle this though I really hate that
~ 200 ms in this path.

Regards,
Santosh

^ permalink raw reply

* [PATCH 1/1] davinci: changed SRAM allocator to shared ram.
From: Subhasish Ghosh @ 2011-02-11 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

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

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/da850.c              |    6 +++---
 arch/arm/mach-davinci/include/mach/da8xx.h |    1 +
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 3443d97..8a4de97 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -711,7 +711,7 @@ static struct map_desc da850_io_desc[] = {
 	},
 	{
 		.virtual	= SRAM_VIRT,
-		.pfn		= __phys_to_pfn(DA8XX_ARM_RAM_BASE),
+		.pfn		= __phys_to_pfn(DA8XX_SHARED_RAM_BASE),
 		.length		= SZ_8K,
 		.type		= MT_DEVICE
 	},
@@ -1083,8 +1083,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,
 	.reset_device		= &da8xx_wdt_device,
 };
 
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index cfcb223..c3c3339 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -70,6 +70,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_AEMIF_CTL_BASE	0x68000000
 #define DA8XX_DDR2_CTL_BASE	0xb0000000
 #define DA8XX_ARM_RAM_BASE	0xffff0000
+#define DA8XX_SHARED_RAM_BASE	0x80000000
 
 void __init da830_init(void);
 void __init da850_init(void);
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH 1/1] da830: macro rename DA8XX_LPSC0_DMAX to DA8XX_LPSC0_PRUSS.
From: Subhasish Ghosh @ 2011-02-11 14:18 UTC (permalink / raw)
  To: linux-arm-kernel

The PRUSS was named as DMAX on da830 platform.
This patch resolves the naming conflict by replacing the macro
DA8XX_LPSC0_DMAX with DA8XX_LPSC0_PRUSS.

Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
---
 arch/arm/mach-davinci/da830.c            |    2 +-
 arch/arm/mach-davinci/include/mach/psc.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index ec23ab4..0577a5d 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -148,7 +148,7 @@ static struct clk scr2_ss_clk = {
 static struct clk dmax_clk = {
 	.name		= "dmax",
 	.parent		= &pll0_sysclk2,
-	.lpsc		= DA8XX_LPSC0_DMAX,
+	.lpsc		= DA8XX_LPSC0_PRUSS,
 	.flags		= ALWAYS_ENABLED,
 };
 
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 62b0858..a47e6f2 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -150,7 +150,7 @@
 #define DA8XX_LPSC0_SCR0_SS		10
 #define DA8XX_LPSC0_SCR1_SS		11
 #define DA8XX_LPSC0_SCR2_SS		12
-#define DA8XX_LPSC0_DMAX		13
+#define DA8XX_LPSC0_PRUSS		13
 #define DA8XX_LPSC0_ARM			14
 #define DA8XX_LPSC0_GEM			15
 
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH v3] i.MX51 iomux: Fixes MX51_PAD_UART2_TXD__UART2_TXD & MX51_PAD_USBH1_DATA2__UART2_TXD declarations
From: julien.boibessot at free.fr @ 2011-02-11 14:15 UTC (permalink / raw)
  To: linux-arm-kernel

From: Julien Boibessot <julien.boibessot@armadeus.com>

Fixes 2 small regressions of recent iomux changes:
 - current MX51_PAD_UART2_TXD__UART2_TXD declaration overwrites
   IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT register (0x09ec) and prevent
   UART2 Rx from working properly.
   (Tested on my custom i.MX51 board where UART2 is used as console)
 - current MX51_PAD_USBH1_DATA2__UART2_TXD declaration also has the same problem.
   (Not tested)

Signed-off-by: Julien Boibessot <julien.boibessot@armadeus.com>
---
Changes since v2:
 - Also correct MX51_PAD_USBH1_DATA2__UART2_TXD as pointed by Richard Zhao
Changes since v1:
 - Improve patch description as requested by Sascha Hauer

 arch/arm/plat-mxc/include/mach/iomux-mx51.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index b6767f9..6056cf2 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -473,7 +473,7 @@
 #define _MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x09ec, 2, 0)
 #define _MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, 0x0000, 0, 0)
 #define _MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x09ec, 3, 0)
+#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, 0x0000, 0, 0)
@@ -528,7 +528,7 @@
 #define _MX51_PAD_USBH1_DATA1__UART2_RXD	IOMUX_PAD(0x68c, 0x28c, 1, 0x09ec, 4, 0)
 #define _MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
+#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA3__UART2_RTS	IOMUX_PAD(0x694, 0x294, 1, 0x09e8, 5, 0)
-- 
1.6.0.4

^ permalink raw reply related

* [PATCH] arm: update gitignore file
From: Sergei Shtylyov @ 2011-02-11 14:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297387616-29390-1-git-send-email-rklein@nvidia.com>

Hello.

On 11-02-2011 4:26, rklein at nvidia.com wrote:

> From: Rhyland Klein<rklein@nvidia.com>

> Updating the .gitignore file to ignore 3 files that are always created in
> manual builds to cleanup git status results.

> Signed-off-by: Rhyland Klein<rklein@nvidia.com>
> ---
>   arch/arm/boot/compressed/.gitignore |    3 +++
>   1 files changed, 3 insertions(+), 0 deletions(-)

> diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
> index ab204db..c52a6dd 100644
> --- a/arch/arm/boot/compressed/.gitignore
> +++ b/arch/arm/boot/compressed/.gitignore
> @@ -1,3 +1,6 @@
>   font.c
>   piggy.gz
>   vmlinux.lds
> +lib1funcs.S
> +piggy.gzip
> +vmlinux

    Similar patch has already been submitted several times by Sergio Aguirre...

WBR, Sergei

^ permalink raw reply

* [PATCH v2] i.MX51 iomux: Fixes MX51_PAD_UART2_TXD__UART2_TXD declaration
From: Lothar Waßmann @ 2011-02-11 13:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110211133945.GA2282@richard-laptop>

Hi,

Richard Zhao writes:
> On Fri, Feb 11, 2011 at 02:05:21PM +0100, Lothar Wa?mann wrote:
> > Hi,
> > 
> > Richard Zhao writes:
> > > Hi Julien,
> > > 
> > > #define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
> > > 
> > > Will you change the above line too?
> > > 
> > Seems like a general copy/paste error in the i.MX51 Ref Manual.
> > For all pads that can have an UART RXD or TXD function the manual
> > states that the UART*_IPP_UART_RXD_MUX_SELECT_INPUT register must be
> > configured, while this is obviously only sensible for the RXD
> > function.
> Yes, it's for RXD. RXD can also select input from TXD.
> 
The RXD function can be routed to the TXD pads via
RXD_MUX_SELECT_INPUT, but IMO setting the INPUT_MUX for an OUTPUT
function (TXD) is nonsense.

E.g.:
|Table A-1271. Register: IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT
|
|010: Selecting Pad: UART2_RXD for Mode: ALT0.
|011: Selecting Pad: UART2_TXD for Mode: ALT0.
so, the input path for the RXD function can be routed to either the
UART2_RXD or UART2_TXD pad.

|Table A-286. Register IOMUXC_SW_MUX_CTL_PAD_UART2_RXD Bits Description
|000: Select mux mode: ALT0 mux port: RXD_MUX of instance: uart2.
|NOTE: Pad UART2_RXD is involved in Daisy Chain.
|- Config Register IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT for mode
|ALT0.
This is OK. RXD_MUX is an input whose source is defined by the
RXD_MUX_SELECT_INPUT register.

But:
|Table A-288. Register IOMUXC_SW_MUX_CTL_PAD_UART2_TXD Bits Description
|000: Select mux mode: ALT0 mux port: TXD_MUX of instance: uart2.
|
|NOTE: Pad UART2_TXD is involved in Daisy Chain.
|- Config Register IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT for mode
|ALT0.
IMO does not make any sense. TXD_MUX is an OUTPUT function.
How can the INPUT MUX route an OUTPUT PAD?

Also, the table Table 4-3. i.MX51 Daisy Chain Settings only mentions
the uart_rxd_mux pins, but not uart_txd_mux.


Lothar Wa?mann
-- 
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________

^ permalink raw reply

* ARM: relocation out of range (when loading a module)
From: Nicolas Pitre @ 2011-02-11 13:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTikBJw4tS6cGjUMSPjCGCkURBUdZCfwvmMtsDcG4@mail.gmail.com>

On Fri, 11 Feb 2011, Dave Martin wrote:

> On Fri, Feb 11, 2011 at 9:38 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Fri, Feb 11, 2011 at 09:31:04AM +0000, Dave Martin wrote:
> >> You could probably cook up a good upper bound based on the size of the
> >> kernel and the number of symbols in the module: i.e., assume that
> >> every undefined symbol in the module needs to be fixed up to point at
> >> the most distant symbol in the kernel.
> >>
> >> For people with normal-sized kernels, this bound will probably work
> >> out as zero most of the time (i.e., the current situation). ?For
> >> people with big kernels, or when many modules are already loaded, it
> >> may work out at 100% -- but that's the price to pay for guaranteed
> >> preallocation of the space required for the veneers. ?And anyway, you
> >> may really need a substantial chunk of those veneers in such cases.
> >
> > I think it's going to be easier just to re-order the kernel image link
> > order to solve that problem. ?That just leaves uclinux...
> >
> 
> But if the kernel is big, or there are many modules, changing the
> order can't solve the problem surely?  Or is the problem purely caused
> by having the initramfs in the way, and we think the amount of actual
> code will never be big enough to cause a problem?

Right now the biggest problem comes from the size of the initramfs.  The 
solution for that is simply to move it elsewhere towards the end of the 
kernel image instead of at the beginning.  And I think we're good for a 
couple years before the actual kernel code size becomes an issue.


Nicolas

^ permalink raw reply

* ARM: relocation out of range (when loading a module)
From: Nicolas Pitre @ 2011-02-11 13:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTi=KtFf5BU-iH-sUUL=Q30S90bk608JR4zFz2CKf@mail.gmail.com>

On Fri, 11 Feb 2011, Dave Martin wrote:

> On Thu, Feb 10, 2011 at 7:41 PM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> > On Thu, 10 Feb 2011, Russell King - ARM Linux wrote:
> >
> >> On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
> >> > The MMU-less kernel should still favor allocations close to the kernel
> >> > text for modules, and anything else away from the kernel going
> >> > downwards.
> >> >
> >> > Otherwise a veneer should be created by the module symbol resolver such
> >> > that if the branch distance to reach, say, printk is too large, then the
> >> > following code would have to be dynamically generated right next to the
> >> > module:
> >> >
> >> > ? ? ldr ? ? pc, [pc, #-4]
> >> > ? ? .word ? <far_away_symbol>
> >> >
> >> > Then, in your module, you patch the branch relocation for printk so that
> >> > it branches to the code above instead, and then store the address of
> >> > printk at the location represented by the .word directive.
> >>
> >> What you're suggesting is what we used to do with the old user-space
> >> module tools, which would've been nice to carry forwards to the new
> >> module code. ?I never found a way to do it.
> >>
> >> The problems:
> >> 1. Where do you create those veneers?
> >> 2. How many veneers do you allocate space for?
> >> 3. How do you determine that you need a veneer?
> >>
> >> While you can say "next to the module" for (1), you can only do that at
> >> the point in time when the space for the module is allocated, and you
> >> need to know at that point how much space you require.
> >
> > You would have to guess of course. ?Having a guess of 1/2 the module
> > size should be pretty safe. ?So allocating 3/2 the space in
> > module_alloc(), and then suffice to free the unused portion in
> > module_finalize().
> >
> >> For (2), you could always allocate space for one veneer per symbol present
> >> in the module, but that's very wasteful.
> >>
> >> (3) is almost impossible to know ahead of time as you don't have the
> >> relocations, realistically you have to allocate one veneer per symbol,
> >> and as you don't know whether it's a data or code symbol, you'll have
> >> to allocate one veneer for every symbol in a module.
> >
> > I don't think you may know the number of symbols in advance either
> > anyway.
> 
> You could probably cook up a good upper bound based on the size of the
> kernel and the number of symbols in the module: i.e., assume that
> every undefined symbol in the module needs to be fixed up to point at
> the most distant symbol in the kernel.

Sure... It is just that the memory allocation is currently done before 
the number of symbols in the module is known.  Changing that would 
require non trivial changes in the generic module loading code which 
potentially would affect all architectures, and therefore I don't think 
we want to go there.

The other solution would be to determine the number of objects in need 
of a veneer in apply_relocate(), allocate a replacement area for the 
module, copy everything over, and then create the veneers close to the 
module.  But 1) the second allocation may fail, and 2) this will change 
the distance from the kernel potentially requiring more veneers than 
initially determined, and 3) the generic module code might still have 
pointer references into the old allocation area (didn't check but that 
can be expected).  That's just too messy.

> For people with normal-sized kernels, this bound will probably work
> out as zero most of the time (i.e., the current situation).  For
> people with big kernels, or when many modules are already loaded, it
> may work out at 100% -- but that's the price to pay for guaranteed
> preallocation of the space required for the veneers.  And anyway, you
> may really need a substantial chunk of those veneers in such cases.

I still think that compiling modules with -mlong-calls, and making that 
conditional on a kernel config option so only those who need it will 
have it, is the simplest solution.  Nothing in the kernel code would 
need to be changed.


Nicolas

^ permalink raw reply

* [PATCH] RTC: Include information about UIE and PIE in RTC driver proc.
From: Marcelo Roberto Jimenez @ 2011-02-11 13:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297432224-14001-1-git-send-email-mroberto@cpti.cetuc.puc-rio.br>

Generic RTC code is always able to provide the necessary information
about update and periodic interrupts. This patch add such information to
the proc interface.

Signed-off-by: Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
---
 drivers/rtc/rtc-proc.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index c086fc3..a61091c 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -69,6 +69,14 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
 				alrm.enabled ? "yes" : "no");
 		seq_printf(seq, "alrm_pending\t: %s\n",
 				alrm.pending ? "yes" : "no");
+		seq_printf(seq, "update IRQ enabled\t: %s\n",
+			(rtc->uie_rtctimer.enabled) ? "yes" : "no");
+		seq_printf(seq, "periodic IRQ enabled\t: %s\n",
+			(rtc->pie_enabled) ? "yes" : "no");
+		seq_printf(seq, "periodic IRQ frequency\t: %d\n",
+			rtc->irq_freq);
+		seq_printf(seq, "max user IRQ frequency\t: %d\n",
+			rtc->max_user_freq);
 	}
 
 	seq_printf(seq, "24hr\t\t: yes\n");
-- 
1.7.3.4

^ permalink raw reply related

* [PATCH 1/4] RTC: Include information about UIE and PIE in RTC driver proc.
From: Marcelo Roberto Jimenez @ 2011-02-11 13:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi again,

On Fri, Feb 11, 2011 at 10:34, Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br> wrote:
Hi John,

On Thu, Feb 10, 2011 at 21:06, John Stultz <john.stultz@linaro.org> wrote:
>
>> This seems to be mostly formatting changes. Are you sure we wont' break
>> applications expecting the existing format?
>>
> No, I can't be 100% sure, ...

While reworking the patch, I can be 100% sure it would break because it fixed a typo and changed two names, so it was not white space at all.

The reworked patch follows.

Regards,
Marcelo.

^ permalink raw reply

* [PATCH v2 5/5] ARM: omap3: Thumb-2 compatibility for sleep34xx.S
From: Dave Martin @ 2011-02-11 13:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87ei7fe8mk.fsf@ti.com>

On Fri, Feb 11, 2011 at 12:07 AM, Kevin Hilman <khilman@ti.com> wrote:
> Kevin Hilman <khilman@ti.com> writes:
>
>> Dave Martin <dave.martin@linaro.org> writes:
>>
>>> ?* Use BSYM() to get the correct Thumb branch address
>>> ? ?for adr <Rd>, <label>
>>>
>>> ?* Fix an out-of-range ADR when building for ARM
>>>
>>> ?* Correctly call es3_sdrc_fix as Thumb when copied to SRAM.
>>>
>>> ?* Remove deprecated/undefined PC-relative stores
>>>
>>> ?* Add the required ENDPROC() directive for each ENTRY().
>>>
>>> ?* .align before data words
>>>
>>> Signed-off-by: Dave Martin <dave.martin@linaro.org>
>>
>> I'm attempting to test this series with OMAP PM, but some changes here
>> don't compile for me.
>>
>> My toolchain is: gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50)
>>
>> First, I merged your arm/omap-thumb2+merged branch with my pm branch
>> from git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git
>
> Sorry for the confusion, this patch should've been in reply to your v4
> version, since I merged with your 'arm/omap-thumb2+merged' branch from
> today.

If you are able to test off mode with CONFIG_THUMB2_KERNEL enabled,
that would be great.

I have some evidence that the resume path may be working in Thumb-2,
but I think I'm being bitten by erratum i583 (I have to disable the
workaround to even attempt to test off mode on Beagle xM)

Cheers
---Dave

^ permalink raw reply

* [PATCH v2] i.MX51 iomux: Fixes MX51_PAD_UART2_TXD__UART2_TXD declaration
From: Julien Boibessot @ 2011-02-11 13:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110211122505.GB1866@richard-laptop>

Hi Richard,

Richard Zhao a ?crit :
> #define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
>
> Will you change the above line too?
>   
yes, you're right, it needs too.

Julien

^ permalink raw reply

* [PATCH v2] i.MX51 iomux: Fixes MX51_PAD_UART2_TXD__UART2_TXD declaration
From: Richard Zhao @ 2011-02-11 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <19797.13329.366998.503112@ipc1.ka-ro>

On Fri, Feb 11, 2011 at 02:05:21PM +0100, Lothar Wa?mann wrote:
> Hi,
> 
> Richard Zhao writes:
> > Hi Julien,
> > 
> > #define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
> > 
> > Will you change the above line too?
> > 
> Seems like a general copy/paste error in the i.MX51 Ref Manual.
> For all pads that can have an UART RXD or TXD function the manual
> states that the UART*_IPP_UART_RXD_MUX_SELECT_INPUT register must be
> configured, while this is obviously only sensible for the RXD
> function.
Yes, it's for RXD. RXD can also select input from TXD.

Thanks
Richard
> 
> 
> Lothar Wa?mann
> -- 
> ___________________________________________________________
> 
> Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
> Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
> Gesch?ftsf?hrer: Matthias Kaussen
> Handelsregistereintrag: Amtsgericht Aachen, HRB 4996
> 
> www.karo-electronics.de | info at karo-electronics.de
> ___________________________________________________________

^ permalink raw reply

* [PATCH] ARM: SAMSUNG: Removing dependency on CONFIG_PM_DEBUG for clock debugging
From: Amit Kucheria @ 2011-02-11 13:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTinPP5Qi5KbQSwPbQoBVdNdkOV-mDMiTkJvzrcS8@mail.gmail.com>

On Fri, Feb 11, 2011 at 11:22 AM, Amit Kachhap <amit.kachhap@linaro.org> wrote:
> yes this is a temporary patch untill all the PM
> components(sleep/resume) are mainlined.
> The exact compilation error is,
>
> ?CC ? ? ?arch/arm/plat-samsung/pm.o
> arch/arm/plat-samsung/pm.c:32: fatal error: mach/pm-core.h: No such
> file or directory
>
> compilation terminated.
> make[1]: *** [arch/arm/plat-samsung/pm.o] Error 1

Your patch is just masking the real problem in that case. Do you
really need to include mach/pm-core.h in plat-samsung/pm.c?

So the real problem seems to be that the platform hasn't been
test-compiled with CONFIG_PM enabled perhaps?

/Amit

> Thanks,
> Amit Daniel
>
>
> On 11 February 2011 02:57, Amit Kucheria <amit.kucheria@linaro.org> wrote:
>>
>> On Sat, Feb 12, 2011 at 7:06 PM, Amit Daniel Kachhap
>> <amit.kachhap@linaro.org> wrote:
>> > Enabling the macro CONFIG_PM_DEBUG is causing compilation error as all PM components
>> > are included which is not in mainline for samsung V310 platform, therefore, this patch
>> > removes the dependency on macro CONFIG_PM_DEBUG for clock debugging through debugfs
>> > interface.
>>
>> What is the exact error? Might be helpful to have it in the patch description.
>>
>> Presumably, this is a temporary patch until PM components
>> (suspend/resume hooks?) are mainlined and then we can put all this
>> back under PM_DEBUG? In that case, it might be a good idea to mark it
>> as such.
>>
>> Regards,
>> Amit

^ permalink raw reply

* [PATCH v2] i.MX51 iomux: Fixes MX51_PAD_UART2_TXD__UART2_TXD declaration
From: Lothar Waßmann @ 2011-02-11 13:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110211122505.GB1866@richard-laptop>

Hi,

Richard Zhao writes:
> Hi Julien,
> 
> #define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
> 
> Will you change the above line too?
> 
Seems like a general copy/paste error in the i.MX51 Ref Manual.
For all pads that can have an UART RXD or TXD function the manual
states that the UART*_IPP_UART_RXD_MUX_SELECT_INPUT register must be
configured, while this is obviously only sensible for the RXD
function.


Lothar Wa?mann
-- 
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________

^ permalink raw reply

* [RFC PATCH 3/3] ARM: vfp: Use cpu pm notifiers to save vfp state
From: Catalin Marinas @ 2011-02-11 12:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110211122410.GF23404@n2100.arm.linux.org.uk>

On 11 February 2011 12:24, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Fri, Feb 11, 2011 at 12:12:25PM +0000, Catalin Marinas wrote:
>> On SMP systems, we save the VFP at every context switch to deal with the
>> thread migration (though I have a plan to make this lazily on SMP as
>> well).
>
> I'm not sure it's worth the complexity. ?You'd have to do an IPI to the
> old CPU to provoke it to save the context from its VFP unit. ?You'd have
> to do that in some kind of atomic way as the old CPU may be in the middle
> of already saving it. ?You're also going to have to add locking to the
> last_VFP_context[] array as other CPUs will be accessing non-local
> entries, and that means doing locking in assembly. ?Yuck.

I wasn't thinking about that, too complex indeed. But it may be easier
to detect thread migration, possibly with some hooks into generic
scheduler and only save the VFP state at that point. I haven't looked
in detail but I heard the x86 people have patches for something
similar.

-- 
Catalin

^ permalink raw reply

* [PATCH 2.6.39 3/3] ARM: simpad: add GPIO based device definitions
From: Jochen Friedrich @ 2011-02-11 12:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297427836-6341-1-git-send-email-jochen@scram.de>

Register LED, keyboard, polled keyboard and I2C platform
devices based on GPIOs.

Make LED resources conditional to CONFIG_LEDS to avoid
using the legacy ARM LED code and generic GPIO LED code
concurrently on the same GPIO pin.

Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
 arch/arm/mach-sa1100/simpad.c |   99 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 98 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index ec6e381..058a3ee 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -29,6 +29,10 @@
 
 #include <linux/serial_core.h>
 #include <linux/ioport.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <linux/i2c-gpio.h>
 
 #include "generic.h"
 
@@ -249,6 +253,93 @@ static void simpad_power_off(void)
 
 }
 
+/*
+ * gpio_keys
+ */
+
+static struct gpio_keys_button simpad_button_table[] = {
+	{ KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" },
+};
+
+static struct gpio_keys_platform_data simpad_keys_data = {
+	.buttons = simpad_button_table,
+	.nbuttons = ARRAY_SIZE(simpad_button_table),
+};
+
+static struct platform_device simpad_keys = {
+	.name = "gpio-keys",
+	.dev = {
+		.platform_data = &simpad_keys_data,
+	},
+};
+
+static struct gpio_keys_button simpad_polled_button_table[] = {
+	{ KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" },
+	{ KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" },
+	{ KEY_UP,    SIMPAD_UCB1X00_GPIO_UP,    1, "up button" },
+	{ KEY_DOWN,  SIMPAD_UCB1X00_GPIO_DOWN,  1, "down button" },
+	{ KEY_LEFT,  SIMPAD_UCB1X00_GPIO_LEFT,  1, "left button" },
+	{ KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" },
+};
+
+static struct gpio_keys_platform_data simpad_polled_keys_data = {
+	.buttons = simpad_polled_button_table,
+	.nbuttons = ARRAY_SIZE(simpad_polled_button_table),
+	.poll_interval = 50,
+};
+
+static struct platform_device simpad_polled_keys = {
+	.name = "gpio-keys-polled",
+	.dev = {
+		.platform_data = &simpad_polled_keys_data,
+	},
+};
+
+/*
+ * GPIO LEDs
+ */
+
+#ifndef CONFIG_LEDS
+static struct gpio_led simpad_leds[] = {
+	{
+		.name = "power",
+		.gpio = SIMPAD_CS3_LED2_ON,
+		.active_low = 0,
+		.default_trigger = "default-on",
+	},
+};
+
+static struct gpio_led_platform_data simpad_led_data = {
+	.num_leds = 1,
+	.leds = simpad_leds,
+};
+
+static struct platform_device simpad_gpio_leds = {
+	.name = "leds-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data = &simpad_led_data,
+	},
+};
+#endif
+
+/*
+ * i2c
+ */
+static struct i2c_gpio_platform_data simpad_i2c_data = {
+	.sda_pin = GPIO_GPIO21,
+	.scl_pin = GPIO_GPIO25,
+	.udelay = 10,
+	.timeout = HZ,
+};
+
+static struct platform_device simpad_i2c = {
+	.name = "i2c-gpio",
+	.id = 0,
+	.dev = {
+		.platform_data = &simpad_i2c_data,
+	},
+};
 
 /*
  * MediaQ Video Device
@@ -259,7 +350,13 @@ static struct platform_device simpad_mq200fb = {
 };
 
 static struct platform_device *devices[] __initdata = {
-	&simpad_mq200fb
+	&simpad_keys,
+	&simpad_polled_keys,
+	&simpad_mq200fb,
+#ifndef CONFIG_LEDS
+	&simpad_gpio_leds,
+#endif
+	&simpad_i2c,
 };
 
 
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH 2.6.39 2/3] ARM: simpad: Cleanup CS3 accessors and add GPIO API
From: Jochen Friedrich @ 2011-02-11 12:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297427836-6341-1-git-send-email-jochen@scram.de>

- prepend CS3 accessors by simpad_ to indicate they
  are specific to simpad devices.
- use spinlock to protect shadow register.
- implement 8 read-only pins.
- use readl/writel macros so barriers are used where
  necessary.
- register CS3 as GPIO controller with 24 pins
  (16 output only and 8 input only).

Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
 arch/arm/mach-sa1100/include/mach/simpad.h |   81 ++++++++++++++------
 arch/arm/mach-sa1100/leds-simpad.c         |    7 +-
 arch/arm/mach-sa1100/simpad.c              |  115 ++++++++++++++++++++++------
 drivers/pcmcia/sa1100_simpad.c             |   30 +++----
 4 files changed, 165 insertions(+), 68 deletions(-)

diff --git a/arch/arm/mach-sa1100/include/mach/simpad.h b/arch/arm/mach-sa1100/include/mach/simpad.h
index 231550d..db28118 100644
--- a/arch/arm/mach-sa1100/include/mach/simpad.h
+++ b/arch/arm/mach-sa1100/include/mach/simpad.h
@@ -61,32 +61,67 @@
 #define SIMPAD_UCB1X00_GPIO_HEADSET	(SIMPAD_UCB1X00_GPIO_BASE + 8)
 #define SIMPAD_UCB1X00_GPIO_SPEAKER	(SIMPAD_UCB1X00_GPIO_BASE + 9)
 
-// CS3 Latch is write only, a shadow is necessary
+/*--- CS3 Latch ---*/
+#define SIMPAD_CS3_GPIO_BASE		(GPIO_MAX + 11)
+#define SIMPAD_CS3_VCC_5V_EN		(SIMPAD_CS3_GPIO_BASE)
+#define SIMPAD_CS3_VCC_3V_EN		(SIMPAD_CS3_GPIO_BASE + 1)
+#define SIMPAD_CS3_EN1			(SIMPAD_CS3_GPIO_BASE + 2)
+#define SIMPAD_CS3_EN0			(SIMPAD_CS3_GPIO_BASE + 3)
+#define SIMPAD_CS3_DISPLAY_ON		(SIMPAD_CS3_GPIO_BASE + 4)
+#define SIMPAD_CS3_PCMCIA_BUFF_DIS	(SIMPAD_CS3_GPIO_BASE + 5)
+#define SIMPAD_CS3_MQ_RESET		(SIMPAD_CS3_GPIO_BASE + 6)
+#define SIMPAD_CS3_PCMCIA_RESET		(SIMPAD_CS3_GPIO_BASE + 7)
+#define SIMPAD_CS3_DECT_POWER_ON	(SIMPAD_CS3_GPIO_BASE + 8)
+#define SIMPAD_CS3_IRDA_SD		(SIMPAD_CS3_GPIO_BASE + 9)
+#define SIMPAD_CS3_RS232_ON		(SIMPAD_CS3_GPIO_BASE + 10)
+#define SIMPAD_CS3_SD_MEDIAQ		(SIMPAD_CS3_GPIO_BASE + 11)
+#define SIMPAD_CS3_LED2_ON		(SIMPAD_CS3_GPIO_BASE + 12)
+#define SIMPAD_CS3_IRDA_MODE		(SIMPAD_CS3_GPIO_BASE + 13)
+#define SIMPAD_CS3_ENABLE_5V		(SIMPAD_CS3_GPIO_BASE + 14)
+#define SIMPAD_CS3_RESET_SIMCARD	(SIMPAD_CS3_GPIO_BASE + 15)
+
+#define SIMPAD_CS3_PCMCIA_BVD1		(SIMPAD_CS3_GPIO_BASE + 16)
+#define SIMPAD_CS3_PCMCIA_BVD2		(SIMPAD_CS3_GPIO_BASE + 17)
+#define SIMPAD_CS3_PCMCIA_VS1		(SIMPAD_CS3_GPIO_BASE + 18)
+#define SIMPAD_CS3_PCMCIA_VS2		(SIMPAD_CS3_GPIO_BASE + 19)
+#define SIMPAD_CS3_LOCK_IND		(SIMPAD_CS3_GPIO_BASE + 20)
+#define SIMPAD_CS3_CHARGING_STATE	(SIMPAD_CS3_GPIO_BASE + 21)
+#define SIMPAD_CS3_PCMCIA_SHORT		(SIMPAD_CS3_GPIO_BASE + 22)
+#define SIMPAD_CS3_GPIO_23		(SIMPAD_CS3_GPIO_BASE + 23)
 
-#define CS3BUSTYPE unsigned volatile long
 #define CS3_BASE        0xf1000000
 
-#define VCC_5V_EN       0x0001 // For 5V PCMCIA
-#define VCC_3V_EN       0x0002 // FOR 3.3V PCMCIA
-#define EN1             0x0004 // This is only for EPROM's
-#define EN0             0x0008 // Both should be enable for 3.3V or 5V
-#define DISPLAY_ON      0x0010
-#define PCMCIA_BUFF_DIS 0x0020
-#define MQ_RESET        0x0040
-#define PCMCIA_RESET    0x0080
-#define DECT_POWER_ON   0x0100
-#define IRDA_SD         0x0200 // Shutdown for powersave
-#define RS232_ON        0x0400
-#define SD_MEDIAQ       0x0800 // Shutdown for powersave
-#define LED2_ON         0x1000
-#define IRDA_MODE       0x2000 // Fast/Slow IrDA mode
-#define ENABLE_5V       0x4000 // Enable 5V circuit
-#define RESET_SIMCARD   0x8000
-
-#define RS232_ENABLE    0x0440
-#define PCMCIAMASK      0x402f
-
-
+long simpad_get_cs3_ro(void);
+long simpad_get_cs3_shadow(void);
+void simpad_set_cs3_bit(int value);
+void simpad_clear_cs3_bit(int value);
+
+#define VCC_5V_EN	0x0001 /* For 5V PCMCIA */
+#define VCC_3V_EN	0x0002 /* FOR 3.3V PCMCIA */
+#define EN1		0x0004 /* This is only for EPROM's */
+#define EN0		0x0008 /* Both should be enable for 3.3V or 5V */
+#define DISPLAY_ON	0x0010
+#define PCMCIA_BUFF_DIS	0x0020
+#define MQ_RESET	0x0040
+#define PCMCIA_RESET	0x0080
+#define DECT_POWER_ON	0x0100
+#define IRDA_SD		0x0200 /* Shutdown for powersave */
+#define RS232_ON	0x0400
+#define SD_MEDIAQ	0x0800 /* Shutdown for powersave */
+#define LED2_ON		0x1000
+#define IRDA_MODE	0x2000 /* Fast/Slow IrDA mode */
+#define ENABLE_5V	0x4000 /* Enable 5V circuit */
+#define RESET_SIMCARD	0x8000
+
+#define PCMCIA_BVD1	0x01
+#define PCMCIA_BVD2	0x02
+#define PCMCIA_VS1	0x04
+#define PCMCIA_VS2	0x08
+#define LOCK_IND	0x10
+#define CHARGING_STATE	0x20
+#define PCMCIA_SHORT	0x40
+
+/*--- Battery ---*/
 struct simpad_battery {
 	unsigned char ac_status;	/* line connected yes/no */
 	unsigned char status;		/* battery loading yes/no */
diff --git a/arch/arm/mach-sa1100/leds-simpad.c b/arch/arm/mach-sa1100/leds-simpad.c
index d50f4ee..d25784c 100644
--- a/arch/arm/mach-sa1100/leds-simpad.c
+++ b/arch/arm/mach-sa1100/leds-simpad.c
@@ -22,9 +22,6 @@ static unsigned int hw_led_state;
 #define	LED_GREEN	(1)
 #define	LED_MASK	(1)
 
-extern void set_cs3_bit(int value);
-extern void clear_cs3_bit(int value);     
-
 void simpad_leds_event(led_event_t evt)
 {
 	switch (evt)
@@ -93,8 +90,8 @@ void simpad_leds_event(led_event_t evt)
 	}
 
 	if  (led_state & LED_STATE_ENABLED)
-		set_cs3_bit(LED2_ON);
+		simpad_set_cs3_bit(LED2_ON);
 	else 
-	        clear_cs3_bit(LED2_ON);
+		simpad_clear_cs3_bit(LED2_ON);
 }
 
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 718b802..ec6e381 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -13,6 +13,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -31,32 +32,85 @@
 
 #include "generic.h"
 
-long cs3_shadow;
+/*
+ * CS3 support
+ */
+
+static long cs3_shadow;
+static spinlock_t cs3_lock;
+static struct gpio_chip cs3_gpio;
+
+long simpad_get_cs3_ro(void)
+{
+	return readl(CS3_BASE);
+}
+EXPORT_SYMBOL(simpad_get_cs3_ro);
 
-long get_cs3_shadow(void)
+long simpad_get_cs3_shadow(void)
 {
 	return cs3_shadow;
 }
+EXPORT_SYMBOL(simpad_get_cs3_shadow);
 
-void set_cs3(long value)
+static void __simpad_write_cs3(void)
 {
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value;
+	writel(cs3_shadow, CS3_BASE);
 }
 
-void set_cs3_bit(int value)
+void simpad_set_cs3_bit(int value)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs3_lock, flags);
 	cs3_shadow |= value;
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+	__simpad_write_cs3();
+	spin_unlock_irqrestore(&cs3_lock, flags);
 }
+EXPORT_SYMBOL(simpad_set_cs3_bit);
 
-void clear_cs3_bit(int value)
+void simpad_clear_cs3_bit(int value)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&cs3_lock, flags);
 	cs3_shadow &= ~value;
-	*(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow;
+	__simpad_write_cs3();
+	spin_unlock_irqrestore(&cs3_lock, flags);
 }
+EXPORT_SYMBOL(simpad_clear_cs3_bit);
+
+static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (offset > 15)
+		return;
+	if (value)
+		simpad_set_cs3_bit(1 << offset);
+	else
+		simpad_clear_cs3_bit(1 << offset);
+};
 
-EXPORT_SYMBOL(set_cs3_bit);
-EXPORT_SYMBOL(clear_cs3_bit);
+static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 15)
+		return simpad_get_cs3_ro() & (1 << (offset - 16));
+	return simpad_get_cs3_shadow() & (1 << offset);
+};
+
+static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 15)
+		return 0;
+	return -EINVAL;
+};
+
+static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+	int value)
+{
+	if (offset > 15)
+		return -EINVAL;
+	cs3_gpio_set(chip, offset, value);
+	return 0;
+};
 
 static struct map_desc simpad_io_desc[] __initdata = {
 	{	/* MQ200 */
@@ -64,9 +118,9 @@ static struct map_desc simpad_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(0x4b800000),
 		.length		= 0x00800000,
 		.type		= MT_DEVICE
-	}, {	/* Paules CS3, write only */
-		.virtual	=  0xf1000000,
-		.pfn		= __phys_to_pfn(0x18000000),
+	}, {	/* Simpad CS3 */
+		.virtual	= CS3_BASE,
+		.pfn		= __phys_to_pfn(SA1100_CS3_PHYS),
 		.length		= 0x00100000,
 		.type		= MT_DEVICE
 	},
@@ -78,12 +132,12 @@ static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate)
 	if (port->mapbase == (u_int)&Ser1UTCR0) {
 		if (state)
 		{
-			clear_cs3_bit(RS232_ON);
-			clear_cs3_bit(DECT_POWER_ON);
+			simpad_clear_cs3_bit(RS232_ON);
+			simpad_clear_cs3_bit(DECT_POWER_ON);
 		}else
 		{
-			set_cs3_bit(RS232_ON);
-			set_cs3_bit(DECT_POWER_ON);
+			simpad_set_cs3_bit(RS232_ON);
+			simpad_set_cs3_bit(DECT_POWER_ON);
 		}
 	}
 }
@@ -143,9 +197,10 @@ static void __init simpad_map_io(void)
 
 	iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc));
 
-	set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON |
-		      ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
-
+	/* Initialize CS3 */
+	cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON |
+		RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON);
+	__simpad_write_cs3(); /* Spinlocks not yet initialized */
 
         sa1100_register_uart_fns(&simpad_port_fns);
 	sa1100_register_uart(0, 3);  /* serial interface */
@@ -171,12 +226,13 @@ static void __init simpad_map_io(void)
 
 static void simpad_power_off(void)
 {
-	local_irq_disable(); // was cli
-	set_cs3(0x800);        /* only SD_MEDIAQ */
+	local_irq_disable(); /* was cli */
+	cs3_shadow = SD_MEDIAQ;
+	__simpad_write_cs3(); /* Bypass spinlock here */
 
 	/* disable internal oscillator, float CS lines */
 	PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS);
-	/* enable wake-up on GPIO0 (Assabet...) */
+	/* enable wake-up on GPIO0 */
 	PWER = GFER = GRER = 1;
 	/*
 	 * set scratchpad to zero, just in case it is used as a
@@ -212,6 +268,19 @@ static int __init simpad_init(void)
 {
 	int ret;
 
+	spin_lock_init(&cs3_lock);
+
+	cs3_gpio.label = "simpad_cs3";
+	cs3_gpio.base = SIMPAD_CS3_GPIO_BASE;
+	cs3_gpio.ngpio = 24;
+	cs3_gpio.set = cs3_gpio_set;
+	cs3_gpio.get = cs3_gpio_get;
+	cs3_gpio.direction_input = cs3_gpio_direction_input;
+	cs3_gpio.direction_output = cs3_gpio_direction_output;
+	ret = gpiochip_add(&cs3_gpio);
+	if (ret)
+		printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device");
+
 	pm_power_off = simpad_power_off;
 
 	sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index c998f7a..540320d 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -15,10 +15,6 @@
 #include <mach/simpad.h>
 #include "sa1100_generic.h"
  
-extern long get_cs3_shadow(void);
-extern void set_cs3_bit(int value); 
-extern void clear_cs3_bit(int value);
-
 static struct pcmcia_irqs irqs[] = {
 	{ 1, IRQ_GPIO_CF_CD, "CF_CD" },
 };
@@ -26,7 +22,7 @@ static struct pcmcia_irqs irqs[] = {
 static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 
-	clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+	simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
 
 	skt->socket.pci_irq = IRQ_GPIO_CF_IRQ;
 
@@ -38,8 +34,8 @@ static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/* Disable CF bus: */
-	//set_cs3_bit(PCMCIA_BUFF_DIS);
-	clear_cs3_bit(PCMCIA_RESET);       
+	/*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
+	simpad_clear_cs3_bit(PCMCIA_RESET);
 }
 
 static void
@@ -47,15 +43,15 @@ simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			   struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
-	long cs3reg = get_cs3_shadow();
+	long cs3reg = simpad_get_cs3_shadow();
 
 	state->detect=((levels & GPIO_CF_CD)==0)?1:0;
 	state->ready=(levels & GPIO_CF_IRQ)?1:0;
 	state->bvd1=1; /* Not available on Simpad. */
 	state->bvd2=1; /* Not available on Simpad. */
 	state->wrprot=0; /* Not available on Simpad. */
-  
-	if((cs3reg & 0x0c) == 0x0c) {
+
+	if ((cs3reg & 0x0c) == 0x0c) {
 		state->vs_3v=0;
 		state->vs_Xv=0;
 	} else {
@@ -75,23 +71,23 @@ simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 	/* Murphy: see table of MIC2562a-1 */
 	switch (state->Vcc) {
 	case 0:
-		clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+		simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
 		break;
 
 	case 33:  
-		clear_cs3_bit(VCC_3V_EN|EN1);
-		set_cs3_bit(VCC_5V_EN|EN0);
+		simpad_clear_cs3_bit(VCC_3V_EN|EN1);
+		simpad_set_cs3_bit(VCC_5V_EN|EN0);
 		break;
 
 	case 50:
-		clear_cs3_bit(VCC_5V_EN|EN1);
-		set_cs3_bit(VCC_3V_EN|EN0);
+		simpad_clear_cs3_bit(VCC_5V_EN|EN1);
+		simpad_set_cs3_bit(VCC_3V_EN|EN0);
 		break;
 
 	default:
 		printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
 			__func__, state->Vcc);
-		clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
+		simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
 		local_irq_restore(flags);
 		return -1;
 	}
@@ -110,7 +106,7 @@ static void simpad_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
 	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
-	set_cs3_bit(PCMCIA_RESET);
+	simpad_set_cs3_bit(PCMCIA_RESET);
 }
 
 static struct pcmcia_low_level simpad_pcmcia_ops = { 
-- 
1.7.2.3

^ 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