1 /* 2 * Copyright (C) 2015-2016 Marvell International Ltd. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 10 #include "comphy.h" 11 #include "comphy_hpipe.h" 12 13 /* 14 * comphy_mux_check_config() 15 * description: this function passes over the COMPHY lanes and check if the type 16 * is valid for specific lane. If the type is not valid, 17 * the function update the struct and set the type of the lane as 18 * PHY_TYPE_UNCONNECTED 19 */ 20 static void comphy_mux_check_config(struct comphy_mux_data *mux_data, 21 struct comphy_map *comphy_map_data, int comphy_max_lanes) 22 { 23 struct comphy_mux_options *mux_opt; 24 int lane, opt, valid; 25 26 debug_enter(); 27 28 for (lane = 0; lane < comphy_max_lanes; 29 lane++, comphy_map_data++, mux_data++) { 30 /* Don't check ignored COMPHYs */ 31 if (comphy_map_data->type == PHY_TYPE_IGNORE) 32 continue; 33 34 mux_opt = mux_data->mux_values; 35 for (opt = 0, valid = 0; opt < mux_data->max_lane_values; 36 opt++, mux_opt++) { 37 if (mux_opt->type == comphy_map_data->type) { 38 valid = 1; 39 break; 40 } 41 } 42 if (valid == 0) { 43 debug("lane number %d, had invalid type %d\n", 44 lane, comphy_map_data->type); 45 debug("set lane %d as type %d\n", lane, 46 PHY_TYPE_UNCONNECTED); 47 comphy_map_data->type = PHY_TYPE_UNCONNECTED; 48 } else { 49 debug("lane number %d, has type %d\n", 50 lane, comphy_map_data->type); 51 } 52 } 53 54 debug_exit(); 55 } 56 57 static u32 comphy_mux_get_mux_value(struct comphy_mux_data *mux_data, 58 u32 type, int lane) 59 { 60 struct comphy_mux_options *mux_opt; 61 int opt; 62 u32 value = 0; 63 64 debug_enter(); 65 66 mux_opt = mux_data->mux_values; 67 for (opt = 0 ; opt < mux_data->max_lane_values; opt++, mux_opt++) { 68 if (mux_opt->type == type) { 69 value = mux_opt->mux_value; 70 break; 71 } 72 } 73 74 debug_exit(); 75 76 return value; 77 } 78 79 static void comphy_mux_reg_write(struct comphy_mux_data *mux_data, 80 struct comphy_map *comphy_map_data, 81 int comphy_max_lanes, 82 void __iomem *selector_base, u32 bitcount) 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++) { 90 if (comphy_map_data->type == PHY_TYPE_IGNORE) 91 continue; 92 93 offset = lane * bitcount; 94 mask = (((1 << bitcount) - 1) << offset); 95 value = (comphy_mux_get_mux_value(mux_data, 96 comphy_map_data->type, 97 lane) << offset); 98 reg_set(selector_base, value, mask); 99 } 100 101 debug_exit(); 102 } 103 104 void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg, 105 struct comphy_map *comphy_map_data, 106 void __iomem *selector_base) 107 { 108 struct comphy_mux_data *mux_data; 109 u32 mux_bitcount; 110 u32 comphy_max_lanes; 111 112 debug_enter(); 113 114 comphy_max_lanes = chip_cfg->comphy_lanes_count; 115 mux_data = chip_cfg->mux_data; 116 mux_bitcount = chip_cfg->comphy_mux_bitcount; 117 118 /* check if the configuration is valid */ 119 comphy_mux_check_config(mux_data, comphy_map_data, comphy_max_lanes); 120 /* Init COMPHY selectors */ 121 comphy_mux_reg_write(mux_data, comphy_map_data, comphy_max_lanes, 122 selector_base, mux_bitcount); 123 124 debug_exit(); 125 } 126