]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
3335786a SR |
2 | /* |
3 | * Copyright (C) 2015-2016 Marvell International Ltd. | |
3335786a SR |
4 | */ |
5 | ||
d678a59d | 6 | #include <common.h> |
f7ae49fc | 7 | #include <log.h> |
3335786a SR |
8 | #include <asm/io.h> |
9 | ||
4b8cb843 | 10 | #include "comphy_core.h" |
3335786a SR |
11 | |
12 | /* | |
13 | * comphy_mux_check_config() | |
14 | * description: this function passes over the COMPHY lanes and check if the type | |
15 | * is valid for specific lane. If the type is not valid, | |
16 | * the function update the struct and set the type of the lane as | |
2dbba240 | 17 | * COMPHY_TYPE_UNCONNECTED |
3335786a SR |
18 | */ |
19 | static void comphy_mux_check_config(struct comphy_mux_data *mux_data, | |
20 | struct comphy_map *comphy_map_data, int comphy_max_lanes) | |
21 | { | |
22 | struct comphy_mux_options *mux_opt; | |
23 | int lane, opt, valid; | |
24 | ||
25 | debug_enter(); | |
26 | ||
27 | for (lane = 0; lane < comphy_max_lanes; | |
28 | lane++, comphy_map_data++, mux_data++) { | |
6ecc0b1c | 29 | /* Don't check ignored COMPHYs */ |
2dbba240 | 30 | if (comphy_map_data->type == COMPHY_TYPE_IGNORE) |
6ecc0b1c SR |
31 | continue; |
32 | ||
3335786a SR |
33 | mux_opt = mux_data->mux_values; |
34 | for (opt = 0, valid = 0; opt < mux_data->max_lane_values; | |
35 | opt++, mux_opt++) { | |
36 | if (mux_opt->type == comphy_map_data->type) { | |
37 | valid = 1; | |
38 | break; | |
39 | } | |
40 | } | |
41 | if (valid == 0) { | |
42 | debug("lane number %d, had invalid type %d\n", | |
43 | lane, comphy_map_data->type); | |
44 | debug("set lane %d as type %d\n", lane, | |
2dbba240 IL |
45 | COMPHY_TYPE_UNCONNECTED); |
46 | comphy_map_data->type = COMPHY_TYPE_UNCONNECTED; | |
3335786a SR |
47 | } else { |
48 | debug("lane number %d, has type %d\n", | |
49 | lane, comphy_map_data->type); | |
50 | } | |
51 | } | |
52 | ||
53 | debug_exit(); | |
54 | } | |
55 | ||
56 | static u32 comphy_mux_get_mux_value(struct comphy_mux_data *mux_data, | |
57 | u32 type, int lane) | |
58 | { | |
59 | struct comphy_mux_options *mux_opt; | |
60 | int opt; | |
61 | u32 value = 0; | |
62 | ||
63 | debug_enter(); | |
64 | ||
65 | mux_opt = mux_data->mux_values; | |
66 | for (opt = 0 ; opt < mux_data->max_lane_values; opt++, mux_opt++) { | |
67 | if (mux_opt->type == type) { | |
68 | value = mux_opt->mux_value; | |
69 | break; | |
70 | } | |
71 | } | |
72 | ||
73 | debug_exit(); | |
74 | ||
75 | return value; | |
76 | } | |
77 | ||
78 | static void comphy_mux_reg_write(struct comphy_mux_data *mux_data, | |
79 | struct comphy_map *comphy_map_data, | |
80 | int comphy_max_lanes, | |
7586ac2b MB |
81 | void __iomem *selector_base, |
82 | const fdt32_t *mux_lane_order, u32 bitcount) | |
3335786a SR |
83 | { |
84 | u32 lane, value, offset, mask; | |
85 | ||
86 | debug_enter(); | |
87 | ||
88 | for (lane = 0; lane < comphy_max_lanes; | |
89 | lane++, comphy_map_data++, mux_data++) { | |
2dbba240 | 90 | if (comphy_map_data->type == COMPHY_TYPE_IGNORE) |
6ecc0b1c SR |
91 | continue; |
92 | ||
7586ac2b MB |
93 | /* |
94 | * if the order of nodes in selector base register is | |
95 | * nontrivial, use mapping from mux_lane_order | |
96 | */ | |
97 | if (mux_lane_order) | |
98 | offset = fdt32_to_cpu(mux_lane_order[lane]) * bitcount; | |
99 | else | |
100 | offset = lane * bitcount; | |
101 | ||
3335786a SR |
102 | mask = (((1 << bitcount) - 1) << offset); |
103 | value = (comphy_mux_get_mux_value(mux_data, | |
104 | comphy_map_data->type, | |
105 | lane) << offset); | |
106 | reg_set(selector_base, value, mask); | |
107 | } | |
108 | ||
109 | debug_exit(); | |
110 | } | |
111 | ||
112 | void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg, | |
113 | struct comphy_map *comphy_map_data, | |
114 | void __iomem *selector_base) | |
115 | { | |
116 | struct comphy_mux_data *mux_data; | |
7586ac2b | 117 | const fdt32_t *mux_lane_order; |
3335786a SR |
118 | u32 mux_bitcount; |
119 | u32 comphy_max_lanes; | |
120 | ||
121 | debug_enter(); | |
122 | ||
123 | comphy_max_lanes = chip_cfg->comphy_lanes_count; | |
124 | mux_data = chip_cfg->mux_data; | |
7586ac2b | 125 | mux_lane_order = chip_cfg->comphy_mux_lane_order; |
3335786a SR |
126 | mux_bitcount = chip_cfg->comphy_mux_bitcount; |
127 | ||
128 | /* check if the configuration is valid */ | |
129 | comphy_mux_check_config(mux_data, comphy_map_data, comphy_max_lanes); | |
130 | /* Init COMPHY selectors */ | |
131 | comphy_mux_reg_write(mux_data, comphy_map_data, comphy_max_lanes, | |
7586ac2b | 132 | selector_base, mux_lane_order, mux_bitcount); |
3335786a SR |
133 | |
134 | debug_exit(); | |
135 | } |