summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/mach-imx6sx.c
diff options
context:
space:
mode:
authorDong Aisheng <b29396@freescale.com>2014-02-20 16:48:05 +0800
committerNitin Garg <nitin.garg@freescale.com>2015-09-17 08:58:48 -0500
commit2f5f47f9d5767a373399fbfb8f49434e3f4f805c (patch)
tree3ae223890553f3316caf70277887006d37e2dbcf /arch/arm/mach-imx/mach-imx6sx.c
parent5dab40a870203103cf41c0f233fb1b36a6ffa860 (diff)
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 <b29396@freescale.com> (cherry picked from commit a6e475caedb096c631f853b33e7787f2f7caff17)
Diffstat (limited to 'arch/arm/mach-imx/mach-imx6sx.c')
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c71
1 files 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 <linux/can/platform/flexcan.h>
+#include <linux/gpio.h>
#include <linux/irqchip.h>
+#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/pm_opp.h>
#include <asm/mach/arch.h>
@@ -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,
};