summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-2.6.31/boc01/008-091005-spi.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.31/boc01/008-091005-spi.patch')
-rw-r--r--recipes/linux/linux-2.6.31/boc01/008-091005-spi.patch226
1 files changed, 226 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.31/boc01/008-091005-spi.patch b/recipes/linux/linux-2.6.31/boc01/008-091005-spi.patch
new file mode 100644
index 0000000000..ea775a8b73
--- /dev/null
+++ b/recipes/linux/linux-2.6.31/boc01/008-091005-spi.patch
@@ -0,0 +1,226 @@
+Index: linux-2.6.31/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+===================================================================
+--- linux-2.6.31.orig/arch/powerpc/platforms/83xx/mpc831x_rdb.c 2009-10-19 16:32:13.000000000 +0200
++++ linux-2.6.31/arch/powerpc/platforms/83xx/mpc831x_rdb.c 2009-10-19 16:48:50.000000000 +0200
+@@ -14,18 +14,175 @@
+ */
+
+ #include <linux/pci.h>
++#include <linux/interrupt.h>
+ #include <linux/of_platform.h>
++#include <linux/spi/spi.h>
++#include <linux/fsl_devices.h>
+
+ #include <asm/time.h>
+ #include <asm/ipic.h>
+ #include <asm/udbg.h>
++#include <asm/qe.h>
+ #include <sysdev/fsl_pci.h>
++#include <sysdev/fsl_soc.h>
+
+ #include "mpc83xx.h"
+
+ /*
+ * Setup the architecture
+ */
++struct gpio {
++ __be32 gpdir;
++ __be32 gpodr;
++ __be32 gpdat;
++ __be32 gpier;
++ __be32 gpimr;
++ __be32 gpicr;
++} __attribute__ ((packed));
++static struct gpio *gpio_regs;
++
++static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
++ struct spi_board_info *board_infos,
++ unsigned int num_board_infos,
++ void (*cs_control)(struct spi_device *dev,
++ bool on))
++{
++ struct device_node *np;
++ unsigned int i = 0;
++
++ for_each_compatible_node(np, type, compatible) {
++ int ret;
++ unsigned int j;
++ const void *prop;
++ struct resource res[2];
++ struct platform_device *pdev;
++ struct fsl_spi_platform_data pdata = {
++ .cs_control = cs_control,
++ };
++
++ memset(res, 0, sizeof(res));
++
++ pdata.sysclk = sysclk;
++
++ prop = of_get_property(np, "reg", NULL);
++ if (!prop)
++ goto err;
++ pdata.bus_num = *(u32 *)prop;
++
++ prop = of_get_property(np, "cell-index", NULL);
++ if (prop)
++ i = *(u32 *)prop;
++
++ prop = of_get_property(np, "mode", NULL);
++ if (prop && !strcmp(prop, "cpu-qe"))
++ pdata.qe_mode = 1;
++
++ for (j = 0; j < num_board_infos; j++) {
++ if (board_infos[j].bus_num == pdata.bus_num)
++ pdata.max_chipselect++;
++ }
++
++ if (!pdata.max_chipselect)
++ continue;
++
++ ret = of_address_to_resource(np, 0, &res[0]);
++ if (ret)
++ goto err;
++
++ ret = of_irq_to_resource(np, 0, &res[1]);
++ if (ret == NO_IRQ)
++ goto err;
++
++ pdev = platform_device_alloc("mpc83xx_spi", i);
++ if (!pdev)
++ goto err;
++
++ ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
++ if (ret)
++ goto unreg;
++
++ ret = platform_device_add_resources(pdev, res,
++ ARRAY_SIZE(res));
++ if (ret)
++ goto unreg;
++
++ ret = platform_device_add(pdev);
++ if (ret)
++ goto unreg;
++
++ goto next;
++unreg:
++ platform_device_del(pdev);
++err:
++ pr_err("%s: registration failed\n", np->full_name);
++next:
++ i++;
++ }
++
++ return i;
++}
++
++static int __init fsl_spi_init(struct spi_board_info *board_infos,
++ unsigned int num_board_infos,
++ void (*cs_control)(struct spi_device *spi,
++ bool on))
++{
++ u32 sysclk = -1;
++ int ret;
++
++ /* SPI controller is either clocked from QE or SoC clock */
++ sysclk = get_brgfreq();
++ if (sysclk == -1) {
++ sysclk = fsl_get_sys_freq();
++ if (sysclk == -1)
++ return -ENODEV;
++ }
++
++ ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
++ num_board_infos, cs_control);
++ if (!ret)
++ of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos,
++ num_board_infos, cs_control);
++
++ return spi_register_board_info(board_infos, num_board_infos);
++}
++
++static void mpc83xx_spi_cs_control(struct spi_device *spi, bool on)
++{
++ pr_debug("%s %d %d\n", __func__, spi->chip_select, on);
++ par_io_data_set(3, 13, on);
++}
++
++static struct spi_board_info mpc8313_spi_boardinfo = {
++ .bus_num = 0x7000,
++ .chip_select = 0,
++ .max_speed_hz = 50000000,
++ .modalias = "spidev",
++};
++
++static int __init mpc8313_spi_init(void)
++{
++ __be32 __iomem *psicrl;
++
++ /* System I/O Configuration Register Low */
++ psicrl = ioremap(get_immrbase() + MPC83XX_SICRL_OFFS, 0x4);
++ gpio_regs = ioremap(get_immrbase() + 0xc00, 0x20);
++ if (!psicrl || !gpio_regs)
++ return -ENOMEM;
++
++ clrbits32(psicrl, 0x03F00000);
++ setbits32(psicrl, 0x30000000);
++ iounmap(psicrl);
++
++ /* set GPIO13 as output */
++ setbits32(&gpio_regs->gpdir, 1 << (31 - 14));
++ clrbits32(&gpio_regs->gpodr, 1 << (31 - 14));
++ setbits32(&gpio_regs->gpdat, 1 << (31 - 14));
++
++ return fsl_spi_init(&mpc8313_spi_boardinfo, 1, mpc83xx_spi_cs_control);
++}
++machine_device_initcall(mpc831x_rdb, mpc8313_spi_init);
++
+ static void __init mpc831x_rdb_setup_arch(void)
+ {
+ #ifdef CONFIG_PCI
+Index: linux-2.6.31/drivers/spi/spi_mpc8xxx.c
+===================================================================
+--- linux-2.6.31.orig/drivers/spi/spi_mpc8xxx.c 2009-10-19 16:32:13.000000000 +0200
++++ linux-2.6.31/drivers/spi/spi_mpc8xxx.c 2009-10-19 16:41:27.000000000 +0200
+@@ -285,7 +285,9 @@
+ if (pm)
+ pm--;
+
+- cs->hw_mode |= SPMODE_PM(pm);
++ cs->hw_mode = 0x0F700000;
++ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode,cs->hw_mode);
++
+ regval = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
+ if (cs->hw_mode != regval) {
+ unsigned long flags;
+@@ -445,7 +447,7 @@
+ cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
+ /* mask out bits we are going to set */
+ cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
+- | SPMODE_REV | SPMODE_LOOP);
++ | SPMODE_REV );
+
+ if (spi->mode & SPI_CPHA)
+ cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
+@@ -453,8 +455,10 @@
+ cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
+ if (!(spi->mode & SPI_LSB_FIRST))
+ cs->hw_mode |= SPMODE_REV;
+- if (spi->mode & SPI_LOOP)
+- cs->hw_mode |= SPMODE_LOOP;
++
++ cs->hw_mode = 0x0F700000;
++ mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode,cs->hw_mode);
++ cs->hw_mode = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode);
+
+ retval = mpc8xxx_spi_setup_transfer(spi, NULL);
+ if (retval < 0) {
+@@ -602,7 +606,7 @@
+ INIT_LIST_HEAD(&mpc8xxx_spi->queue);
+
+ mpc8xxx_spi->workqueue = create_singlethread_workqueue(
+- dev_name(master->dev.parent));
++ dev_name(&dev->dev));
+ if (mpc8xxx_spi->workqueue == NULL) {
+ ret = -EBUSY;
+ goto free_irq;