diff options
author | Dong Aisheng <b29396@freescale.com> | 2014-02-20 03:48:05 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:57:44 -0400 |
commit | 93a1ab5533c0fb9047d7ab91e516c450219a97a3 (patch) | |
tree | 30fb31ef8b3cfd1e337666d922d7588daa4976cc | |
parent | 80a72be45341c352bb178c83715ac4f3473893d7 (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>
-rw-r--r-- | arch/arm/mach-imx/mach-imx6sx.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 3aca0e0359a1..a0059960dd8b 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c | |||
@@ -7,11 +7,14 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/can/platform/flexcan.h> | ||
10 | #include <linux/clk-provider.h> | 11 | #include <linux/clk-provider.h> |
11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | #include <linux/gpio.h> | ||
12 | #include <linux/irqchip.h> | 14 | #include <linux/irqchip.h> |
13 | #include <linux/of.h> | 15 | #include <linux/of.h> |
14 | #include <linux/of_address.h> | 16 | #include <linux/of_address.h> |
17 | #include <linux/of_gpio.h> | ||
15 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
16 | #include <linux/opp.h> | 19 | #include <linux/opp.h> |
17 | #include <linux/phy.h> | 20 | #include <linux/phy.h> |
@@ -26,6 +29,62 @@ | |||
26 | #include "cpuidle.h" | 29 | #include "cpuidle.h" |
27 | #include "hardware.h" | 30 | #include "hardware.h" |
28 | 31 | ||
32 | static struct flexcan_platform_data flexcan_pdata[2]; | ||
33 | static int flexcan_en_gpio; | ||
34 | static int flexcan_stby_gpio; | ||
35 | static int flexcan0_en; | ||
36 | static int flexcan1_en; | ||
37 | static void mx6sx_flexcan_switch(void) | ||
38 | { | ||
39 | if (flexcan0_en || flexcan1_en) { | ||
40 | gpio_set_value_cansleep(flexcan_en_gpio, 0); | ||
41 | gpio_set_value_cansleep(flexcan_stby_gpio, 0); | ||
42 | gpio_set_value_cansleep(flexcan_en_gpio, 1); | ||
43 | gpio_set_value_cansleep(flexcan_stby_gpio, 1); | ||
44 | } else { | ||
45 | /* | ||
46 | * avoid to disable CAN xcvr if any of the CAN interfaces | ||
47 | * are down. XCRV will be disabled only if both CAN2 | ||
48 | * interfaces are DOWN. | ||
49 | */ | ||
50 | gpio_set_value_cansleep(flexcan_en_gpio, 0); | ||
51 | gpio_set_value_cansleep(flexcan_stby_gpio, 0); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static void imx6sx_arm2_flexcan0_switch(int enable) | ||
56 | { | ||
57 | flexcan0_en = enable; | ||
58 | mx6sx_flexcan_switch(); | ||
59 | } | ||
60 | |||
61 | static void imx6sx_arm2_flexcan1_switch(int enable) | ||
62 | { | ||
63 | flexcan1_en = enable; | ||
64 | mx6sx_flexcan_switch(); | ||
65 | } | ||
66 | |||
67 | static int __init imx6sx_arm2_flexcan_fixup(void) | ||
68 | { | ||
69 | struct device_node *np; | ||
70 | |||
71 | np = of_find_node_by_path("/soc/aips-bus@02000000/can@02090000"); | ||
72 | if (!np) | ||
73 | return -ENODEV; | ||
74 | |||
75 | flexcan_en_gpio = of_get_named_gpio(np, "trx-en-gpio", 0); | ||
76 | flexcan_stby_gpio = of_get_named_gpio(np, "trx-stby-gpio", 0); | ||
77 | if (gpio_is_valid(flexcan_en_gpio) && gpio_is_valid(flexcan_stby_gpio) && | ||
78 | !gpio_request_one(flexcan_en_gpio, GPIOF_DIR_OUT, "flexcan-trx-en") && | ||
79 | !gpio_request_one(flexcan_stby_gpio, GPIOF_DIR_OUT, "flexcan-trx-stby")) { | ||
80 | /* flexcan 0 & 1 are using the same GPIOs for transceiver */ | ||
81 | flexcan_pdata[0].transceiver_switch = imx6sx_arm2_flexcan0_switch; | ||
82 | flexcan_pdata[1].transceiver_switch = imx6sx_arm2_flexcan1_switch; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
29 | static void __init imx6sx_enet_clk_sel(void) | 88 | static void __init imx6sx_enet_clk_sel(void) |
30 | { | 89 | { |
31 | struct regmap *gpr; | 90 | struct regmap *gpr; |
@@ -87,6 +146,13 @@ static inline void imx6sx_enet_init(void) | |||
87 | imx6sx_enet_clk_sel(); | 146 | imx6sx_enet_clk_sel(); |
88 | } | 147 | } |
89 | 148 | ||
149 | /* Add auxdata to pass platform data */ | ||
150 | static const struct of_dev_auxdata imx6sx_auxdata_lookup[] __initconst = { | ||
151 | OF_DEV_AUXDATA("fsl,imx6q-flexcan", 0x02090000, NULL, &flexcan_pdata[0]), | ||
152 | OF_DEV_AUXDATA("fsl,imx6q-flexcan", 0x02094000, NULL, &flexcan_pdata[1]), | ||
153 | { /* sentinel */ } | ||
154 | }; | ||
155 | |||
90 | static void __init imx6sx_init_machine(void) | 156 | static void __init imx6sx_init_machine(void) |
91 | { | 157 | { |
92 | struct device *parent; | 158 | struct device *parent; |
@@ -97,7 +163,8 @@ static void __init imx6sx_init_machine(void) | |||
97 | if (parent == NULL) | 163 | if (parent == NULL) |
98 | pr_warn("failed to initialize soc device\n"); | 164 | pr_warn("failed to initialize soc device\n"); |
99 | 165 | ||
100 | of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); | 166 | of_platform_populate(NULL, of_default_bus_match_table, |
167 | imx6sx_auxdata_lookup, parent); | ||
101 | 168 | ||
102 | imx6sx_enet_init(); | 169 | imx6sx_enet_init(); |
103 | imx_anatop_init(); | 170 | imx_anatop_init(); |
@@ -119,6 +186,9 @@ static void __init imx6sx_init_late(void) | |||
119 | IMX6Q_GPR1_GINT_ASSERT); | 186 | IMX6Q_GPR1_GINT_ASSERT); |
120 | 187 | ||
121 | imx6q_cpuidle_init(); | 188 | imx6q_cpuidle_init(); |
189 | |||
190 | if (of_machine_is_compatible("fsl,imx6sx-17x17-arm2")) | ||
191 | imx6sx_arm2_flexcan_fixup(); | ||
122 | } | 192 | } |
123 | 193 | ||
124 | static void __init imx6sx_map_io(void) | 194 | static void __init imx6sx_map_io(void) |