1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/of_gpio.h> 7 #include <linux/phy/phy.h> 8 9 #include <drm/drm_of.h> 10 #include <drm/drm_print.h> 11 #include <drm/drm_bridge.h> 12 13 #include "dp_parser.h" 14 #include "dp_reg.h" 15 16 #define DP_DEFAULT_AHB_OFFSET 0x0000 17 #define DP_DEFAULT_AHB_SIZE 0x0200 18 #define DP_DEFAULT_AUX_OFFSET 0x0200 19 #define DP_DEFAULT_AUX_SIZE 0x0200 20 #define DP_DEFAULT_LINK_OFFSET 0x0400 21 #define DP_DEFAULT_LINK_SIZE 0x0C00 22 #define DP_DEFAULT_P0_OFFSET 0x1000 23 #define DP_DEFAULT_P0_SIZE 0x0400 24 25 static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len) 26 { 27 struct resource *res; 28 void __iomem *base; 29 30 base = devm_platform_get_and_ioremap_resource(pdev, idx, &res); 31 if (!IS_ERR(base)) 32 *len = resource_size(res); 33 34 return base; 35 } 36 37 static int dp_parser_ctrl_res(struct dp_parser *parser) 38 { 39 struct platform_device *pdev = parser->pdev; 40 struct dp_io *io = &parser->io; 41 struct dss_io_data *dss = &io->dp_controller; 42 43 dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len); 44 if (IS_ERR(dss->ahb.base)) 45 return PTR_ERR(dss->ahb.base); 46 47 dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len); 48 if (IS_ERR(dss->aux.base)) { 49 /* 50 * The initial binding had a single reg, but in order to 51 * support variation in the sub-region sizes this was split. 52 * dp_ioremap() will fail with -EINVAL here if only a single 53 * reg is specified, so fill in the sub-region offsets and 54 * lengths based on this single region. 55 */ 56 if (PTR_ERR(dss->aux.base) == -EINVAL) { 57 if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { 58 DRM_ERROR("legacy memory region not large enough\n"); 59 return -EINVAL; 60 } 61 62 dss->ahb.len = DP_DEFAULT_AHB_SIZE; 63 dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET; 64 dss->aux.len = DP_DEFAULT_AUX_SIZE; 65 dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET; 66 dss->link.len = DP_DEFAULT_LINK_SIZE; 67 dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET; 68 dss->p0.len = DP_DEFAULT_P0_SIZE; 69 } else { 70 DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base); 71 return PTR_ERR(dss->aux.base); 72 } 73 } else { 74 dss->link.base = dp_ioremap(pdev, 2, &dss->link.len); 75 if (IS_ERR(dss->link.base)) { 76 DRM_ERROR("unable to remap link region: %pe\n", dss->link.base); 77 return PTR_ERR(dss->link.base); 78 } 79 80 dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len); 81 if (IS_ERR(dss->p0.base)) { 82 DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base); 83 return PTR_ERR(dss->p0.base); 84 } 85 } 86 87 io->phy = devm_phy_get(&pdev->dev, "dp"); 88 if (IS_ERR(io->phy)) 89 return PTR_ERR(io->phy); 90 91 return 0; 92 } 93 94 static int dp_parser_misc(struct dp_parser *parser) 95 { 96 struct device_node *of_node = parser->pdev->dev.of_node; 97 int len; 98 99 len = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES); 100 if (len < 0) { 101 DRM_WARN("Invalid property \"data-lanes\", default max DP lanes = %d\n", 102 DP_MAX_NUM_DP_LANES); 103 len = DP_MAX_NUM_DP_LANES; 104 } 105 106 parser->max_dp_lanes = len; 107 return 0; 108 } 109 110 static inline bool dp_parser_check_prefix(const char *clk_prefix, 111 const char *clk_name) 112 { 113 return !strncmp(clk_prefix, clk_name, strlen(clk_prefix)); 114 } 115 116 static int dp_parser_init_clk_data(struct dp_parser *parser) 117 { 118 int num_clk, i, rc; 119 int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0; 120 const char *clk_name; 121 struct device *dev = &parser->pdev->dev; 122 struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; 123 struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; 124 struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM]; 125 126 num_clk = of_property_count_strings(dev->of_node, "clock-names"); 127 if (num_clk <= 0) { 128 DRM_ERROR("no clocks are defined\n"); 129 return -EINVAL; 130 } 131 132 for (i = 0; i < num_clk; i++) { 133 rc = of_property_read_string_index(dev->of_node, 134 "clock-names", i, &clk_name); 135 if (rc < 0) 136 return rc; 137 138 if (dp_parser_check_prefix("core", clk_name)) 139 core_clk_count++; 140 141 if (dp_parser_check_prefix("ctrl", clk_name)) 142 ctrl_clk_count++; 143 144 if (dp_parser_check_prefix("stream", clk_name)) 145 stream_clk_count++; 146 } 147 148 /* Initialize the CORE power module */ 149 if (core_clk_count == 0) { 150 DRM_ERROR("no core clocks are defined\n"); 151 return -EINVAL; 152 } 153 154 core_power->num_clk = core_clk_count; 155 core_power->clocks = devm_kcalloc(dev, 156 core_power->num_clk, sizeof(struct clk_bulk_data), 157 GFP_KERNEL); 158 if (!core_power->clocks) 159 return -ENOMEM; 160 161 /* Initialize the CTRL power module */ 162 if (ctrl_clk_count == 0) { 163 DRM_ERROR("no ctrl clocks are defined\n"); 164 return -EINVAL; 165 } 166 167 ctrl_power->num_clk = ctrl_clk_count; 168 ctrl_power->clocks = devm_kcalloc(dev, 169 ctrl_power->num_clk, sizeof(struct clk_bulk_data), 170 GFP_KERNEL); 171 if (!ctrl_power->clocks) { 172 ctrl_power->num_clk = 0; 173 return -ENOMEM; 174 } 175 176 /* Initialize the STREAM power module */ 177 if (stream_clk_count == 0) { 178 DRM_ERROR("no stream (pixel) clocks are defined\n"); 179 return -EINVAL; 180 } 181 182 stream_power->num_clk = stream_clk_count; 183 stream_power->clocks = devm_kcalloc(dev, 184 stream_power->num_clk, sizeof(struct clk_bulk_data), 185 GFP_KERNEL); 186 if (!stream_power->clocks) { 187 stream_power->num_clk = 0; 188 return -ENOMEM; 189 } 190 191 return 0; 192 } 193 194 static int dp_parser_clock(struct dp_parser *parser) 195 { 196 int rc = 0, i = 0; 197 int num_clk = 0; 198 int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0; 199 int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0; 200 const char *clk_name; 201 struct device *dev = &parser->pdev->dev; 202 struct dss_module_power *core_power = &parser->mp[DP_CORE_PM]; 203 struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM]; 204 struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM]; 205 206 rc = dp_parser_init_clk_data(parser); 207 if (rc) { 208 DRM_ERROR("failed to initialize power data %d\n", rc); 209 return -EINVAL; 210 } 211 212 core_clk_count = core_power->num_clk; 213 ctrl_clk_count = ctrl_power->num_clk; 214 stream_clk_count = stream_power->num_clk; 215 216 num_clk = core_clk_count + ctrl_clk_count + stream_clk_count; 217 218 for (i = 0; i < num_clk; i++) { 219 rc = of_property_read_string_index(dev->of_node, "clock-names", 220 i, &clk_name); 221 if (rc) { 222 DRM_ERROR("error reading clock-names %d\n", rc); 223 return rc; 224 } 225 if (dp_parser_check_prefix("core", clk_name) && 226 core_clk_index < core_clk_count) { 227 core_power->clocks[core_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); 228 core_clk_index++; 229 } else if (dp_parser_check_prefix("stream", clk_name) && 230 stream_clk_index < stream_clk_count) { 231 stream_power->clocks[stream_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); 232 stream_clk_index++; 233 } else if (dp_parser_check_prefix("ctrl", clk_name) && 234 ctrl_clk_index < ctrl_clk_count) { 235 ctrl_power->clocks[ctrl_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL); 236 ctrl_clk_index++; 237 } 238 } 239 240 return 0; 241 } 242 243 int dp_parser_find_next_bridge(struct dp_parser *parser) 244 { 245 struct device *dev = &parser->pdev->dev; 246 struct drm_bridge *bridge; 247 248 bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); 249 if (IS_ERR(bridge)) 250 return PTR_ERR(bridge); 251 252 parser->next_bridge = bridge; 253 254 return 0; 255 } 256 257 static int dp_parser_parse(struct dp_parser *parser) 258 { 259 int rc = 0; 260 261 if (!parser) { 262 DRM_ERROR("invalid input\n"); 263 return -EINVAL; 264 } 265 266 rc = dp_parser_ctrl_res(parser); 267 if (rc) 268 return rc; 269 270 rc = dp_parser_misc(parser); 271 if (rc) 272 return rc; 273 274 rc = dp_parser_clock(parser); 275 if (rc) 276 return rc; 277 278 return 0; 279 } 280 281 struct dp_parser *dp_parser_get(struct platform_device *pdev) 282 { 283 struct dp_parser *parser; 284 285 parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL); 286 if (!parser) 287 return ERR_PTR(-ENOMEM); 288 289 parser->parse = dp_parser_parse; 290 parser->pdev = pdev; 291 292 return parser; 293 } 294