From ab1843096323070396a0adec016c5d67c07eb9ad Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 20 Feb 2014 16:48:05 +0800 Subject: [PATCH] ENGR00300439-3 imx6sx: use auxdata for can transceiver setting We still do not have a framework for can tranceiver settings. Use audxdata as workaround as before. Signed-off-by: Dong Aisheng (cherry picked from commit a6e475caedb096c631f853b33e7787f2f7caff17) --- arch/arm/mach-imx/mach-imx6sx.c | 71 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 968ef509933b..436a9be8ab8b 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -6,7 +6,10 @@ * published by the Free Software Foundation. */ +#include +#include #include +#include #include #include #include @@ -14,6 +17,69 @@ #include "common.h" +static struct flexcan_platform_data flexcan_pdata[2]; +static int flexcan_en_gpio; +static int flexcan_stby_gpio; +static int flexcan0_en; +static int flexcan1_en; +static void mx6sx_flexcan_switch(void) +{ + if (flexcan0_en || flexcan1_en) { + gpio_set_value_cansleep(flexcan_en_gpio, 0); + gpio_set_value_cansleep(flexcan_stby_gpio, 0); + gpio_set_value_cansleep(flexcan_en_gpio, 1); + gpio_set_value_cansleep(flexcan_stby_gpio, 1); + } else { + /* + * avoid to disable CAN xcvr if any of the CAN interfaces + * are down. XCRV will be disabled only if both CAN2 + * interfaces are DOWN. + */ + gpio_set_value_cansleep(flexcan_en_gpio, 0); + gpio_set_value_cansleep(flexcan_stby_gpio, 0); + } +} + +static void imx6sx_arm2_flexcan0_switch(int enable) +{ + flexcan0_en = enable; + mx6sx_flexcan_switch(); +} + +static void imx6sx_arm2_flexcan1_switch(int enable) +{ + flexcan1_en = enable; + mx6sx_flexcan_switch(); +} + +static int __init imx6sx_arm2_flexcan_fixup(void) +{ + struct device_node *np; + + np = of_find_node_by_path("/soc/aips-bus@02000000/can@02090000"); + if (!np) + return -ENODEV; + + flexcan_en_gpio = of_get_named_gpio(np, "trx-en-gpio", 0); + flexcan_stby_gpio = of_get_named_gpio(np, "trx-stby-gpio", 0); + if (gpio_is_valid(flexcan_en_gpio) && gpio_is_valid(flexcan_stby_gpio) && + !gpio_request_one(flexcan_en_gpio, GPIOF_DIR_OUT, "flexcan-trx-en") && + !gpio_request_one(flexcan_stby_gpio, GPIOF_DIR_OUT, "flexcan-trx-stby")) { + /* flexcan 0 & 1 are using the same GPIOs for transceiver */ + flexcan_pdata[0].transceiver_switch = imx6sx_arm2_flexcan0_switch; + flexcan_pdata[1].transceiver_switch = imx6sx_arm2_flexcan1_switch; + } + + return 0; +} + +/* Add auxdata to pass platform data */ +static const struct of_dev_auxdata imx6sx_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("fsl,imx6q-flexcan", 0x02090000, NULL, &flexcan_pdata[0]), + OF_DEV_AUXDATA("fsl,imx6q-flexcan", 0x02094000, NULL, &flexcan_pdata[1]), + { /* sentinel */ } +}; + static void __init imx6sx_init_machine(void) { struct device *parent; @@ -24,7 +90,8 @@ static void __init imx6sx_init_machine(void) if (parent == NULL) pr_warn("failed to initialize soc device\n"); - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); + of_platform_populate(NULL, of_default_bus_match_table, + imx6sx_auxdata_lookup, parent); imx_anatop_init(); imx6sx_pm_init(); @@ -39,7 +106,7 @@ static void __init imx6sx_init_irq(void) irqchip_init(); } -static const char *imx6sx_dt_compat[] __initconst = { +static const char *imx6sx_dt_compat[] __initdata = { "fsl,imx6sx", NULL, }; -- 2.39.2