|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/spi/mmc_spi.h>
|
|
|
#include <linux/mmc/host.h>
|
|
|
#include <linux/of_platform.h>
|
|
|
+#include <linux/fsl_devices.h>
|
|
|
|
|
|
#include <asm/time.h>
|
|
|
#include <asm/ipic.h>
|
|
@@ -39,6 +40,112 @@
|
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_QUICC_ENGINE
|
|
|
+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);
|