diff options
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.patch | 226 |
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; |