1 /* $NetBSD: amdgpu_gpio_base.c,v 1.2 2021/12/18 23:45:04 riastradh Exp $ */ 2 3 /* 4 * Copyright 2012-15 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28 /* 29 * Pre-requisites: headers required by header of this unit 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: amdgpu_gpio_base.c,v 1.2 2021/12/18 23:45:04 riastradh Exp $"); 34 35 #include <linux/slab.h> 36 37 #include "dm_services.h" 38 39 #include "include/gpio_interface.h" 40 #include "include/gpio_service_interface.h" 41 #include "hw_gpio.h" 42 #include "hw_translate.h" 43 #include "hw_factory.h" 44 #include "gpio_service.h" 45 46 /* 47 * Post-requisites: headers required by this unit 48 */ 49 50 /* 51 * This unit 52 */ 53 54 /* 55 * @brief 56 * Public API 57 */ 58 59 enum gpio_result dal_gpio_open( 60 struct gpio *gpio, 61 enum gpio_mode mode) 62 { 63 return dal_gpio_open_ex(gpio, mode); 64 } 65 66 enum gpio_result dal_gpio_open_ex( 67 struct gpio *gpio, 68 enum gpio_mode mode) 69 { 70 if (gpio->pin) { 71 ASSERT_CRITICAL(false); 72 return GPIO_RESULT_ALREADY_OPENED; 73 } 74 75 // No action if allocation failed during gpio construct 76 if (!gpio->hw_container.ddc) { 77 ASSERT_CRITICAL(false); 78 return GPIO_RESULT_NON_SPECIFIC_ERROR; 79 } 80 gpio->mode = mode; 81 82 return dal_gpio_service_open(gpio); 83 } 84 85 enum gpio_result dal_gpio_get_value( 86 const struct gpio *gpio, 87 uint32_t *value) 88 { 89 if (!gpio->pin) { 90 BREAK_TO_DEBUGGER(); 91 return GPIO_RESULT_NULL_HANDLE; 92 } 93 94 return gpio->pin->funcs->get_value(gpio->pin, value); 95 } 96 97 enum gpio_result dal_gpio_set_value( 98 const struct gpio *gpio, 99 uint32_t value) 100 { 101 if (!gpio->pin) { 102 BREAK_TO_DEBUGGER(); 103 return GPIO_RESULT_NULL_HANDLE; 104 } 105 106 return gpio->pin->funcs->set_value(gpio->pin, value); 107 } 108 109 enum gpio_mode dal_gpio_get_mode( 110 const struct gpio *gpio) 111 { 112 return gpio->mode; 113 } 114 115 enum gpio_result dal_gpio_lock_pin( 116 struct gpio *gpio) 117 { 118 return dal_gpio_service_lock(gpio->service, gpio->id, gpio->en); 119 } 120 121 enum gpio_result dal_gpio_unlock_pin( 122 struct gpio *gpio) 123 { 124 return dal_gpio_service_unlock(gpio->service, gpio->id, gpio->en); 125 } 126 127 enum gpio_result dal_gpio_change_mode( 128 struct gpio *gpio, 129 enum gpio_mode mode) 130 { 131 if (!gpio->pin) { 132 BREAK_TO_DEBUGGER(); 133 return GPIO_RESULT_NULL_HANDLE; 134 } 135 136 return gpio->pin->funcs->change_mode(gpio->pin, mode); 137 } 138 139 enum gpio_id dal_gpio_get_id( 140 const struct gpio *gpio) 141 { 142 return gpio->id; 143 } 144 145 uint32_t dal_gpio_get_enum( 146 const struct gpio *gpio) 147 { 148 return gpio->en; 149 } 150 151 enum gpio_result dal_gpio_set_config( 152 struct gpio *gpio, 153 const struct gpio_config_data *config_data) 154 { 155 if (!gpio->pin) { 156 BREAK_TO_DEBUGGER(); 157 return GPIO_RESULT_NULL_HANDLE; 158 } 159 160 return gpio->pin->funcs->set_config(gpio->pin, config_data); 161 } 162 163 enum gpio_result dal_gpio_get_pin_info( 164 const struct gpio *gpio, 165 struct gpio_pin_info *pin_info) 166 { 167 return gpio->service->translate.funcs->id_to_offset( 168 gpio->id, gpio->en, pin_info) ? 169 GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA; 170 } 171 172 enum sync_source dal_gpio_get_sync_source( 173 const struct gpio *gpio) 174 { 175 switch (gpio->id) { 176 case GPIO_ID_GENERIC: 177 switch (gpio->en) { 178 case GPIO_GENERIC_A: 179 return SYNC_SOURCE_IO_GENERIC_A; 180 case GPIO_GENERIC_B: 181 return SYNC_SOURCE_IO_GENERIC_B; 182 case GPIO_GENERIC_C: 183 return SYNC_SOURCE_IO_GENERIC_C; 184 case GPIO_GENERIC_D: 185 return SYNC_SOURCE_IO_GENERIC_D; 186 case GPIO_GENERIC_E: 187 return SYNC_SOURCE_IO_GENERIC_E; 188 case GPIO_GENERIC_F: 189 return SYNC_SOURCE_IO_GENERIC_F; 190 default: 191 return SYNC_SOURCE_NONE; 192 } 193 break; 194 case GPIO_ID_SYNC: 195 switch (gpio->en) { 196 case GPIO_SYNC_HSYNC_A: 197 return SYNC_SOURCE_IO_HSYNC_A; 198 case GPIO_SYNC_VSYNC_A: 199 return SYNC_SOURCE_IO_VSYNC_A; 200 case GPIO_SYNC_HSYNC_B: 201 return SYNC_SOURCE_IO_HSYNC_B; 202 case GPIO_SYNC_VSYNC_B: 203 return SYNC_SOURCE_IO_VSYNC_B; 204 default: 205 return SYNC_SOURCE_NONE; 206 } 207 break; 208 case GPIO_ID_HPD: 209 switch (gpio->en) { 210 case GPIO_HPD_1: 211 return SYNC_SOURCE_IO_HPD1; 212 case GPIO_HPD_2: 213 return SYNC_SOURCE_IO_HPD2; 214 default: 215 return SYNC_SOURCE_NONE; 216 } 217 break; 218 case GPIO_ID_GSL: 219 switch (gpio->en) { 220 case GPIO_GSL_GENLOCK_CLOCK: 221 return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK; 222 case GPIO_GSL_GENLOCK_VSYNC: 223 return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC; 224 case GPIO_GSL_SWAPLOCK_A: 225 return SYNC_SOURCE_GSL_IO_SWAPLOCK_A; 226 case GPIO_GSL_SWAPLOCK_B: 227 return SYNC_SOURCE_GSL_IO_SWAPLOCK_B; 228 default: 229 return SYNC_SOURCE_NONE; 230 } 231 break; 232 default: 233 return SYNC_SOURCE_NONE; 234 } 235 } 236 237 enum gpio_pin_output_state dal_gpio_get_output_state( 238 const struct gpio *gpio) 239 { 240 return gpio->output_state; 241 } 242 243 struct hw_ddc *dal_gpio_get_ddc(struct gpio *gpio) 244 { 245 return gpio->hw_container.ddc; 246 } 247 248 struct hw_hpd *dal_gpio_get_hpd(struct gpio *gpio) 249 { 250 return gpio->hw_container.hpd; 251 } 252 253 struct hw_generic *dal_gpio_get_generic(struct gpio *gpio) 254 { 255 return gpio->hw_container.generic; 256 } 257 258 void dal_gpio_close( 259 struct gpio *gpio) 260 { 261 if (!gpio) 262 return; 263 264 dal_gpio_service_close(gpio->service, &gpio->pin); 265 266 gpio->mode = GPIO_MODE_UNKNOWN; 267 } 268 269 /* 270 * @brief 271 * Creation and destruction 272 */ 273 274 struct gpio *dal_gpio_create( 275 struct gpio_service *service, 276 enum gpio_id id, 277 uint32_t en, 278 enum gpio_pin_output_state output_state) 279 { 280 struct gpio *gpio = kzalloc(sizeof(struct gpio), GFP_KERNEL); 281 282 if (!gpio) { 283 ASSERT_CRITICAL(false); 284 return NULL; 285 } 286 287 gpio->service = service; 288 gpio->pin = NULL; 289 gpio->id = id; 290 gpio->en = en; 291 gpio->mode = GPIO_MODE_UNKNOWN; 292 gpio->output_state = output_state; 293 294 //initialize hw_container union based on id 295 switch (gpio->id) { 296 case GPIO_ID_DDC_DATA: 297 gpio->service->factory.funcs->init_ddc_data(&gpio->hw_container.ddc, service->ctx, id, en); 298 break; 299 case GPIO_ID_DDC_CLOCK: 300 gpio->service->factory.funcs->init_ddc_data(&gpio->hw_container.ddc, service->ctx, id, en); 301 break; 302 case GPIO_ID_GENERIC: 303 gpio->service->factory.funcs->init_generic(&gpio->hw_container.generic, service->ctx, id, en); 304 break; 305 case GPIO_ID_HPD: 306 gpio->service->factory.funcs->init_hpd(&gpio->hw_container.hpd, service->ctx, id, en); 307 break; 308 // TODO: currently gpio for sync and gsl does not get created, might need it later 309 case GPIO_ID_SYNC: 310 break; 311 case GPIO_ID_GSL: 312 break; 313 default: 314 ASSERT_CRITICAL(false); 315 gpio->pin = NULL; 316 } 317 318 return gpio; 319 } 320 321 void dal_gpio_destroy( 322 struct gpio **gpio) 323 { 324 if (!gpio || !*gpio) { 325 ASSERT_CRITICAL(false); 326 return; 327 } 328 329 switch ((*gpio)->id) { 330 case GPIO_ID_DDC_DATA: 331 kfree((*gpio)->hw_container.ddc); 332 (*gpio)->hw_container.ddc = NULL; 333 break; 334 case GPIO_ID_DDC_CLOCK: 335 //TODO: might want to change it to init_ddc_clock 336 kfree((*gpio)->hw_container.ddc); 337 (*gpio)->hw_container.ddc = NULL; 338 break; 339 case GPIO_ID_GENERIC: 340 kfree((*gpio)->hw_container.generic); 341 (*gpio)->hw_container.generic = NULL; 342 break; 343 case GPIO_ID_HPD: 344 kfree((*gpio)->hw_container.hpd); 345 (*gpio)->hw_container.hpd = NULL; 346 break; 347 // TODO: currently gpio for sync and gsl does not get created, might need it later 348 case GPIO_ID_SYNC: 349 break; 350 case GPIO_ID_GSL: 351 break; 352 default: 353 break; 354 } 355 356 kfree(*gpio); 357 358 *gpio = NULL; 359 } 360