* pull request for next
From: Kumar Gala @ 2009-11-13 13:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
The following changes since commit 0526484aa345adbf790d1201a6f5d09be0a648a3:
Benjamin Herrenschmidt (1):
Merge commit 'origin/master' into next
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git next
Anton Vorontsov (18):
powerpc/qe: Increase MAX_QE_RISC to 4
powerpc/qe: Add qe_upload_firmware() stub for non-QE builds
powerpc/qe: Make qe_reset() code path safe for repeated invocation
powerpc/qe: QE also shuts down on MPC8568
powerpc/cpm: Remove SPI defines and spi structs
powerpc/qe&cpm2: Avoid redefinitions in CPM2 and QE headers
powerpc/cpm: Move CPMFCR_* defines into cpm.h
powerpc/qe&cpm: Implement static inline stubs for non-QE/CPM builds
spi_mpc8xxx: Fix uninitialized variable
spi_mpc8xxx: Factor out SPI mode change steps into a call
spi_mpc8xxx: Turn qe_mode into flags
spi_mpc8xxx: Add support for QE DMA mode and CPM1/CPM2 chips
powerpc/qe: Implement QE driver for handling resume on MPC85xx
powerpc/85xx/86xx: Add suspend/resume support
powerpc/85xx: Add power management support for MPC85xxMDS boards
powerpc/86xx: Add power management support for MPC8610HPCD boards
powerpc/83xx: Add power management support for MPC83xx QE boards
powerpc/fsl: Make fsl_deep_sleep() usable w/ modules and non-83xx builds
Kumar Gala (3):
powerpc/85xx: Kconfig cleanup
powerpc/fsl-booke: Rework TLB CAM code
powerpc/fsl: Add PCI device ids for new QoirQ chips
Martyn Welch (3):
powerpc/86xx: Enable NVRAM on GE Fanuc's SBC610
powerpc/86xx: Support for NVRAM on GE Fanuc's SBC310
powerpc/86xx: Support for NVRAM on GE Fanuc's PPC9A
Poonam Aggrwal (2):
powerpc/85xx: Create dts for each core in CAMP mode for P2020RDB
powerpc/85xx: Added P1020RDB Platform support.
Documentation/powerpc/dts-bindings/fsl/board.txt | 4 +
arch/powerpc/Kconfig | 11 +-
arch/powerpc/boot/dts/gef_ppc9a.dts | 6 +
arch/powerpc/boot/dts/gef_sbc310.dts | 6 +
arch/powerpc/boot/dts/gef_sbc610.dts | 6 +
arch/powerpc/boot/dts/kmeter1.dts | 7 +
arch/powerpc/boot/dts/mpc832x_mds.dts | 9 +
arch/powerpc/boot/dts/mpc832x_rdb.dts | 9 +
arch/powerpc/boot/dts/mpc836x_mds.dts | 9 +
arch/powerpc/boot/dts/mpc836x_rdk.dts | 9 +
arch/powerpc/boot/dts/mpc8568mds.dts | 119 +++--
arch/powerpc/boot/dts/mpc8569mds.dts | 111 +++--
arch/powerpc/boot/dts/mpc8610_hpcd.dts | 26 +
arch/powerpc/boot/dts/p1020rdb.dts | 477 +++++++++++++++++
arch/powerpc/boot/dts/p2020rdb_camp_core0.dts | 363 +++++++++++++
arch/powerpc/boot/dts/p2020rdb_camp_core1.dts | 184 +++++++
arch/powerpc/configs/86xx/gef_ppc9a_defconfig | 2 +-
arch/powerpc/configs/86xx/gef_sbc310_defconfig | 2 +-
arch/powerpc/configs/86xx/gef_sbc610_defconfig | 4 +-
arch/powerpc/include/asm/cpm.h | 82 +++
arch/powerpc/include/asm/cpm1.h | 45 --
arch/powerpc/include/asm/cpm2.h | 47 --
arch/powerpc/include/asm/immap_cpm2.h | 2 +-
arch/powerpc/include/asm/immap_qe.h | 8 +-
arch/powerpc/include/asm/qe.h | 43 ++-
arch/powerpc/kernel/asm-offsets.c | 3 -
arch/powerpc/kernel/head_fsl_booke.S | 22 -
arch/powerpc/mm/fsl_booke_mmu.c | 132 +++--
arch/powerpc/mm/mmu_decl.h | 11 -
arch/powerpc/platforms/83xx/suspend.c | 1 +
arch/powerpc/platforms/85xx/Kconfig | 11 +-
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 1 +
arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 34 ++-
arch/powerpc/platforms/86xx/Kconfig | 3 +
arch/powerpc/platforms/86xx/gef_ppc9a.c | 5 +
arch/powerpc/platforms/86xx/gef_sbc310.c | 5 +
arch/powerpc/platforms/86xx/gef_sbc610.c | 5 +
arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 48 ++-
arch/powerpc/platforms/Kconfig | 2 +-
arch/powerpc/platforms/Kconfig.cputype | 17 +-
arch/powerpc/platforms/Makefile | 2 +-
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/cpm_common.c | 5 +-
arch/powerpc/sysdev/fsl_pci.c | 18 +-
arch/powerpc/sysdev/fsl_pmc.c | 88 +++
arch/powerpc/sysdev/fsl_soc.c | 2 +-
arch/powerpc/sysdev/qe_lib/qe.c | 61 ++-
drivers/spi/Kconfig | 3 -
drivers/spi/spi_mpc8xxx.c | 623 +++++++++++++++++++---
drivers/usb/gadget/fsl_qe_udc.h | 15 -
include/linux/fsl_devices.h | 6 +-
include/linux/pci_ids.h | 14 +
52 files changed, 2308 insertions(+), 421 deletions(-)
create mode 100644 arch/powerpc/boot/dts/p1020rdb.dts
create mode 100644 arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
create mode 100644 arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
create mode 100644 arch/powerpc/sysdev/fsl_pmc.c
^ permalink raw reply
* [PATCH v2 4/4] xilinx_spi: add a platform driver using the xilinx_spi common module.
From: Richard Röjfors @ 2009-11-13 12:29 UTC (permalink / raw)
To: spi-devel-general; +Cc: linuxppc-dev, Andrew Morton, dbrownell, John Linn
This patch adds in a platform device driver using the xilinx_spi common module.
Tested-by: John Linn <John.Linn@xilinx.com>
Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
---
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 35fb1e2..b0cfc98 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -253,6 +253,13 @@ config SPI_XILINX_OF
help
This is the OF driver for the SPI controller IP from the Xilinx EDK.
+config SPI_XILINX_PLTFM
+ tristate "Xilinx SPI controller platform device"
+ depends on SPI_XILINX
+ help
+ This is the platform driver for the SPI controller IP
+ from the Xilinx EDK.
+
#
# Add new SPI master controllers in alphabetical order above this line
#
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 97dee8f..d8b0e4c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o
+obj-$(CONFIG_SPI_XILINX_PLTFM) += xilinx_spi_pltfm.o
obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
# ... add above this line ...
diff --git a/drivers/spi/xilinx_spi_pltfm.c b/drivers/spi/xilinx_spi_pltfm.c
new file mode 100644
index 0000000..24debac
--- /dev/null
+++ b/drivers/spi/xilinx_spi_pltfm.c
@@ -0,0 +1,102 @@
+/*
+ * Support for Xilinx SPI platform devices
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Xilinx SPI devices as platform devices
+ *
+ * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/xilinx_spi.h>
+
+#include "xilinx_spi.h"
+
+static int __devinit xilinx_spi_probe(struct platform_device *dev)
+{
+ struct xspi_platform_data *pdata;
+ struct resource *r;
+ int irq;
+ struct spi_master *master;
+ u8 i;
+
+ pdata = dev->dev.platform_data;
+ if (!pdata)
+ return -ENODEV;
+
+ r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!r)
+ return -ENODEV;
+
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0)
+ return -ENXIO;
+
+ master = xilinx_spi_init(&dev->dev, r, irq, dev->id);
+ if (!master)
+ return -ENODEV;
+
+ for (i = 0; i < pdata->num_devices; i++)
+ spi_new_device(master, pdata->devices + i);
+
+ platform_set_drvdata(dev, master);
+ return 0;
+}
+
+static int __devexit xilinx_spi_remove(struct platform_device *dev)
+{
+ xilinx_spi_deinit(platform_get_drvdata(dev));
+ platform_set_drvdata(dev, 0);
+
+ return 0;
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:" XILINX_SPI_NAME);
+
+static struct platform_driver xilinx_spi_driver = {
+ .probe = xilinx_spi_probe,
+ .remove = __devexit_p(xilinx_spi_remove),
+ .driver = {
+ .name = XILINX_SPI_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init xilinx_spi_pltfm_init(void)
+{
+ return platform_driver_register(&xilinx_spi_driver);
+}
+module_init(xilinx_spi_pltfm_init);
+
+static void __exit xilinx_spi_pltfm_exit(void)
+{
+ platform_driver_unregister(&xilinx_spi_driver);
+}
+module_exit(xilinx_spi_pltfm_exit);
+
+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_DESCRIPTION("Xilinx SPI platform driver");
+MODULE_LICENSE("GPL v2");
^ permalink raw reply related
* [PATCH v3 3/4] xilinx_spi: add support for the DS570 IP.
From: Richard Röjfors @ 2009-11-13 12:28 UTC (permalink / raw)
To: spi-devel-general; +Cc: linuxppc-dev, Andrew Morton, dbrownell, John Linn
This patch adds in support for the DS570 IP.
It's register compatible with the DS464, but adds support for 8/16/32 SPI.
The 8/16/32 support is added by attaching callbacks reading/writing the
proper amount of data. To indicate to the driver which amount of bits
to use a new field is introduced in the platform data struct.
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: John Linn <John.Linn@xilinx.com>
Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
---
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 04ba35f..35fb1e2 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -235,7 +235,7 @@ config SPI_TXX9
SPI driver for Toshiba TXx9 MIPS SoCs
config SPI_XILINX
- tristate "Xilinx SPI controller"
+ tristate "Xilinx SPI controller common module"
depends on HAS_IOMEM && EXPERIMENTAL
select SPI_BITBANG
select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
@@ -245,6 +245,8 @@ config SPI_XILINX
See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
Product Specification document (DS464) for hardware details.
+ Or for the DS570, see "XPS Serial Peripheral Interface (SPI) (v2.00b)"
+
config SPI_XILINX_OF
tristate "Xilinx SPI controller OF device"
depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE)
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 74a04d6..bac51e8 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -27,7 +27,7 @@
/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
* Product Specification", DS464
*/
-#define XSPI_CR_OFFSET 0x60 /* 16-bit Control Register */
+#define XSPI_CR_OFFSET 0x60 /* Control Register */
#define XSPI_CR_ENABLE 0x02
#define XSPI_CR_MASTER_MODE 0x04
@@ -38,8 +38,9 @@
#define XSPI_CR_RXFIFO_RESET 0x40
#define XSPI_CR_MANUAL_SSELECT 0x80
#define XSPI_CR_TRANS_INHIBIT 0x100
+#define XSPI_CR_LSB_FIRST 0x200
-#define XSPI_SR_OFFSET 0x64 /* 8-bit Status Register */
+#define XSPI_SR_OFFSET 0x64 /* Status Register */
#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
@@ -47,8 +48,8 @@
#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
-#define XSPI_TXD_OFFSET 0x68 /* 8-bit Data Transmit Register */
-#define XSPI_RXD_OFFSET 0x6c /* 8-bit Data Receive Register */
+#define XSPI_TXD_OFFSET 0x68 /* Data Transmit Register */
+#define XSPI_RXD_OFFSET 0x6c /* Data Receive Register */
#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
@@ -68,6 +69,7 @@
#define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */
#define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */
#define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */
+#define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */
#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */
#define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
@@ -81,15 +83,61 @@ struct xilinx_spi {
u32 irq;
- u32 speed_hz; /* SCK has a fixed frequency of speed_hz Hz */
-
u8 *rx_ptr; /* pointer in the Tx buffer */
const u8 *tx_ptr; /* pointer in the Rx buffer */
int remaining_bytes; /* the number of bytes left to transfer */
+ u8 bits_per_word;
unsigned int (*read_fn) (void __iomem *);
void (*write_fn) (u32, void __iomem *);
+ void (*tx_fn) (struct xilinx_spi *);
+ void (*rx_fn) (struct xilinx_spi *);
};
+static void xspi_tx8(struct xilinx_spi *xspi)
+{
+ xspi->write_fn(*xspi->tx_ptr, xspi->regs + XSPI_TXD_OFFSET);
+ xspi->tx_ptr++;
+}
+
+static void xspi_tx16(struct xilinx_spi *xspi)
+{
+ xspi->write_fn(*(u16 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
+ xspi->tx_ptr += 2;
+}
+
+static void xspi_tx32(struct xilinx_spi *xspi)
+{
+ xspi->write_fn(*(u32 *)(xspi->tx_ptr), xspi->regs + XSPI_TXD_OFFSET);
+ xspi->tx_ptr += 4;
+}
+
+static void xspi_rx8(struct xilinx_spi *xspi)
+{
+ u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
+ if (xspi->rx_ptr) {
+ *xspi->rx_ptr = data & 0xff;
+ xspi->rx_ptr++;
+ }
+}
+
+static void xspi_rx16(struct xilinx_spi *xspi)
+{
+ u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
+ if (xspi->rx_ptr) {
+ *(u16 *)(xspi->rx_ptr) = data & 0xffff;
+ xspi->rx_ptr += 2;
+ }
+}
+
+static void xspi_rx32(struct xilinx_spi *xspi)
+{
+ u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
+ if (xspi->rx_ptr) {
+ *(u32 *)(xspi->rx_ptr) = data;
+ xspi->rx_ptr += 4;
+ }
+}
+
static void xspi_init_hw(struct xilinx_spi *xspi)
{
void __iomem *regs_base = xspi->regs;
@@ -107,8 +155,8 @@ static void xspi_init_hw(struct xilinx_spi *xspi)
/* Disable the transmitter, enable Manual Slave Select Assertion,
* put SPI controller into master mode, and enable it */
xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
- XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE,
- regs_base + XSPI_CR_OFFSET);
+ XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET |
+ XSPI_CR_RXFIFO_RESET, regs_base + XSPI_CR_OFFSET);
}
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
@@ -141,17 +189,20 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
/* spi_bitbang requires custom setup_transfer() to be defined if there is a
* custom txrx_bufs(). We have nothing to setup here as the SPI IP block
- * supports just 8 bits per word, and SPI clock can't be changed in software.
- * Check for 8 bits per word. Chip select delay calculations could be
+ * supports 8 or 16 bits per word, which can not be changed in software.
+ * SPI clock can't be changed in software.
+ * Check for correct bits per word. Chip select delay calculations could be
* added here as soon as bitbang_work() can be made aware of the delay value.
*/
static int xilinx_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
+ struct spi_transfer *t)
{
u8 bits_per_word;
+ struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
- bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
- if (bits_per_word != 8) {
+ bits_per_word = (t->bits_per_word) ? t->bits_per_word :
+ spi->bits_per_word;
+ if (bits_per_word != xspi->bits_per_word) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, bits_per_word);
return -EINVAL;
@@ -162,17 +213,16 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
static int xilinx_spi_setup(struct spi_device *spi)
{
- struct spi_bitbang *bitbang;
- struct xilinx_spi *xspi;
- int retval;
-
- xspi = spi_master_get_devdata(spi->master);
- bitbang = &xspi->bitbang;
-
- retval = xilinx_spi_setup_transfer(spi, NULL);
- if (retval < 0)
- return retval;
-
+ /* always return 0, we can not check the number of bits.
+ * There are cases when SPI setup is called before any driver is
+ * there, in that case the SPI core defaults to 8 bits, which we
+ * do not support in some cases. But if we return an error, the
+ * SPI device would not be registered and no driver can get hold of it
+ * When the driver is there, it will call SPI setup again with the
+ * correct number of bits per transfer.
+ * If a driver setups with the wrong bit number, it will fail when
+ * it tries to do a transfer
+ */
return 0;
}
@@ -184,11 +234,10 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
if (xspi->tx_ptr)
- xspi->write_fn(*xspi->tx_ptr++,
- xspi->regs + XSPI_TXD_OFFSET);
+ xspi->tx_fn(xspi);
else
xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
- xspi->remaining_bytes--;
+ xspi->remaining_bytes -= xspi->bits_per_word / 8;
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
}
}
@@ -259,12 +308,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
/* Read out all the data from the Rx FIFO */
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
- u8 data;
-
- data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
- if (xspi->rx_ptr) {
- *xspi->rx_ptr++ = data;
- }
+ xspi->rx_fn(xspi);
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
}
@@ -336,6 +380,19 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
xspi->read_fn = ioread32be;
xspi->write_fn = iowrite32be;
}
+ xspi->bits_per_word = pdata->bits_per_word;
+ if (xspi->bits_per_word == 8) {
+ xspi->tx_fn = xspi_tx8;
+ xspi->rx_fn = xspi_rx8;
+ } else if (xspi->bits_per_word == 16) {
+ xspi->tx_fn = xspi_tx16;
+ xspi->rx_fn = xspi_rx16;
+ } else if (xspi->bits_per_word == 32) {
+ xspi->tx_fn = xspi_tx32;
+ xspi->rx_fn = xspi_rx32;
+ } else
+ goto unmap_io;
+
/* SPI controller initializations */
xspi_init_hw(xspi);
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c
index 151aa13..71dc3ad 100644
--- a/drivers/spi/xilinx_spi_of.c
+++ b/drivers/spi/xilinx_spi_of.c
@@ -72,6 +72,7 @@ static int __devinit xilinx_spi_of_probe(struct of_device *ofdev,
return -EINVAL;
}
pdata->num_chipselect = *prop;
+ pdata->bits_per_word = 8;
master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1);
if (!master)
return -ENODEV;
diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h
index a705ad8..6f17278 100644
--- a/include/linux/spi/xilinx_spi.h
+++ b/include/linux/spi/xilinx_spi.h
@@ -3,14 +3,16 @@
/**
* struct xspi_platform_data - Platform data of the Xilinx SPI driver
- * @num_chipselect: Number of chip select by the IP
- * @little_endian If registers should be accessed little endian or not
+ * @num_chipselect: Number of chip select by the IP.
+ * @little_endian: If registers should be accessed little endian or not.
+ * @bits_per_word: Number of bits per word.
* @devices: Devices to add when the driver is probed.
* @num_devices: Number of devices in the devices array.
*/
struct xspi_platform_data {
u16 num_chipselect;
bool little_endian;
+ u8 bits_per_word;
struct spi_board_info *devices;
u8 num_devices;
};
^ permalink raw reply related
* [PATCH v3 2/4] xilinx_spi: Switch to iomem functions and support little endian.
From: Richard Röjfors @ 2009-11-13 12:28 UTC (permalink / raw)
To: spi-devel-general; +Cc: linuxppc-dev, Andrew Morton, dbrownell, John Linn
This patch changes the out_(be)(8|16|32) and in_(be)(8|16|32) calls to 32 bits ioread/iowrite.
The read and write function are attached to the internal struct as callbacks, callback
is selected depending on endianess.
This will also build on platforms not supporting the in/out calls for instance x86.
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Tested-by: John Linn <John.Linn@xilinx.com>
Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
---
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index c08fd4f..04ba35f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -236,7 +236,7 @@ config SPI_TXX9
config SPI_XILINX
tristate "Xilinx SPI controller"
- depends on EXPERIMENTAL
+ depends on HAS_IOMEM && EXPERIMENTAL
select SPI_BITBANG
select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
help
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index fa53d85..74a04d6 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -27,7 +27,7 @@
/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
* Product Specification", DS464
*/
-#define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */
+#define XSPI_CR_OFFSET 0x60 /* 16-bit Control Register */
#define XSPI_CR_ENABLE 0x02
#define XSPI_CR_MASTER_MODE 0x04
@@ -39,7 +39,7 @@
#define XSPI_CR_MANUAL_SSELECT 0x80
#define XSPI_CR_TRANS_INHIBIT 0x100
-#define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */
+#define XSPI_SR_OFFSET 0x64 /* 8-bit Status Register */
#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
@@ -47,8 +47,8 @@
#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
-#define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */
-#define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */
+#define XSPI_TXD_OFFSET 0x68 /* 8-bit Data Transmit Register */
+#define XSPI_RXD_OFFSET 0x6c /* 8-bit Data Receive Register */
#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
@@ -86,25 +86,29 @@ struct xilinx_spi {
u8 *rx_ptr; /* pointer in the Tx buffer */
const u8 *tx_ptr; /* pointer in the Rx buffer */
int remaining_bytes; /* the number of bytes left to transfer */
+ unsigned int (*read_fn) (void __iomem *);
+ void (*write_fn) (u32, void __iomem *);
};
-static void xspi_init_hw(void __iomem *regs_base)
+static void xspi_init_hw(struct xilinx_spi *xspi)
{
+ void __iomem *regs_base = xspi->regs;
+
/* Reset the SPI device */
- out_be32(regs_base + XIPIF_V123B_RESETR_OFFSET,
- XIPIF_V123B_RESET_MASK);
+ xspi->write_fn(XIPIF_V123B_RESET_MASK,
+ regs_base + XIPIF_V123B_RESETR_OFFSET);
/* Disable all the interrupts just in case */
- out_be32(regs_base + XIPIF_V123B_IIER_OFFSET, 0);
+ xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET);
/* Enable the global IPIF interrupt */
- out_be32(regs_base + XIPIF_V123B_DGIER_OFFSET,
- XIPIF_V123B_GINTR_ENABLE);
+ xspi->write_fn(XIPIF_V123B_GINTR_ENABLE,
+ regs_base + XIPIF_V123B_DGIER_OFFSET);
/* Deselect the slave on the SPI bus */
- out_be32(regs_base + XSPI_SSR_OFFSET, 0xffff);
+ xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET);
/* Disable the transmitter, enable Manual Slave Select Assertion,
* put SPI controller into master mode, and enable it */
- out_be16(regs_base + XSPI_CR_OFFSET,
- XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT
- | XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE);
+ xspi->write_fn(XSPI_CR_TRANS_INHIBIT | XSPI_CR_MANUAL_SSELECT |
+ XSPI_CR_MASTER_MODE | XSPI_CR_ENABLE,
+ regs_base + XSPI_CR_OFFSET);
}
static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
@@ -113,16 +117,16 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
if (is_on == BITBANG_CS_INACTIVE) {
/* Deselect the slave on the SPI bus */
- out_be32(xspi->regs + XSPI_SSR_OFFSET, 0xffff);
+ xspi->write_fn(0xffff, xspi->regs + XSPI_SSR_OFFSET);
} else if (is_on == BITBANG_CS_ACTIVE) {
/* Set the SPI clock phase and polarity */
- u16 cr = in_be16(xspi->regs + XSPI_CR_OFFSET)
+ u16 cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET)
& ~XSPI_CR_MODE_MASK;
if (spi->mode & SPI_CPHA)
cr |= XSPI_CR_CPHA;
if (spi->mode & SPI_CPOL)
cr |= XSPI_CR_CPOL;
- out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+ xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
/* We do not check spi->max_speed_hz here as the SPI clock
* frequency is not software programmable (the IP block design
@@ -130,8 +134,8 @@ static void xilinx_spi_chipselect(struct spi_device *spi, int is_on)
*/
/* Activate the chip select */
- out_be32(xspi->regs + XSPI_SSR_OFFSET,
- ~(0x0001 << spi->chip_select));
+ xspi->write_fn(~(0x0001 << spi->chip_select),
+ xspi->regs + XSPI_SSR_OFFSET);
}
}
@@ -177,15 +181,15 @@ static void xilinx_spi_fill_tx_fifo(struct xilinx_spi *xspi)
u8 sr;
/* Fill the Tx FIFO with as many bytes as possible */
- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
while ((sr & XSPI_SR_TX_FULL_MASK) == 0 && xspi->remaining_bytes > 0) {
- if (xspi->tx_ptr) {
- out_8(xspi->regs + XSPI_TXD_OFFSET, *xspi->tx_ptr++);
- } else {
- out_8(xspi->regs + XSPI_TXD_OFFSET, 0);
- }
+ if (xspi->tx_ptr)
+ xspi->write_fn(*xspi->tx_ptr++,
+ xspi->regs + XSPI_TXD_OFFSET);
+ else
+ xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET);
xspi->remaining_bytes--;
- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
}
}
@@ -207,18 +211,19 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
/* Enable the transmit empty interrupt, which we use to determine
* progress on the transmission.
*/
- ipif_ier = in_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET);
- out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET,
- ipif_ier | XSPI_INTR_TX_EMPTY);
+ ipif_ier = xspi->read_fn(xspi->regs + XIPIF_V123B_IIER_OFFSET);
+ xspi->write_fn(ipif_ier | XSPI_INTR_TX_EMPTY,
+ xspi->regs + XIPIF_V123B_IIER_OFFSET);
/* Start the transfer by not inhibiting the transmitter any longer */
- cr = in_be16(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_TRANS_INHIBIT;
- out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) &
+ ~XSPI_CR_TRANS_INHIBIT;
+ xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
wait_for_completion(&xspi->done);
/* Disable the transmit empty interrupt */
- out_be32(xspi->regs + XIPIF_V123B_IIER_OFFSET, ipif_ier);
+ xspi->write_fn(ipif_ier, xspi->regs + XIPIF_V123B_IIER_OFFSET);
return t->len - xspi->remaining_bytes;
}
@@ -235,8 +240,8 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
u32 ipif_isr;
/* Get the IPIF interrupts, and clear them immediately */
- ipif_isr = in_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET);
- out_be32(xspi->regs + XIPIF_V123B_IISR_OFFSET, ipif_isr);
+ ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET);
+ xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET);
if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */
u16 cr;
@@ -247,20 +252,20 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
* transmitter while the Isr refills the transmit register/FIFO,
* or make sure it is stopped if we're done.
*/
- cr = in_be16(xspi->regs + XSPI_CR_OFFSET);
- out_be16(xspi->regs + XSPI_CR_OFFSET,
- cr | XSPI_CR_TRANS_INHIBIT);
+ cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET);
+ xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
+ xspi->regs + XSPI_CR_OFFSET);
/* Read out all the data from the Rx FIFO */
- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
while ((sr & XSPI_SR_RX_EMPTY_MASK) == 0) {
u8 data;
- data = in_8(xspi->regs + XSPI_RXD_OFFSET);
+ data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET);
if (xspi->rx_ptr) {
*xspi->rx_ptr++ = data;
}
- sr = in_8(xspi->regs + XSPI_SR_OFFSET);
+ sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
}
/* See if there is more data to send */
@@ -269,7 +274,7 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
/* Start the transfer by not inhibiting the
* transmitter any longer
*/
- out_be16(xspi->regs + XSPI_CR_OFFSET, cr);
+ xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
} else {
/* No more data to send.
* Indicate the transfer is completed.
@@ -324,9 +329,16 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
xspi->mem = *mem;
xspi->irq = irq;
+ if (pdata->little_endian) {
+ xspi->read_fn = ioread32;
+ xspi->write_fn = iowrite32;
+ } else {
+ xspi->read_fn = ioread32be;
+ xspi->write_fn = iowrite32be;
+ }
/* SPI controller initializations */
- xspi_init_hw(xspi->regs);
+ xspi_init_hw(xspi);
/* Register for SPI Interrupt */
ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h
index 06df0ab..a705ad8 100644
--- a/include/linux/spi/xilinx_spi.h
+++ b/include/linux/spi/xilinx_spi.h
@@ -4,11 +4,13 @@
/**
* struct xspi_platform_data - Platform data of the Xilinx SPI driver
* @num_chipselect: Number of chip select by the IP
+ * @little_endian If registers should be accessed little endian or not
* @devices: Devices to add when the driver is probed.
* @num_devices: Number of devices in the devices array.
*/
struct xspi_platform_data {
u16 num_chipselect;
+ bool little_endian;
struct spi_board_info *devices;
u8 num_devices;
};
^ permalink raw reply related
* [PATCH v3 1/4] xilinx_spi: Split into of driver and generic part.
From: Richard Röjfors @ 2009-11-13 12:28 UTC (permalink / raw)
To: spi-devel-general; +Cc: linuxppc-dev, Andrew Morton, dbrownell, John Linn
This patch splits the xilinx_spi driver into a generic part and a
OF driver part.
The reason for this is to later add in a platform driver as well.
Tested-by: John Linn <John.Linn@xilinx.com>
Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
---
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4b6f7cb..c08fd4f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -236,14 +236,21 @@ config SPI_TXX9
config SPI_XILINX
tristate "Xilinx SPI controller"
- depends on (XILINX_VIRTEX || MICROBLAZE) && EXPERIMENTAL
+ depends on EXPERIMENTAL
select SPI_BITBANG
+ select SPI_XILINX_OF if (XILINX_VIRTEX || MICROBLAZE)
help
This exposes the SPI controller IP from the Xilinx EDK.
See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
Product Specification document (DS464) for hardware details.
+config SPI_XILINX_OF
+ tristate "Xilinx SPI controller OF device"
+ depends on SPI_XILINX && (XILINX_VIRTEX || MICROBLAZE)
+ help
+ This is the OF driver for the SPI controller IP from the Xilinx EDK.
+
#
# Add new SPI master controllers in alphabetical order above this line
#
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 21a1182..97dee8f 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
+obj-$(CONFIG_SPI_XILINX_OF) += xilinx_spi_of.o
obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
# ... add above this line ...
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 46b8c5c..fa53d85 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -14,16 +14,14 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
-#include <linux/of_spi.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/io.h>
+#include "xilinx_spi.h"
+#include <linux/spi/xilinx_spi.h>
+
#define XILINX_SPI_NAME "xilinx_spi"
/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
@@ -78,7 +76,7 @@ struct xilinx_spi {
/* bitbang has to be first */
struct spi_bitbang bitbang;
struct completion done;
-
+ struct resource mem; /* phys mem */
void __iomem *regs; /* virt. address of the control registers */
u32 irq;
@@ -283,40 +281,22 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __init xilinx_spi_of_probe(struct of_device *ofdev,
- const struct of_device_id *match)
+struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
+ u32 irq, s16 bus_num)
{
struct spi_master *master;
struct xilinx_spi *xspi;
- struct resource r_irq_struct;
- struct resource r_mem_struct;
-
- struct resource *r_irq = &r_irq_struct;
- struct resource *r_mem = &r_mem_struct;
- int rc = 0;
- const u32 *prop;
- int len;
-
- /* Get resources(memory, IRQ) associated with the device */
- master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));
+ struct xspi_platform_data *pdata = dev->platform_data;
+ int ret;
- if (master == NULL) {
- return -ENOMEM;
- }
-
- dev_set_drvdata(&ofdev->dev, master);
-
- rc = of_address_to_resource(ofdev->node, 0, r_mem);
- if (rc) {
- dev_warn(&ofdev->dev, "invalid address\n");
- goto put_master;
+ if (!pdata) {
+ dev_err(dev, "No platform data attached\n");
+ return NULL;
}
- rc = of_irq_to_resource(ofdev->node, 0, r_irq);
- if (rc == NO_IRQ) {
- dev_warn(&ofdev->dev, "no IRQ found\n");
- goto put_master;
- }
+ master = spi_alloc_master(dev, sizeof(struct xilinx_spi));
+ if (!master)
+ return NULL;
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA;
@@ -329,128 +309,67 @@ static int __init xilinx_spi_of_probe(struct of_device *ofdev,
xspi->bitbang.master->setup = xilinx_spi_setup;
init_completion(&xspi->done);
- xspi->irq = r_irq->start;
-
- if (!request_mem_region(r_mem->start,
- r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
- rc = -ENXIO;
- dev_warn(&ofdev->dev, "memory request failure\n");
+ if (!request_mem_region(mem->start, resource_size(mem),
+ XILINX_SPI_NAME))
goto put_master;
- }
- xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1);
+ xspi->regs = ioremap(mem->start, resource_size(mem));
if (xspi->regs == NULL) {
- rc = -ENOMEM;
- dev_warn(&ofdev->dev, "ioremap failure\n");
- goto release_mem;
+ dev_warn(dev, "ioremap failure\n");
+ goto map_failed;
}
- xspi->irq = r_irq->start;
- /* dynamic bus assignment */
- master->bus_num = -1;
+ master->bus_num = bus_num;
+ master->num_chipselect = pdata->num_chipselect;
- /* number of slave select bits is required */
- prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
- if (!prop || len < sizeof(*prop)) {
- dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
- goto unmap_io;
- }
- master->num_chipselect = *prop;
+ xspi->mem = *mem;
+ xspi->irq = irq;
/* SPI controller initializations */
xspi_init_hw(xspi->regs);
/* Register for SPI Interrupt */
- rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
- if (rc != 0) {
- dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
+ ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+ if (ret)
goto unmap_io;
- }
- rc = spi_bitbang_start(&xspi->bitbang);
- if (rc != 0) {
- dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n");
+ ret = spi_bitbang_start(&xspi->bitbang);
+ if (ret) {
+ dev_err(dev, "spi_bitbang_start FAILED\n");
goto free_irq;
}
- dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
- (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq);
-
- /* Add any subnodes on the SPI bus */
- of_register_spi_devices(master, ofdev->node);
-
- return rc;
+ dev_info(dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+ (u32)mem->start, (u32)xspi->regs, xspi->irq);
+ return master;
free_irq:
free_irq(xspi->irq, xspi);
unmap_io:
iounmap(xspi->regs);
-release_mem:
- release_mem_region(r_mem->start, resource_size(r_mem));
+map_failed:
+ release_mem_region(mem->start, resource_size(mem));
put_master:
spi_master_put(master);
- return rc;
+ return NULL;
}
+EXPORT_SYMBOL(xilinx_spi_init);
-static int __devexit xilinx_spi_remove(struct of_device *ofdev)
+void xilinx_spi_deinit(struct spi_master *master)
{
struct xilinx_spi *xspi;
- struct spi_master *master;
- struct resource r_mem;
- master = platform_get_drvdata(ofdev);
xspi = spi_master_get_devdata(master);
spi_bitbang_stop(&xspi->bitbang);
free_irq(xspi->irq, xspi);
iounmap(xspi->regs);
- if (!of_address_to_resource(ofdev->node, 0, &r_mem))
- release_mem_region(r_mem.start, resource_size(&r_mem));
- dev_set_drvdata(&ofdev->dev, 0);
- spi_master_put(xspi->bitbang.master);
-
- return 0;
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:" XILINX_SPI_NAME);
-
-static int __exit xilinx_spi_of_remove(struct of_device *op)
-{
- return xilinx_spi_remove(op);
-}
-static struct of_device_id xilinx_spi_of_match[] = {
- { .compatible = "xlnx,xps-spi-2.00.a", },
- { .compatible = "xlnx,xps-spi-2.00.b", },
- {}
-};
-
-MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-
-static struct of_platform_driver xilinx_spi_of_driver = {
- .owner = THIS_MODULE,
- .name = "xilinx-xps-spi",
- .match_table = xilinx_spi_of_match,
- .probe = xilinx_spi_of_probe,
- .remove = __exit_p(xilinx_spi_of_remove),
- .driver = {
- .name = "xilinx-xps-spi",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init xilinx_spi_init(void)
-{
- return of_register_platform_driver(&xilinx_spi_of_driver);
+ release_mem_region(xspi->mem.start, resource_size(&xspi->mem));
+ spi_master_put(xspi->bitbang.master);
}
-module_init(xilinx_spi_init);
+EXPORT_SYMBOL(xilinx_spi_deinit);
-static void __exit xilinx_spi_exit(void)
-{
- of_unregister_platform_driver(&xilinx_spi_of_driver);
-}
-module_exit(xilinx_spi_exit);
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx SPI driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h
new file mode 100644
index 0000000..d211acc
--- /dev/null
+++ b/drivers/spi/xilinx_spi.h
@@ -0,0 +1,32 @@
+/*
+ * Xilinx SPI device driver API and platform data header file
+ *
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _XILINX_SPI_H_
+#define _XILINX_SPI_H_
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#define XILINX_SPI_NAME "xilinx_spi"
+
+struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
+ u32 irq, s16 bus_num);
+
+void xilinx_spi_deinit(struct spi_master *master);
+#endif
diff --git a/drivers/spi/xilinx_spi_of.c b/drivers/spi/xilinx_spi_of.c
new file mode 100644
index 0000000..151aa13
--- /dev/null
+++ b/drivers/spi/xilinx_spi_of.c
@@ -0,0 +1,133 @@
+/*
+ * Xilinx SPI OF device driver
+ *
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Supports:
+ * Xilinx SPI devices as OF devices
+ *
+ * Inspired by xilinx_spi.c, 2002-2007 (c) MontaVista Software, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_spi.h>
+
+#include <linux/spi/xilinx_spi.h>
+#include "xilinx_spi.h"
+
+
+static int __devinit xilinx_spi_of_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct spi_master *master;
+ struct xspi_platform_data *pdata;
+ struct resource r_mem;
+ struct resource r_irq;
+ int rc = 0;
+ const u32 *prop;
+ int len;
+
+ rc = of_address_to_resource(ofdev->node, 0, &r_mem);
+ if (rc) {
+ dev_warn(&ofdev->dev, "invalid address\n");
+ return rc;
+ }
+
+ rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
+ if (rc == NO_IRQ) {
+ dev_warn(&ofdev->dev, "no IRQ found\n");
+ return -ENODEV;
+ }
+
+ ofdev->dev.platform_data =
+ kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL);
+ pdata = ofdev->dev.platform_data;
+ if (!pdata)
+ return -ENOMEM;
+
+ /* number of slave select bits is required */
+ prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
+ return -EINVAL;
+ }
+ pdata->num_chipselect = *prop;
+ master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1);
+ if (!master)
+ return -ENODEV;
+
+ dev_set_drvdata(&ofdev->dev, master);
+
+ /* Add any subnodes on the SPI bus */
+ of_register_spi_devices(master, ofdev->node);
+
+ return 0;
+}
+
+static int __devexit xilinx_spi_remove(struct of_device *ofdev)
+{
+ xilinx_spi_deinit(dev_get_drvdata(&ofdev->dev));
+ dev_set_drvdata(&ofdev->dev, 0);
+ kfree(ofdev->dev.platform_data);
+ ofdev->dev.platform_data = NULL;
+ return 0;
+}
+
+static int __exit xilinx_spi_of_remove(struct of_device *op)
+{
+ return xilinx_spi_remove(op);
+}
+
+static struct of_device_id xilinx_spi_of_match[] = {
+ { .compatible = "xlnx,xps-spi-2.00.a", },
+ { .compatible = "xlnx,xps-spi-2.00.b", },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+
+static struct of_platform_driver xilinx_spi_of_driver = {
+ .match_table = xilinx_spi_of_match,
+ .probe = xilinx_spi_of_probe,
+ .remove = __exit_p(xilinx_spi_of_remove),
+ .driver = {
+ .name = "xilinx-xps-spi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init xilinx_spi_of_init(void)
+{
+ return of_register_platform_driver(&xilinx_spi_of_driver);
+}
+module_init(xilinx_spi_of_init);
+
+static void __exit xilinx_spi_of_exit(void)
+{
+ of_unregister_platform_driver(&xilinx_spi_of_driver);
+}
+module_exit(xilinx_spi_of_exit);
+
+MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
+MODULE_DESCRIPTION("Xilinx SPI platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/spi/xilinx_spi.h b/include/linux/spi/xilinx_spi.h
new file mode 100644
index 0000000..06df0ab
--- /dev/null
+++ b/include/linux/spi/xilinx_spi.h
@@ -0,0 +1,16 @@
+#ifndef __LINUX_SPI_XILINX_SPI_H
+#define __LINUX_SPI_XILINX_SPI_H
+
+/**
+ * struct xspi_platform_data - Platform data of the Xilinx SPI driver
+ * @num_chipselect: Number of chip select by the IP
+ * @devices: Devices to add when the driver is probed.
+ * @num_devices: Number of devices in the devices array.
+ */
+struct xspi_platform_data {
+ u16 num_chipselect;
+ struct spi_board_info *devices;
+ u8 num_devices;
+};
+
+#endif /* __LINUX_SPI_XILINX_SPI_H */
^ permalink raw reply related
* [PATCH v3 0/4] xilinx_spi: Split into platform and of driver, support new IP, platform independence.
From: Richard Röjfors @ 2009-11-13 12:28 UTC (permalink / raw)
To: spi-devel-general; +Cc: linuxppc-dev, Andrew Morton, dbrownell, John Linn
Hi,
To follow is a series of patches against the xilinx_spi driver.
The patchset is against 2.6.32-rc6
The patchset addresses several problems in the current driver:
* It's PPC only (OF and uses PPC specific memory operations)
* Only supporting big endian writes
* Supports only 8bit SPI, support for DS570 (also 16 or 32 bit) is added.
* A platform driver is introduced for non OF capable architectures.
These patches were posted as one big patch up to 4 iterations, not splitted into 4.
This version, 3, is updated after review from Grant Likely and John Linn
John Linn has also tested the code on PPC, I have only tested on X86.
--Richard
^ permalink raw reply
* Re: [PATCH 3/3] [V2] mpc52xx_spi: add gpio chipselect
From: Wolfram Sang @ 2009-11-13 11:10 UTC (permalink / raw)
To: Luotao Fu; +Cc: spi-devel-general, David Brownell, linux-kernel, linuxppc-dev
In-Reply-To: <1258108877-25435-4-git-send-email-l.fu@pengutronix.de>
[-- Attachment #1: Type: text/plain, Size: 5437 bytes --]
On Fri, Nov 13, 2009 at 11:41:17AM +0100, Luotao Fu wrote:
> This one enables the mpc52xx_spi driver for usage of user defined gpio lines
> as chipselect. This way we can control some more spi devices than only one
>
> V2 Changes:
> * preinitialize the gpio as output in probe function and call gpio_set_value in
> the chip select function instead of calling direction_output every time.
> * initialize the gpio line with output high, since we don't support CS_HIGH
> in the driver currently any way. change gpio value setting to default active
> low in chip select call.
> * free the gpio array while error or removing.
>
> Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Just the kfree-comment, otherwise:
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
> drivers/spi/mpc52xx_spi.c | 64 ++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 60 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
> index 64862cf..97beba2 100644
> --- a/drivers/spi/mpc52xx_spi.c
> +++ b/drivers/spi/mpc52xx_spi.c
> @@ -21,6 +21,7 @@
> #include <linux/spi/mpc52xx_spi.h>
> #include <linux/of_spi.h>
> #include <linux/io.h>
> +#include <linux/of_gpio.h>
> #include <asm/time.h>
> #include <asm/mpc52xx.h>
>
> @@ -79,7 +80,6 @@ struct mpc52xx_spi {
> spinlock_t lock;
> struct work_struct work;
>
> -
> /* Details of current transfer (length, and buffer pointers) */
> struct spi_message *message; /* current message */
> struct spi_transfer *transfer; /* current transfer */
> @@ -89,6 +89,8 @@ struct mpc52xx_spi {
> u8 *rx_buf;
> const u8 *tx_buf;
> int cs_change;
> + int gpio_cs_count;
> + unsigned int *gpio_cs;
> };
>
> /*
> @@ -96,7 +98,13 @@ struct mpc52xx_spi {
> */
> static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
> {
> - out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
> + int cs;
> +
> + if (ms->gpio_cs_count > 0) {
> + cs = ms->message->spi->chip_select;
> + gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1);
> + } else
> + out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
> }
>
> /*
> @@ -390,8 +398,9 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
> struct spi_master *master;
> struct mpc52xx_spi *ms;
> void __iomem *regs;
> - int rc;
> u8 ctrl1;
> + int rc, i = 0;
> + int gpio_cs;
>
> /* MMIO registers */
> dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
> @@ -426,8 +435,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
> rc = -ENOMEM;
> goto err_alloc;
> }
> +
> master->bus_num = -1;
> - master->num_chipselect = 1;
> master->setup = mpc52xx_spi_setup;
> master->transfer = mpc52xx_spi_transfer;
> master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
> @@ -441,6 +450,40 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
> ms->irq1 = irq_of_parse_and_map(op->node, 1);
> ms->state = mpc52xx_spi_fsmstate_idle;
> ms->ipb_freq = mpc5xxx_get_bus_frequency(op->node);
> + ms->gpio_cs_count = of_gpio_count(op->node);
> + if (ms->gpio_cs_count > 0) {
> + master->num_chipselect = ms->gpio_cs_count;
> + ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int),
> + GFP_KERNEL);
> + if (!ms->gpio_cs) {
> + rc = -ENOMEM;
> + goto err_alloc;
> + }
> +
> + for (i = 0; i < ms->gpio_cs_count; i++) {
> + gpio_cs = of_get_gpio(op->node, i);
> + if (gpio_cs < 0) {
> + dev_err(&op->dev,
> + "could not parse the gpio field "
> + "in oftree\n");
> + rc = -ENODEV;
> + goto err_gpio;
> + }
> +
> + rc = gpio_request(gpio_cs, dev_name(&op->dev));
> + if (rc) {
> + dev_err(&op->dev,
> + "can't request spi cs gpio #%d "
> + "on gpio line %d\n", i, gpio_cs);
> + goto err_gpio;
> + }
> +
> + gpio_direction_output(gpio_cs, 1);
> + ms->gpio_cs[i] = gpio_cs;
> + }
> + } else
> + master->num_chipselect = 1;
> +
> spin_lock_init(&ms->lock);
> INIT_LIST_HEAD(&ms->queue);
> INIT_WORK(&ms->work, mpc52xx_spi_wq);
> @@ -477,6 +520,12 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
> err_register:
> dev_err(&ms->master->dev, "initialization failed\n");
> spi_master_put(master);
> + err_gpio:
> + while (i-- > 0)
> + gpio_free(ms->gpio_cs[i]);
> +
> + if (ms->gpio_cs != NULL)
> + kfree(ms->gpio_cs);
kfree() is NULL aware, so no if needed.
> err_alloc:
> err_init:
> iounmap(regs);
> @@ -487,10 +536,17 @@ static int __devexit mpc52xx_spi_remove(struct of_device *op)
> {
> struct spi_master *master = dev_get_drvdata(&op->dev);
> struct mpc52xx_spi *ms = spi_master_get_devdata(master);
> + int i;
>
> free_irq(ms->irq0, ms);
> free_irq(ms->irq1, ms);
>
> + for (i = 0; i < ms->gpio_cs_count; i++)
> + gpio_free(ms->gpio_cs[i]);
> +
> + if (ms->gpio_cs != NULL)
> + kfree(ms->gpio_cs);
ditto.
> +
> spi_unregister_master(master);
> spi_master_put(master);
> iounmap(ms->regs);
> --
> 1.6.5.2
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* [PATCH 3/3] [V2] mpc52xx_spi: add gpio chipselect
From: Luotao Fu @ 2009-11-13 10:41 UTC (permalink / raw)
To: Grant Likely
Cc: spi-devel-general, David Brownell, linux-kernel, Luotao Fu,
linuxppc-dev
In-Reply-To: <1258108877-25435-3-git-send-email-l.fu@pengutronix.de>
This one enables the mpc52xx_spi driver for usage of user defined gpio lines
as chipselect. This way we can control some more spi devices than only one
V2 Changes:
* preinitialize the gpio as output in probe function and call gpio_set_value in
the chip select function instead of calling direction_output every time.
* initialize the gpio line with output high, since we don't support CS_HIGH
in the driver currently any way. change gpio value setting to default active
low in chip select call.
* free the gpio array while error or removing.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
drivers/spi/mpc52xx_spi.c | 64 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
index 64862cf..97beba2 100644
--- a/drivers/spi/mpc52xx_spi.c
+++ b/drivers/spi/mpc52xx_spi.c
@@ -21,6 +21,7 @@
#include <linux/spi/mpc52xx_spi.h>
#include <linux/of_spi.h>
#include <linux/io.h>
+#include <linux/of_gpio.h>
#include <asm/time.h>
#include <asm/mpc52xx.h>
@@ -79,7 +80,6 @@ struct mpc52xx_spi {
spinlock_t lock;
struct work_struct work;
-
/* Details of current transfer (length, and buffer pointers) */
struct spi_message *message; /* current message */
struct spi_transfer *transfer; /* current transfer */
@@ -89,6 +89,8 @@ struct mpc52xx_spi {
u8 *rx_buf;
const u8 *tx_buf;
int cs_change;
+ int gpio_cs_count;
+ unsigned int *gpio_cs;
};
/*
@@ -96,7 +98,13 @@ struct mpc52xx_spi {
*/
static void mpc52xx_spi_chipsel(struct mpc52xx_spi *ms, int value)
{
- out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
+ int cs;
+
+ if (ms->gpio_cs_count > 0) {
+ cs = ms->message->spi->chip_select;
+ gpio_set_value(ms->gpio_cs[cs], value ? 0 : 1);
+ } else
+ out_8(ms->regs + SPI_PORTDATA, value ? 0 : 0x08);
}
/*
@@ -390,8 +398,9 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
struct spi_master *master;
struct mpc52xx_spi *ms;
void __iomem *regs;
- int rc;
u8 ctrl1;
+ int rc, i = 0;
+ int gpio_cs;
/* MMIO registers */
dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
@@ -426,8 +435,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
rc = -ENOMEM;
goto err_alloc;
}
+
master->bus_num = -1;
- master->num_chipselect = 1;
master->setup = mpc52xx_spi_setup;
master->transfer = mpc52xx_spi_transfer;
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
@@ -441,6 +450,40 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
ms->irq1 = irq_of_parse_and_map(op->node, 1);
ms->state = mpc52xx_spi_fsmstate_idle;
ms->ipb_freq = mpc5xxx_get_bus_frequency(op->node);
+ ms->gpio_cs_count = of_gpio_count(op->node);
+ if (ms->gpio_cs_count > 0) {
+ master->num_chipselect = ms->gpio_cs_count;
+ ms->gpio_cs = kmalloc(ms->gpio_cs_count * sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!ms->gpio_cs) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ for (i = 0; i < ms->gpio_cs_count; i++) {
+ gpio_cs = of_get_gpio(op->node, i);
+ if (gpio_cs < 0) {
+ dev_err(&op->dev,
+ "could not parse the gpio field "
+ "in oftree\n");
+ rc = -ENODEV;
+ goto err_gpio;
+ }
+
+ rc = gpio_request(gpio_cs, dev_name(&op->dev));
+ if (rc) {
+ dev_err(&op->dev,
+ "can't request spi cs gpio #%d "
+ "on gpio line %d\n", i, gpio_cs);
+ goto err_gpio;
+ }
+
+ gpio_direction_output(gpio_cs, 1);
+ ms->gpio_cs[i] = gpio_cs;
+ }
+ } else
+ master->num_chipselect = 1;
+
spin_lock_init(&ms->lock);
INIT_LIST_HEAD(&ms->queue);
INIT_WORK(&ms->work, mpc52xx_spi_wq);
@@ -477,6 +520,12 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
err_register:
dev_err(&ms->master->dev, "initialization failed\n");
spi_master_put(master);
+ err_gpio:
+ while (i-- > 0)
+ gpio_free(ms->gpio_cs[i]);
+
+ if (ms->gpio_cs != NULL)
+ kfree(ms->gpio_cs);
err_alloc:
err_init:
iounmap(regs);
@@ -487,10 +536,17 @@ static int __devexit mpc52xx_spi_remove(struct of_device *op)
{
struct spi_master *master = dev_get_drvdata(&op->dev);
struct mpc52xx_spi *ms = spi_master_get_devdata(master);
+ int i;
free_irq(ms->irq0, ms);
free_irq(ms->irq1, ms);
+ for (i = 0; i < ms->gpio_cs_count; i++)
+ gpio_free(ms->gpio_cs[i]);
+
+ if (ms->gpio_cs != NULL)
+ kfree(ms->gpio_cs);
+
spi_unregister_master(master);
spi_master_put(master);
iounmap(ms->regs);
--
1.6.5.2
^ permalink raw reply related
* [PATCH 1/3] [V2] mpc52xx_spi: fix clearing status register
From: Luotao Fu @ 2009-11-13 10:41 UTC (permalink / raw)
To: Grant Likely
Cc: spi-devel-general, David Brownell, linux-kernel, Luotao Fu,
linuxppc-dev
In-Reply-To: <1258108877-25435-1-git-send-email-l.fu@pengutronix.de>
Before reading status register to check MODF failure, we have to clear it
first since the MODF flag will be set after initializing the spi master,
if the hardware comes up with a low SS. The processor datasheet reads:
Mode Fault flag -- bit sets if SS input goes low while SPI is configured as a
master. Flag is cleared automatically by an SPI status register read (with MODF
set) followed by a SPI control register 1 write.
Hence simply rereading the register is not sufficient to clear the flag. We
redo the write also to make sure to clear the flag.
V2 Changes:
* change variable type from int to u8
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/spi/mpc52xx_spi.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
index ef8379b..2322250 100644
--- a/drivers/spi/mpc52xx_spi.c
+++ b/drivers/spi/mpc52xx_spi.c
@@ -391,6 +391,7 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
struct mpc52xx_spi *ms;
void __iomem *regs;
int rc;
+ u8 ctrl1;
/* MMIO registers */
dev_dbg(&op->dev, "probing mpc5200 SPI device\n");
@@ -399,7 +400,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
return -ENODEV;
/* initialize the device */
- out_8(regs+SPI_CTRL1, SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR);
+ ctrl1 = SPI_CTRL1_SPIE | SPI_CTRL1_SPE | SPI_CTRL1_MSTR;
+ out_8(regs + SPI_CTRL1, ctrl1);
out_8(regs + SPI_CTRL2, 0x0);
out_8(regs + SPI_DATADIR, 0xe); /* Set output pins */
out_8(regs + SPI_PORTDATA, 0x8); /* Deassert /SS signal */
@@ -409,6 +411,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
* on the SPI bus. This fault will also occur if the SPI signals
* are not connected to any pins (port_config setting) */
in_8(regs + SPI_STATUS);
+ out_8(regs + SPI_CTRL1, ctrl1);
+
in_8(regs + SPI_DATA);
if (in_8(regs + SPI_STATUS) & SPI_STATUS_MODF) {
dev_err(&op->dev, "mode fault; is port_config correct?\n");
--
1.6.5.2
^ permalink raw reply related
* [PATCH 2/3] [V2] mpc52xx_spi: add missing mode_bits definition
From: Luotao Fu @ 2009-11-13 10:41 UTC (permalink / raw)
To: Grant Likely
Cc: spi-devel-general, David Brownell, linux-kernel, Luotao Fu,
linuxppc-dev
In-Reply-To: <1258108877-25435-2-git-send-email-l.fu@pengutronix.de>
V2 changes:
* remove CS_HIGH mode
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
---
drivers/spi/mpc52xx_spi.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
index 2322250..64862cf 100644
--- a/drivers/spi/mpc52xx_spi.c
+++ b/drivers/spi/mpc52xx_spi.c
@@ -430,6 +430,8 @@ static int __devinit mpc52xx_spi_probe(struct of_device *op,
master->num_chipselect = 1;
master->setup = mpc52xx_spi_setup;
master->transfer = mpc52xx_spi_transfer;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
+
dev_set_drvdata(&op->dev, master);
ms = spi_master_get_devdata(master);
--
1.6.5.2
^ permalink raw reply related
* [V2] Patches for mpc52xx_spi
From: Luotao Fu @ 2009-11-13 10:41 UTC (permalink / raw)
To: Grant Likely
Cc: spi-devel-general, David Brownell, linux-kernel, linuxppc-dev
In-Reply-To: <1257844329-20687-1-git-send-email-l.fu@pengutronix.de>
Hi Grand,
here are the V2 of my patchset for mpc52xx_spi. Besides Wolframs suggestions I
also added some more fixes. Details of changes can be checked in the patch
header. Please do consider to apply the patches. The patch 1/2 e.g. fix bugs,
which prevent the driver to work in some cases, as seen on my board.
cheers
Luotao Fu
^ permalink raw reply
* Re: [powerpc] Next tree Nov 2 : kernel BUG at mm/mmap.c:2135!
From: Sachin Sant @ 2009-11-13 9:35 UTC (permalink / raw)
To: dwg; +Cc: Linux/PPC Development, linux-next, Stephen Rothwell
In-Reply-To: <20091113021048.GA4865@yookeroo.seuss>
[-- Attachment #1: Type: text/plain, Size: 1898 bytes --]
David Gibson wrote:
> so, could you try booting the kernel with the patch below, which
> should give a bit more information about the problem.
>
> Index: working-2.6/mm/mmap.c
> ===================================================================
> --- working-2.6.orig/mm/mmap.c 2009-11-13 13:08:29.000000000 +1100
> +++ working-2.6/mm/mmap.c 2009-11-13 13:09:26.000000000 +1100
> @@ -2136,6 +2136,8 @@ void exit_mmap(struct mm_struct *mm)
> while (vma)
> vma = remove_vma(vma);
>
> + if (nr_ptes != 0)
> + printk("exit_mmap(): mm %p nr_ptes %d\n", mm, mm->nr_ptes);
> BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
> }
>
Here is the information collected with today's next.
(2.6.32-rc7-20091113)
------------[ cut here ]------------
kernel BUG at mm/mmap.c:2139!
cpu 0x3: Vector: 700 (Program Check) at [c0000000fae1b7e0]
pc: c000000000150e88: .exit_mmap+0x1ac/0x1d4
lr: c000000000150e78: .exit_mmap+0x19c/0x1d4
sp: c0000000fae1ba60
msr: 8000000000029032
current = 0xc0000000fada8be0
paca = 0xc000000000bb2c00
pid = 84, comm = cat
kernel BUG at mm/mmap.c:2139!
enter ? for help
[c0000000fae1bb10] c000000000093d24 .mmput+0x54/0x164
[c0000000fae1bba0] c000000000098f30 .exit_mm+0x17c/0x1a0
[c0000000fae1bc50] c00000000009b310 .do_exit+0x248/0x784
[c0000000fae1bd30] c00000000009b900 .do_group_exit+0xb4/0xe8
[c0000000fae1bdc0] c00000000009b948 .SyS_exit_group+0x14/0x28
[c0000000fae1be30] c0000000000085b4 syscall_exit+0x0/0x40
--- Exception: c01 (System Call) at 00000fff89a8ff40
SP (fffdf8a2460) is in userspace
Have attached the complete boot log.
At the time of crash values of mm and mm->nr_ptes were
<7>exit_mmap(): mm c0000000fa9f9580 nr_ptes 1
Thanks
-Sachin
--
---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------
[-- Attachment #2: next13Nov-boot-log --]
[-- Type: text/plain, Size: 7764 bytes --]
<4>Crash kernel location must be 0x2000000
<6>Reserving 256MB of memory at 32MB for crashkernel (System RAM: 4096MB)
<6>Using pSeries machine description
<7>Page orders: linear mapping = 24, virtual = 16, io = 12
<6>Using 1TB segments
<4>Found initrd at 0xc0000000034d0000:0xc000000003cf8359
<6>bootconsole [udbg0] enabled
<6>Partition configured for 4 cpus.
<6>CPU maps initialized for 2 threads per core
<7> (thread shift is 1)
<4>Starting Linux PPC64 #3 SMP Fri Nov 13 14:48:28 IST 2009
<4>-----------------------------------------------------
<4>ppc64_pft_size = 0x1a
<4>physicalMemorySize = 0x100000000
<4>htab_hash_mask = 0x7ffff
<4>-----------------------------------------------------
<6>Initializing cgroup subsys cpuset
<6>Initializing cgroup subsys cpu
<5>Linux version 2.6.32-rc7-next-20091113 (root@llm62) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #3 SMP Fri Nov 13 14:48:28 IST 2009
<4>[boot]0012 Setup Arch
<7>Node 0 Memory:
<7>Node 1 Memory: 0x0-0x100000000
<4>EEH: No capable adapters found
<6>PPC64 nvram contains 15360 bytes
<7>Using shared processor idle loop
<4>Zone PFN ranges:
<4> DMA 0x00000000 -> 0x00010000
<4> Normal 0x00010000 -> 0x00010000
<4>Movable zone start PFN for each node
<4>early_node_map[1] active PFN ranges
<4> 1: 0x00000000 -> 0x00010000
<4>Could not find start_pfn for node 0
<7>On node 0 totalpages: 0
<7>On node 1 totalpages: 65536
<7> DMA zone: 56 pages used for memmap
<7> DMA zone: 0 pages reserved
<7> DMA zone: 65480 pages, LIFO batch:1
<4>[boot]0015 Setup Done
<6>PERCPU: Embedded 2 pages/cpu @c000000000f00000 s89000 r0 d42072 u262144
<6>pcpu-alloc: s89000 r0 d42072 u262144 alloc=1*1048576
<6>pcpu-alloc: [0] 0 1 2 3
<4>Built 2 zonelists in Node order, mobility grouping on. Total pages: 65480
<4>Policy zone: DMA
<5>Kernel command line: root=/dev/sda5 sysrq=1 insmod=sym53c8xx insmod=ipr crashkernel=512M-:256M xmon=on
<6>PID hash table entries: 4096 (order: -1, 32768 bytes)
<4>freeing bootmem node 1
<6>Memory: 3899712k/4194304k available (9216k kernel code, 294592k reserved, 2688k data, 2370k bss, 640k init)
<6>Hierarchical RCU implementation.
<6>RCU-based detection of stalled CPUs is enabled.
<6>NR_IRQS:512 nr_irqs:512
<4>[boot]0020 XICS Init
<4>[boot]0021 XICS Done
<7>pic: no ISA interrupt controller
<7>time_init: decrementer frequency = 512.000000 MHz
<7>time_init: processor frequency = 4704.000000 MHz
<6>clocksource: timebase mult[7d0000] shift[22] registered
<7>clockevent: decrementer mult[83126e97] shift[32] cpu[0]
<4>Console: colour dummy device 80x25
<6>console [hvc0] enabled, bootconsole disabled
<6>allocated 2621440 bytes of page_cgroup
<6>please try 'cgroup_disable=memory' option if you don't want memory cgroups
<6>Security Framework initialized
<6>SELinux: Disabled at boot.
<6>Dentry cache hash table entries: 524288 (order: 6, 4194304 bytes)
<6>Inode-cache hash table entries: 262144 (order: 5, 2097152 bytes)
<4>Mount-cache hash table entries: 4096
<6>Initializing cgroup subsys ns
<6>Initializing cgroup subsys cpuacct
<6>Initializing cgroup subsys memory
<6>Initializing cgroup subsys devices
<6>Initializing cgroup subsys freezer
<7> alloc irq_desc for 16 on node 0
<7> alloc kstat_irqs on node 0
<7>irq: irq 2 on host null mapped to virtual irq 16
<7>clockevent: decrementer mult[83126e97] shift[32] cpu[1]
<4>Processor 1 found.
<7>clockevent: decrementer mult[83126e97] shift[32] cpu[2]
<4>Processor 2 found.
<7>clockevent: decrementer mult[83126e97] shift[32] cpu[3]
<4>Processor 3 found.
<6>Brought up 4 CPUs
<7>Node 0 CPUs: 0-3
<7>Node 1 CPUs:
<7>CPU0 attaching sched-domain:
<7> domain 0: span 0-1 level SIBLING
<7> groups: 0 (cpu_power = 589) 1 (cpu_power = 589)
<7> domain 1: span 0-3 level CPU
<7> groups: 0-1 (cpu_power = 1178) 2-3 (cpu_power = 1178)
<7>CPU1 attaching sched-domain:
<7> domain 0: span 0-1 level SIBLING
<7> groups: 1 (cpu_power = 589) 0 (cpu_power = 589)
<7> domain 1: span 0-3 level CPU
<7> groups: 0-1 (cpu_power = 1178) 2-3 (cpu_power = 1178)
<7>CPU2 attaching sched-domain:
<7> domain 0: span 2-3 level SIBLING
<7> groups: 2 (cpu_power = 589) 3 (cpu_power = 589)
<7> domain 1: span 0-3 level CPU
<7> groups: 2-3 (cpu_power = 1178) 0-1 (cpu_power = 1178)
<7>CPU3 attaching sched-domain:
<7> domain 0: span 2-3 level SIBLING
<7> groups: 3 (cpu_power = 589) 2 (cpu_power = 589)
<7> domain 1: span 0-3 level CPU
<7> groups: 2-3 (cpu_power = 1178) 0-1 (cpu_power = 1178)
<6>NET: Registered protocol family 16
<6>IBM eBus Device Driver
<6>POWER6 performance monitor hardware support registered
<6>PCI: Probing PCI hardware
<7>PCI: Probing PCI hardware done
<4>bio: create slab <bio-0> at 0
<6>vgaarb: loaded
<6>usbcore: registered new interface driver usbfs
<6>usbcore: registered new interface driver hub
<6>usbcore: registered new device driver usb
<6>Switching to clocksource timebase
<6>NET: Registered protocol family 2
<6>IP route cache hash table entries: 32768 (order: 2, 262144 bytes)
<6>TCP established hash table entries: 131072 (order: 5, 2097152 bytes)
<6>TCP bind hash table entries: 65536 (order: 4, 1048576 bytes)
<6>TCP: Hash tables configured (established 131072 bind 65536)
<6>TCP reno registered
<6>UDP hash table entries: 2048 (order: 0, 65536 bytes)
<6>UDP-Lite hash table entries: 2048 (order: 0, 65536 bytes)
<6>NET: Registered protocol family 1
<7>PCI: CLS 0 bytes, default 128
<6>Unpacking initramfs...
<7>RTAS daemon started
<7> alloc irq_desc for 17 on node 0
<7> alloc kstat_irqs on node 0
<7>irq: irq 655360 on host null mapped to virtual irq 17
<7> alloc irq_desc for 18 on node 0
<7> alloc kstat_irqs on node 0
<7>irq: irq 655362 on host null mapped to virtual irq 18
<6>IOMMU table initialized, virtual merging enabled
<7> alloc irq_desc for 19 on node 0
<7> alloc kstat_irqs on node 0
<7>irq: irq 589825 on host null mapped to virtual irq 19
<6>audit: initializing netlink socket (disabled)
<5>type=2000 audit(1258104404.220:1): initialized
<1>rcu-torture:--- Start of test: nreaders=8 nfakewriters=4 stat_interval=0 verbose=0 test_no_idle_hz=0 shuffle_interval=3 stutter=5 irqreader=1
<6>HugeTLB registered 16 MB page size, pre-allocated 0 pages
<6>HugeTLB registered 16 GB page size, pre-allocated 0 pages
<5>VFS: Disk quotas dquot_6.5.2
<4>Dquot-cache hash table entries: 8192 (order 0, 65536 bytes)
<6>msgmni has been set to 7616
<6>alg: No test for stdrng (krng)
<6>Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
<6>io scheduler noop registered
<6>io scheduler deadline registered
<6>io scheduler cfq registered (default)
<6>pci_hotplug: PCI Hot Plug PCI Core version: 0.5
<6>pciehp: PCI Express Hot Plug Controller Driver version: 0.4
<6>rpaphp: RPA HOT Plug PCI Controller Driver version: 0.1
<7>vio_register_driver: driver hvc_console registering
<7>HVSI: registered 0 devices
<6>Generic RTC Driver v1.07
<6>Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
<6>pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)
<6>input: Macintosh mouse button emulation as /devices/virtual/input/input0
<6>Uniform Multi-Platform E-IDE driver
<6>ide-gd driver 1.18
<6>ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
<6>ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
<6>mice: PS/2 mouse device common for all mice
<6>EDAC MC: Ver: 2.1.0 Nov 13 2009
<6>usbcore: registered new interface driver hiddev
<6>usbcore: registered new interface driver usbhid
<6>usbhid: USB HID core driver
<6>TCP cubic registered
<6>NET: Registered protocol family 15
<4>registered taskstats version 1
<4>Freeing unused kernel memory: 640k freed
<7>exit_mmap(): mm c0000000fa9f9580 nr_ptes 1
<0>------------[ cut here ]------------
<2>kernel BUG at mm/mmap.c:2139!
3:mon>
^ permalink raw reply
* Re: [PATCH] mpc5200/gpt: tiny fix for gpt period limitation
From: Albrecht Dreß @ 2009-11-13 9:25 UTC (permalink / raw)
To: w.sang, grant.likely; +Cc: linuxppc-dev
In-Reply-To: <20091112214425.GD13350@pengutronix.de>
Hi Wolfram:
> > up patch 3. BUT, you're on my shit list. Patch 2 in your series
>=20
> Huh, are you in a bad mood today? IMHO he addressed some valid issues; an=
d
Actually, Grant is right here, as I confused two things, see my other reply=
...
Thanks, Albrecht.
Jetzt NEU: Do it youself E-Cards bei Arcor.de!
Stellen Sie Ihr eigenes Unikat zusammen und machen Sie dem Empf=E4nger eine=
ganz pers=F6nliche Freude!
E-Card Marke Eigenbau: HIER KLICKEN: http://www.arcor.de/rd/footer.ecard
^ permalink raw reply
* Re: [PATCH] mpc5200/gpt: tiny fix for gpt period limitation
From: Albrecht Dreß @ 2009-11-13 9:24 UTC (permalink / raw)
To: grant.likely; +Cc: linuxppc-dev
Hi Grant:
Thanks a lot for pushing the stuff to 'test'.
> up patch 3. BUT, you're on my shit list. Patch 2 in your series
> conflicts with this patch. I had to fix it up by hand. This patch
I'm sorry for that confusion! I actually merged this patch into <http://li=
sts.ozlabs.org/pipermail/linuxppc-dev/2009-November/077715.html>:
<quote>
Note: The patch does also include the tiny GPT api changes from
<http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-November/077647.html>.
</quote>
Actually, this was not *really* the truth...
> should have been part of the series, or at least base the series on
> this patch. Take a look in my -test branch and make sure I fixed it
> right.
...because I now see the following diff between your test branch and my loc=
al version:
<snip>
adress@pc-adr2:/opt/eldk-4.2/usr/src/linux-2.6-secretlab$ diff -uBb arch/po=
werpc/platforms/52xx/mpc52xx_gpt.c ../linux-2.6-secretlab__/arch/powerpc/pl=
atforms/52xx/mpc52xx_gpt.c
--- arch/powerpc/platforms/52xx/mpc52xx_gpt.c 2009-11-13 09:31:40.0000000=
00 +0100
+++ ../linux-2.6-secretlab__/arch/powerpc/platforms/52xx/mpc52xx_gpt.c 200=
9-11-12 14:37:39.000000000 +0100
@@ -414,9 +414,10 @@
/* Determine the number of clocks in the requested period. 64 bit
* arithmatic is done here to preserve the precision until the valu=
e
* is scaled back down into the u32 range. Period is in 'ns', bus
- * frequency is in Hz. */
+ * frequency is in Hz. The maximum timeout @33MHz IPB clock is ~13=
0
+ * seconds*/
clocks =3D period * (u64)gpt->ipb_freq;
- do_div(clocks, 1000000000); /* Scale it down to ns range */
+ do_div(clocks, 1000000000ULL); /* Scale it down to ns range */
=20
/* This device cannot handle a clock count greater than 32 bits */
if (clocks > 0xffffffff)
@@ -460,7 +461,7 @@
/**
* mpc52xx_gpt_start_timer - Set and enable the GPT timer
* @gpt: Pointer to gpt private data structure
- * @period: period of timer in ns; max. ~130s @ 33MHz IPB clock
+ * @period: period of timer in ns
* @continuous: set to 1 to make timer continuous free running
*
* An interrupt will be generated every time the timer fires
</snip>
Again, I'm really sorry for the chaos! Apparently, submitting patches afte=
r two glasses of red wine is a questionable idea... :-/
Thanks, Albrecht.
Jetzt NEU: Do it youself E-Cards bei Arcor.de!
Stellen Sie Ihr eigenes Unikat zusammen und machen Sie dem Empf=E4nger eine=
ganz pers=F6nliche Freude!
E-Card Marke Eigenbau: HIER KLICKEN: http://www.arcor.de/rd/footer.ecard
^ permalink raw reply
* RE: [PATCH 3/6] P2020DS: Fixup sdhc to use PIO mode
From: Gao Guanhua-B22826 @ 2009-11-13 8:30 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev, sdhci-devel
In-Reply-To: <56F6ACCC-7FE8-44E6-BF5E-6361997F524F@kernel.crashing.org>
Hi, Kumar,
I tried to update the patch based on the latest kernel tree
(2.6.32-rc6), there are some problems:
1) the P2020DS board has supported SDHC using DMA, and the latest kernel
tree has included the related code, it doesn't need most of the patches
I posted before.
2) I compiled the image, but the SDHC can not work, it reports error
-110. I adjusted the timeout to the max value, but anther error
occurred.
> -----Original Message-----
> From: Kumar Gala [mailto:galak@kernel.crashing.org]=20
> Sent: Thursday, November 05, 2009 9:52 PM
> To: Gao Guanhua-B22826
> Cc: avorontsov@ru.mvista.com; linuxppc-dev@ozlabs.org;=20
> sdhci-devel@lists.ossman.eu
> Subject: Re: [PATCH 3/6] P2020DS: Fixup sdhc to use PIO mode
>=20
>=20
> On Sep 24, 2009, at 3:28 AM, Gao Guanhua-B22826 wrote:
>=20
> > Thanks, I will add them.
> >
> >> -----Original Message-----
> >> From: Anton Vorontsov [mailto:avorontsov@ru.mvista.com]
> >> Sent: Wednesday, September 23, 2009 7:55 PM
> >> To: Gao Guanhua-B22826
> >> Cc: sdhci-devel@lists.ossman.eu; linuxppc-dev@ozlabs.org
> >> Subject: Re: [PATCH 3/6] P2020DS: Fixup sdhc to use PIO mode
> >>
> >> On Wed, Sep 23, 2009 at 05:08:09PM +0800, Gao Guanhua wrote:
> >>> The SDHC can not work on DMA mode because of the hardware
> >> bug, so we
> >>> set a broken dma flag and use PIO mode. This patch applies
> >> to Rev1.0.
> >>
> >> Signed-off-by line is missing (in all patches).
> >
>=20
> Any plan to update & repost these patches?
>=20
> - k
>=20
>=20
^ permalink raw reply
* Re: [PATCH 3/3] mpc52xx/wdt: WDT uses GPT api
From: Grant Likely @ 2009-11-13 6:21 UTC (permalink / raw)
To: Wim Van Sebroeck
Cc: Albrecht Dreß, devicetree-discuss, Linux PPC Development
In-Reply-To: <20091112213630.GE19336@infomag.iguana.be>
On Thu, Nov 12, 2009 at 2:36 PM, Wim Van Sebroeck <wim@iguana.be> wrote:
> Hi All,
>
>>> Can the WDT functionality just be merged entirely into
>>> arch/powerpc/platforms/52xx/mpc52xx_gpt.c, eliminating the need for
>>> this file entirely? =A0I think I'd rather have all the GPT "built in"
>>> behaviour handled by a single driver.
>>
>> I also thought about it, as it has IMHO the cleaner code, and it would h=
ave the extra benefit that the gpt-wdt api doesn't need to be public.
>>
>> However, the reasons I hesitated to do so are:
>> - I don't want to remove a file someone else wrote (even it doesn't work=
);
>> - WDT code is shifted from drivers/watchdog to arch/powerpc/platforms/52=
xx which might not be the "logical" place from the directory layout's pov;
>> - a file living in arch/powerpc/platforms/52xx depends upon config optio=
ns set from drivers/watchdog/Kconfig which may be confusing.
>>
>> You see these are more political/cosmetical questions, so I would prefer=
to leave the decision to the maintainers (i.e. you and Wim). =A0Preparing =
a fully merged driver is actually a matter of minutes!
>
> My opinion: it is harder to maintain the watchdog code if it is being mov=
ed away from drivers/watchdog.
> I need to check the code before I comment any further on this, but my fir=
st thought is: why don't you do it with platform resources like other devic=
es are doing? This way you can keep the platform code under arch and the wa=
tchdog itself under drivers/watchdog/. You can look at the following driver=
s as an example: adx_wdt.c ar7_wdt.c at32ap700x_wdt.c coh901327_wdt.c davin=
ci_wdt.c mpcore_wdt.c mv64x60_wdt.c nuc900_wdt.c omap_wdt.c pnx4008_wdt.c r=
c32434_wdt.c s3c2410_wdt.c txx9wdt.c .
In actual fact, it is a single device with multiple functions, some of
which can be used at the same time. The driver for the device
determines what the device instance supports and registers the
appropriate interfaces. There is a GPIO controller, a PWM controller,
a general purpose timer, and the watchdog. Because of the
multifunction nature of the device, there are subtle interactions
between the functions that the driver needs to maintain. I don't want
to export functions from the driver which will only be used by a
watchdog instance. I also don't want the added code and complexity of
a secondary probe path. It is simpler and less code to roll all the
behaviour up into the one driver single driver that gets probed once.
>From the maintenance perspective, having the main driver in
arch/powerpc and the watchdog bit in drivers/watchdog doesn't really
help much anyway because anything that changes the internal driver API
(between the core and watchdog bits) will require cross-maintainer
changes. ie. do changes go through my tree because they touch
arch/powerpc, or do they go through yours because they touch
drivers/watchdog? I'd much rather all the internal details be
contained within a single driver.
Besides, there is already precedence for very arch-specific drivers
living under arch/*/. find ./arch -name *gpio*
Cheers,
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: OOPS on MPC8548 board when writing RAID5 array
From: hank peng @ 2009-11-13 2:45 UTC (permalink / raw)
To: Dan Williams; +Cc: linux-raid, linuxppc-dev, Suresh Vishnu
In-Reply-To: <e9c3a7c20911121736ma9f8d72waa377c4b61b2f480@mail.gmail.com>
2009/11/13 Dan Williams <dan.j.williams@intel.com>:
> Hi Hank,
>
> Thanks for testing.
>
> On Tue, Nov 10, 2009 at 4:44 AM, hank peng <pengxihan@gmail.com> wrote:
>> CPU is MPC8548, kernel version is 2.6.31.5,CONFIG_FSL_DMA and
>> CONFIG_ASYNC_TX_DMA options are all enabled.
>> #mdadm -C /dev/md0 --assume-clean -l5 -n3 /dev/sd{a,b,c}
>> #dd if=3D/dev/zero of=3D/dev/md0 bs=3D1M count=3D1000
>> Oops: Exception in kernel mode, sig: 5 [#1]
>> MPC85xx CDS
>> Modules linked in:
>> NIP: c01c45d8 LR: c01c4d48 CTR: 00000000
>> REGS: c2dd5c80 TRAP: 0700 =C2=A0 Not tainted =C2=A0(2.6.31.5)
>> MSR: 00029000 <EE,ME,CE> =C2=A0CR: 22004028 =C2=A0XER: 00000000
>> TASK =3D e820a580[3804] 'md0_raid5' THREAD: c2dd4000
>> GPR00: 00000001 c2dd5d30 e820a580 c2fb1088 00000001 00000000 00000002 00=
001000
>> GPR08: 00000001 c0485a20 00000000 ef8092f8 22002024 55555555 c2d67870 c0=
282d2c
>> GPR16: 00001000 e8355c00 c2eff964 00000000 00000000 00000019 01000040 c2=
dd5e00
>> GPR24: c2dd5dfc 00000001 c2dd5dc0 c099c420 00000000 c2d67838 00000002 c2=
dd5d58
>> NIP [c01c45d8] async_tx_quiesce+0x28/0x74
> [..]
>> I checked the kernel source code, and find that this OOPS was caused
>> by the following BUG_ON code:
>> It is in crypto/async_tx/async_tx.c:
>> void async_tx_quiesce(struct dma_async_tx_descriptor **tx)
>> {
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0if (*tx) {
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* if ack is alre=
ady set then we cannot be sure
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * we are referri=
ng to the correct operation
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 */
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0BUG_ON(async_tx_t=
est_ack(*tx));
>> =C2=A0 /* OOPS occured */
>
> Yes, this looks like a manifestation of the issue I brought up in my
> review of the driver [1]. =C2=A0The talitos_prep_dma_xor routine is alway=
s
> acknowledging its descriptors, which it should not because that is the
> responsibility of the client of the api. =C2=A0When the raid code tries t=
o
> attach a memcpy that depends on the xor it sees that it needs to
> switch to from talitos to fsldma (or software if fsldma is turned
> off). =C2=A0Since talitos does not have the DMA_INTERRUPT capability to
> trigger the channel switch we need to perform a synchronous wait for
> the xor to complete before submitting the memcpy. =C2=A0When the ack bit =
is
> not set the xor descriptor might be recycled by the dma device driver
> while we are waiting for it, hence the BUG_ON().
>
Thanks for reply, Dan.
Forgot to say, when this OOPS happened, I have not applied talitos XOR
patch. I only enabled async_xx api and FSL_DMA, so here
I think XOR was done by CPU and memcpy was done by DMA using async_xx api.
Another interseting thing I should say is that I have tried latest
stable kernel 2.6.31.6, this problem didn't exist. After I applied
talitos XOR patch, it was OK too. I checked the related souce codes
and it seems that there were no changes which make me feel very
confused.
I have been testing latest serials of kernels about XOR patch on
MPC8548 board and I hope Freescale guys also can give me help.
> --
> Dan
>
> See the final comment:
> [1]: http://marc.info/?l=3Dlinux-raid&m=3D125685641412112&w=3D2
>
--=20
The simplest is not all best but the best is surely the simplest!
^ permalink raw reply
* Re: [powerpc] Next tree Nov 2 : kernel BUG at mm/mmap.c:2135!
From: David Gibson @ 2009-11-13 2:10 UTC (permalink / raw)
To: Sachin Sant, Linux/PPC Development, Stephen Rothwell, linux-next,
Benjamin Herrenschmidt
In-Reply-To: <20091113013729.GB18848@yookeroo.seuss>
On Fri, Nov 13, 2009 at 12:37:29PM +1100, David Gibson wrote:
> On Thu, Nov 12, 2009 at 04:46:40PM +0530, Sachin Sant wrote:
> > David Gibson wrote:
> > >On Wed, Nov 04, 2009 at 06:08:44PM +0530, Sachin Sant wrote:
> > >>Sachin Sant wrote:
> > >>>Today's next tree failed to boot on a POWER 6 box with :
> > >>>
> > >>>------------[ cut here ]------------
> > >>>kernel BUG at mm/mmap.c:2135!
> > >>>Oops: Exception in kernel mode, sig: 5 [#2]
> > >>>SMP NR_CPUS=1024 NUMA pSeries
> > >>Problem exists with today's next as well.
> > >>
> > >>Likely cause for this problem seems to the following commit.
> > >>If i revert this patch the machine boots fine.
> > >>
> > >>commit a0668cdc154e54bf0c85182e0535eea237d53146
> > >>powerpc/mm: Cleanup management of kmem_caches for pagetables
> > >
> > >Ugh. Ok, it's not at all obvious how my patch could cause this bug.
> > >Can you send your .config?
> > >
> > Still present in today's next.
>
> Sorry, I've been sidetracked by other issues and have only managed to
> look into this today. My initial attempts to reproduce the bug with
> your config on both POWER6 and POWER5+ have failed though.
>
> Is it possible to get the complete boot log from this system - not
> just the [cut here] section around the BUG()? This should help to
> determine exactly when during boot the bug is being triggered.
Also, could you try booting the kernel with the patch below, which
should give a bit more information about the problem.
Index: working-2.6/mm/mmap.c
===================================================================
--- working-2.6.orig/mm/mmap.c 2009-11-13 13:08:29.000000000 +1100
+++ working-2.6/mm/mmap.c 2009-11-13 13:09:26.000000000 +1100
@@ -2136,6 +2136,8 @@ void exit_mmap(struct mm_struct *mm)
while (vma)
vma = remove_vma(vma);
+ if (nr_ptes != 0)
+ printk("exit_mmap(): mm %p nr_ptes %d\n", mm, mm->nr_ptes);
BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
}
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [powerpc] Next tree Nov 2 : kernel BUG at mm/mmap.c:2135!
From: David Gibson @ 2009-11-13 1:37 UTC (permalink / raw)
To: Sachin Sant; +Cc: Linux/PPC Development, linux-next, Stephen Rothwell
In-Reply-To: <4AFBEE98.2070208@in.ibm.com>
On Thu, Nov 12, 2009 at 04:46:40PM +0530, Sachin Sant wrote:
> David Gibson wrote:
> >On Wed, Nov 04, 2009 at 06:08:44PM +0530, Sachin Sant wrote:
> >>Sachin Sant wrote:
> >>>Today's next tree failed to boot on a POWER 6 box with :
> >>>
> >>>------------[ cut here ]------------
> >>>kernel BUG at mm/mmap.c:2135!
> >>>Oops: Exception in kernel mode, sig: 5 [#2]
> >>>SMP NR_CPUS=1024 NUMA pSeries
> >>Problem exists with today's next as well.
> >>
> >>Likely cause for this problem seems to the following commit.
> >>If i revert this patch the machine boots fine.
> >>
> >>commit a0668cdc154e54bf0c85182e0535eea237d53146
> >>powerpc/mm: Cleanup management of kmem_caches for pagetables
> >
> >Ugh. Ok, it's not at all obvious how my patch could cause this bug.
> >Can you send your .config?
> >
> Still present in today's next.
Sorry, I've been sidetracked by other issues and have only managed to
look into this today. My initial attempts to reproduce the bug with
your config on both POWER6 and POWER5+ have failed though.
Is it possible to get the complete boot log from this system - not
just the [cut here] section around the BUG()? This should help to
determine exactly when during boot the bug is being triggered.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: OOPS on MPC8548 board when writing RAID5 array
From: Dan Williams @ 2009-11-13 1:36 UTC (permalink / raw)
To: hank peng; +Cc: linux-raid, linuxppc-dev, Suresh Vishnu
In-Reply-To: <389deec70911100344j5969e834nc80a9fd330935ef3@mail.gmail.com>
Hi Hank,
Thanks for testing.
On Tue, Nov 10, 2009 at 4:44 AM, hank peng <pengxihan@gmail.com> wrote:
> CPU is MPC8548, kernel version is 2.6.31.5,CONFIG_FSL_DMA and
> CONFIG_ASYNC_TX_DMA options are all enabled.
> #mdadm -C /dev/md0 --assume-clean -l5 -n3 /dev/sd{a,b,c}
> #dd if=3D/dev/zero of=3D/dev/md0 bs=3D1M count=3D1000
> Oops: Exception in kernel mode, sig: 5 [#1]
> MPC85xx CDS
> Modules linked in:
> NIP: c01c45d8 LR: c01c4d48 CTR: 00000000
> REGS: c2dd5c80 TRAP: 0700 =A0 Not tainted =A0(2.6.31.5)
> MSR: 00029000 <EE,ME,CE> =A0CR: 22004028 =A0XER: 00000000
> TASK =3D e820a580[3804] 'md0_raid5' THREAD: c2dd4000
> GPR00: 00000001 c2dd5d30 e820a580 c2fb1088 00000001 00000000 00000002 000=
01000
> GPR08: 00000001 c0485a20 00000000 ef8092f8 22002024 55555555 c2d67870 c02=
82d2c
> GPR16: 00001000 e8355c00 c2eff964 00000000 00000000 00000019 01000040 c2d=
d5e00
> GPR24: c2dd5dfc 00000001 c2dd5dc0 c099c420 00000000 c2d67838 00000002 c2d=
d5d58
> NIP [c01c45d8] async_tx_quiesce+0x28/0x74
[..]
> I checked the kernel source code, and find that this OOPS was caused
> by the following BUG_ON code:
> It is in crypto/async_tx/async_tx.c:
> void async_tx_quiesce(struct dma_async_tx_descriptor **tx)
> {
> =A0 =A0 =A0 =A0if (*tx) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* if ack is already set then we cannot be=
sure
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 * we are referring to the correct operati=
on
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BUG_ON(async_tx_test_ack(*tx));
> =A0 /* OOPS occured */
Yes, this looks like a manifestation of the issue I brought up in my
review of the driver [1]. The talitos_prep_dma_xor routine is always
acknowledging its descriptors, which it should not because that is the
responsibility of the client of the api. When the raid code tries to
attach a memcpy that depends on the xor it sees that it needs to
switch to from talitos to fsldma (or software if fsldma is turned
off). Since talitos does not have the DMA_INTERRUPT capability to
trigger the channel switch we need to perform a synchronous wait for
the xor to complete before submitting the memcpy. When the ack bit is
not set the xor descriptor might be recycled by the dma device driver
while we are waiting for it, hence the BUG_ON().
--
Dan
See the final comment:
[1]: http://marc.info/?l=3Dlinux-raid&m=3D125685641412112&w=3D2
^ permalink raw reply
* Re: [PATCH] mpc5200/gpt: tiny fix for gpt period limitation
From: Grant Likely @ 2009-11-13 0:21 UTC (permalink / raw)
To: Wolfram Sang; +Cc: Albrecht Dreß, linuxppc-dev
In-Reply-To: <20091112214425.GD13350@pengutronix.de>
On Thu, Nov 12, 2009 at 2:44 PM, Wolfram Sang <w.sang@pengutronix.de> wrote=
:
>> up patch 3. =A0BUT, you're on my shit list. =A0Patch 2 in your series
>
> Huh, are you in a bad mood today? IMHO he addressed some valid issues; an=
d we
> all had to start somewhere regarding the workflow. I know that manually
> adapting patches is annoying, but this wording sounds quite strong...
Albrecht has been around for a bit now. He does good work, responds
to comments, and in general shows good taste. This particular case
was just a bit sloppy. The patch was damaged on the mailing list and
it conflicted with his other patches. I know he knows better.
Albrecht, I'm not actually mad at you, and I'm sorry for the harsh
working. The patch series is good work. I wouldn't have picked it up
if it was otherwise. I'm just a little annoyed about something I know
you can handle better. I don't bear any ill will.
Cheers,
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: kexec for powerpc
From: wilbur.chan @ 2009-11-12 23:55 UTC (permalink / raw)
To: James Black; +Cc: Linuxppc-dev
In-Reply-To: <b77025b40911121542q2d318870i627b3cc4d8bb444b@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 182 bytes --]
2009/11/13 James Black <jblack547@gmail.com>
> powerpc32 for processors like the freescale 82xx, 83xx machines.
>
> Thanks,
> JB
>
>
maybe 83xx kexec needs to add some dtb support
[-- Attachment #2: Type: text/html, Size: 454 bytes --]
^ permalink raw reply
* Re: kexec for powerpc
From: James Black @ 2009-11-12 23:42 UTC (permalink / raw)
To: Josh Boyer; +Cc: Linuxppc-dev
In-Reply-To: <20091112233148.GF5699@hansolo.jdub.homelinux.org>
powerpc32 for processors like the freescale 82xx, 83xx machines.
Thanks,
JB
On Thu, Nov 12, 2009 at 4:31 PM, Josh Boyer <jwboyer@gmail.com> wrote:
> On Thu, Nov 12, 2009 at 04:08:07PM -0700, James Black wrote:
>>Are there efforts in this area or is it already working for powerpc? I
>>cross compiled kexec and tried it on an old kernel with kexec support
>>compiled in.
>
> 'powerpc' is a bit too vague. It works on lots of ppc64 machines already.
> What class of hardware are you talking about?
>
> josh
>
--
Jim Black
Senior Software Engineer
Aztek Networks, Inc.
2477 55th Street, Suite 202
Boulder, CO 80301
www.azteknetworks.com
^ permalink raw reply
* Re: kexec for powerpc
From: Josh Boyer @ 2009-11-12 23:31 UTC (permalink / raw)
To: James Black; +Cc: Linuxppc-dev
In-Reply-To: <b77025b40911121508l350e629bt7adaa9da936788d5@mail.gmail.com>
On Thu, Nov 12, 2009 at 04:08:07PM -0700, James Black wrote:
>Are there efforts in this area or is it already working for powerpc? I
>cross compiled kexec and tried it on an old kernel with kexec support
>compiled in.
'powerpc' is a bit too vague. It works on lots of ppc64 machines already.
What class of hardware are you talking about?
josh
^ permalink raw reply
* Re: [PATCH 0/8] 8xx: Misc fixes for buggy insn
From: Joakim Tjernlund @ 2009-11-12 23:29 UTC (permalink / raw)
To: Scott Wood; +Cc: linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <4AFC84E7.6050706@freescale.com>
Scott Wood <scottwood@freescale.com> wrote on 12/11/2009 22:57:59:
>
> Joakim Tjernlund wrote:
> > Scott Wood <scottwood@freescale.com> wrote on 12/11/2009 20:45:59:
> >> One other concern with pinning on 8xx -- could it cause problems with
> >> uncached DMA mappings? What happens if a speculative load pulls in a
> >> cache line in an area that's supposed to be uncached?
> >
> > hmm, why should this be a problem?
>
> Because then you would be accessing potentially stale DMA data -- and
> more generally, the architecture prohibits such mixing.
>
> > Pinning has been around as a config option
> > for a long time so any problems should have surfaced by now.
>
> It has existed as an option, which is going to get less test coverage
> than something that is always on. Plus, it would not be a particularly
> common failure -- easy to blame one-off weirdness on something else.
>
> > Secondly, I was thinking that we could just make the ITLB pinning
> > mandatory and let the DTLB pinning be as is, configurable.
>
> That could work. We could also limit the pool of memory
> dma_alloc_coherent() uses to not overlap with anything pinned.
And try using the remaing 3 ITLBs which are unused when pinning to
cover the module space. Probably not going to be perfect.
Anyhow, lets start simple and just do the pinned ITLB so the
new TLB code can be applied. Can you confirm this works for you?
>From 0c30d6c1ee45341fcfc5643bd2ba876e3c9a416e Mon Sep 17 00:00:00 2001
From: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Date: Fri, 13 Nov 2009 00:26:59 +0100
Subject: [PATCH] 8xx: Always pin kernel instruction TLB
---
arch/powerpc/kernel/head_8xx.S | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index adc5a32..c7a4e60 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -767,7 +767,7 @@ start_here:
*/
initial_mmu:
tlbia /* Invalidate all TLB entries */
-#ifdef CONFIG_PIN_TLB
+#ifdef 1 /* CONFIG_PIN_TLB */
lis r8, MI_RSV4I@h
ori r8, r8, 0x1c00
#else
--
1.6.4.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox