diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 87 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.h | 7 |
2 files changed, 94 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 7012e51ae5c..d028e8da027 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/of_platform.h> #include <linux/phy.h> +#include <linux/spi/spi.h> #include <linux/fsl_devices.h> #include <linux/fs_enet_pd.h> #include <linux/fs_uart_pd.h> @@ -1199,3 +1200,89 @@ err: arch_initcall(cpm_smc_uart_of_init); #endif /* CONFIG_8xx */ + +int __init fsl_spi_init(struct spi_board_info *board_infos, + unsigned int num_board_infos, + void (*activate_cs)(u8 cs, u8 polarity), + void (*deactivate_cs)(u8 cs, u8 polarity)) +{ + struct device_node *np; + unsigned int i; + const u32 *sysclk; + + np = of_find_node_by_type(NULL, "qe"); + if (!np) + return -ENODEV; + + sysclk = of_get_property(np, "bus-frequency", NULL); + if (!sysclk) + return -ENODEV; + + for (np = NULL, i = 1; + (np = of_find_compatible_node(np, "spi", "fsl_spi")) != NULL; + i++) { + int ret = 0; + unsigned int j; + const void *prop; + struct resource res[2]; + struct platform_device *pdev; + struct fsl_spi_platform_data pdata = { + .activate_cs = activate_cs, + .deactivate_cs = deactivate_cs, + }; + + 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, "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) + goto err; + + 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_register(pdev); + if (ret) + goto unreg; + + continue; +unreg: + platform_device_del(pdev); +err: + continue; + } + + return spi_register_board_info(board_infos, num_board_infos); +} diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 04e145b5fc3..618d91d1e10 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -8,5 +8,12 @@ extern phys_addr_t get_immrbase(void); extern u32 get_brgfreq(void); extern u32 get_baudrate(void); +struct spi_board_info; + +extern int fsl_spi_init(struct spi_board_info *board_infos, + unsigned int num_board_infos, + void (*activate_cs)(u8 cs, u8 polarity), + void (*deactivate_cs)(u8 cs, u8 polarity)); + #endif #endif |