diff options
Diffstat (limited to 'arch/powerpc/platforms/83xx/mpc832x_rdb.c')
| -rw-r--r-- | arch/powerpc/platforms/83xx/mpc832x_rdb.c | 123 | 
1 files changed, 114 insertions, 9 deletions
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 2a1295f1983..567ded7c3b9 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -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,16 +40,116 @@  #endif  #ifdef CONFIG_QUICC_ENGINE -static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity) +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))  { -	pr_debug("%s %d %d\n", __func__, cs, polarity); -	par_io_data_set(3, 13, polarity); +	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 void mpc83xx_spi_deactivate_cs(u8 cs, u8 polarity) +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))  { -	pr_debug("%s %d %d\n", __func__, cs, polarity); -	par_io_data_set(3, 13, !polarity); +	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 mmc_spi_platform_data mpc832x_mmc_pdata = { @@ -74,9 +175,13 @@ static int __init mpc832x_spi_init(void)  	par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */  	par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */ -	return fsl_spi_init(&mpc832x_spi_boardinfo, 1, -			    mpc83xx_spi_activate_cs, -			    mpc83xx_spi_deactivate_cs); +	/* +	 * Don't bother with legacy stuff when device tree contains +	 * mmc-spi-slot node. +	 */ +	if (of_find_compatible_node(NULL, NULL, "mmc-spi-slot")) +		return 0; +	return fsl_spi_init(&mpc832x_spi_boardinfo, 1, mpc83xx_spi_cs_control);  }  machine_device_initcall(mpc832x_rdb, mpc832x_spi_init);  #endif /* CONFIG_QUICC_ENGINE */  |