Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/tegra: dc: Use direct offset to plane registers

Traditionally, windows were accessed indirectly, through a register
selection window that required a global register to be programmed with
the index of the window to access. Since the global register could be
written from modesetting functions as well as the interrupt handler
concurrently, accesses had to be serialized using a lock. Using direct
accesses to the window registers the lock can be avoided.

Signed-off-by: Thierry Reding <treding@nvidia.com>

+116 -107
+91 -82
drivers/gpu/drm/tegra/dc.c
··· 34 34 stats->overflow = 0; 35 35 } 36 36 37 - /* 38 - * Reads the active copy of a register. This takes the dc->lock spinlock to 39 - * prevent races with the VBLANK processing which also needs access to the 40 - * active copy of some registers. 41 - */ 37 + /* Reads the active copy of a register. */ 42 38 static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset) 43 39 { 44 - unsigned long flags; 45 40 u32 value; 46 - 47 - spin_lock_irqsave(&dc->lock, flags); 48 41 49 42 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); 50 43 value = tegra_dc_readl(dc, offset); 51 44 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); 52 45 53 - spin_unlock_irqrestore(&dc->lock, flags); 54 46 return value; 47 + } 48 + 49 + static inline unsigned int tegra_plane_offset(struct tegra_plane *plane, 50 + unsigned int offset) 51 + { 52 + if (offset >= 0x500 && offset <= 0x638) { 53 + offset = 0x000 + (offset - 0x500); 54 + return plane->offset + offset; 55 + } 56 + 57 + if (offset >= 0x700 && offset <= 0x719) { 58 + offset = 0x180 + (offset - 0x700); 59 + return plane->offset + offset; 60 + } 61 + 62 + if (offset >= 0x800 && offset <= 0x839) { 63 + offset = 0x1c0 + (offset - 0x800); 64 + return plane->offset + offset; 65 + } 66 + 67 + dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset); 68 + 69 + return plane->offset + offset; 70 + } 71 + 72 + static inline u32 tegra_plane_readl(struct tegra_plane *plane, 73 + unsigned int offset) 74 + { 75 + return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset)); 76 + } 77 + 78 + static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value, 79 + unsigned int offset) 80 + { 81 + tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset)); 55 82 } 56 83 57 84 bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev) ··· 152 125 return dfixed_frac(inf); 153 126 } 154 127 155 - static void tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, 128 + static void tegra_dc_setup_window(struct tegra_plane *plane, 156 129 const struct tegra_dc_window *window) 157 130 { 158 131 unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; 159 - unsigned long value, flags; 132 + struct tegra_dc *dc = plane->dc; 160 133 bool yuv, planar; 134 + u32 value; 161 135 162 136 /* 163 137 * For YUV planar modes, the number of bytes per pixel takes into ··· 170 142 else 171 143 bpp = planar ? 1 : 2; 172 144 173 - spin_lock_irqsave(&dc->lock, flags); 174 - 175 - value = WINDOW_A_SELECT << index; 176 - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); 177 - 178 - tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH); 179 - tegra_dc_writel(dc, window->swap, DC_WIN_BYTE_SWAP); 145 + tegra_plane_writel(plane, window->format, DC_WIN_COLOR_DEPTH); 146 + tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP); 180 147 181 148 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x); 182 - tegra_dc_writel(dc, value, DC_WIN_POSITION); 149 + tegra_plane_writel(plane, value, DC_WIN_POSITION); 183 150 184 151 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w); 185 - tegra_dc_writel(dc, value, DC_WIN_SIZE); 152 + tegra_plane_writel(plane, value, DC_WIN_SIZE); 186 153 187 154 h_offset = window->src.x * bpp; 188 155 v_offset = window->src.y; ··· 185 162 v_size = window->src.h; 186 163 187 164 value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size); 188 - tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE); 165 + tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE); 189 166 190 167 /* 191 168 * For DDA computations the number of bytes per pixel for YUV planar ··· 198 175 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp); 199 176 200 177 value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda); 201 - tegra_dc_writel(dc, value, DC_WIN_DDA_INC); 178 + tegra_plane_writel(plane, value, DC_WIN_DDA_INC); 202 179 203 180 h_dda = compute_initial_dda(window->src.x); 204 181 v_dda = compute_initial_dda(window->src.y); 205 182 206 - tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA); 207 - tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA); 183 + tegra_plane_writel(plane, h_dda, DC_WIN_H_INITIAL_DDA); 184 + tegra_plane_writel(plane, v_dda, DC_WIN_V_INITIAL_DDA); 208 185 209 - tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE); 210 - tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE); 186 + tegra_plane_writel(plane, 0, DC_WIN_UV_BUF_STRIDE); 187 + tegra_plane_writel(plane, 0, DC_WIN_BUF_STRIDE); 211 188 212 - tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR); 189 + tegra_plane_writel(plane, window->base[0], DC_WINBUF_START_ADDR); 213 190 214 191 if (yuv && planar) { 215 - tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U); 216 - tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V); 192 + tegra_plane_writel(plane, window->base[1], DC_WINBUF_START_ADDR_U); 193 + tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V); 217 194 value = window->stride[1] << 16 | window->stride[0]; 218 - tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE); 195 + tegra_plane_writel(plane, value, DC_WIN_LINE_STRIDE); 219 196 } else { 220 - tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE); 197 + tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE); 221 198 } 222 199 223 200 if (window->bottom_up) 224 201 v_offset += window->src.h - 1; 225 202 226 - tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); 227 - tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); 203 + tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET); 204 + tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET); 228 205 229 206 if (dc->soc->supports_block_linear) { 230 207 unsigned long height = window->tiling.value; ··· 244 221 break; 245 222 } 246 223 247 - tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND); 224 + tegra_plane_writel(plane, value, DC_WINBUF_SURFACE_KIND); 248 225 } else { 249 226 switch (window->tiling.mode) { 250 227 case TEGRA_BO_TILING_MODE_PITCH: ··· 265 242 break; 266 243 } 267 244 268 - tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); 245 + tegra_plane_writel(plane, value, DC_WIN_BUFFER_ADDR_MODE); 269 246 } 270 247 271 248 value = WIN_ENABLE; 272 249 273 250 if (yuv) { 274 251 /* setup default colorspace conversion coefficients */ 275 - tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF); 276 - tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB); 277 - tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR); 278 - tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR); 279 - tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG); 280 - tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG); 281 - tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB); 282 - tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB); 252 + tegra_plane_writel(plane, 0x00f0, DC_WIN_CSC_YOF); 253 + tegra_plane_writel(plane, 0x012a, DC_WIN_CSC_KYRGB); 254 + tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KUR); 255 + tegra_plane_writel(plane, 0x0198, DC_WIN_CSC_KVR); 256 + tegra_plane_writel(plane, 0x039b, DC_WIN_CSC_KUG); 257 + tegra_plane_writel(plane, 0x032f, DC_WIN_CSC_KVG); 258 + tegra_plane_writel(plane, 0x0204, DC_WIN_CSC_KUB); 259 + tegra_plane_writel(plane, 0x0000, DC_WIN_CSC_KVB); 283 260 284 261 value |= CSC_ENABLE; 285 262 } else if (window->bits_per_pixel < 24) { ··· 289 266 if (window->bottom_up) 290 267 value |= V_DIRECTION; 291 268 292 - tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); 269 + tegra_plane_writel(plane, value, DC_WIN_WIN_OPTIONS); 293 270 294 271 /* 295 272 * Disable blending and assume Window A is the bottom-most window, 296 273 * Window C is the top-most window and Window B is in the middle. 297 274 */ 298 - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY); 299 - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN); 275 + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_NOKEY); 276 + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_1WIN); 300 277 301 - switch (index) { 278 + switch (plane->index) { 302 279 case 0: 303 - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X); 304 - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y); 305 - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY); 280 + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_X); 281 + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); 282 + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); 306 283 break; 307 284 308 285 case 1: 309 - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X); 310 - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y); 311 - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY); 286 + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); 287 + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_2WIN_Y); 288 + tegra_plane_writel(plane, 0x000000, DC_WIN_BLEND_3WIN_XY); 312 289 break; 313 290 314 291 case 2: 315 - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X); 316 - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y); 317 - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY); 292 + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_X); 293 + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_2WIN_Y); 294 + tegra_plane_writel(plane, 0xffff00, DC_WIN_BLEND_3WIN_XY); 318 295 break; 319 296 } 320 - 321 - spin_unlock_irqrestore(&dc->lock, flags); 322 297 } 323 298 324 299 static const u32 tegra20_primary_formats[] = { ··· 426 405 static void tegra_plane_atomic_disable(struct drm_plane *plane, 427 406 struct drm_plane_state *old_state) 428 407 { 429 - struct tegra_dc *dc = to_tegra_dc(old_state->crtc); 430 408 struct tegra_plane *p = to_tegra_plane(plane); 431 - unsigned long flags; 432 409 u32 value; 433 410 434 411 /* rien ne va plus */ 435 412 if (!old_state || !old_state->crtc) 436 413 return; 437 414 438 - spin_lock_irqsave(&dc->lock, flags); 439 - 440 - value = WINDOW_A_SELECT << p->index; 441 - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); 442 - 443 - value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); 415 + value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS); 444 416 value &= ~WIN_ENABLE; 445 - tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); 446 - 447 - spin_unlock_irqrestore(&dc->lock, flags); 417 + tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS); 448 418 } 449 419 450 420 static void tegra_plane_atomic_update(struct drm_plane *plane, 451 421 struct drm_plane_state *old_state) 452 422 { 453 423 struct tegra_plane_state *state = to_tegra_plane_state(plane->state); 454 - struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); 455 424 struct drm_framebuffer *fb = plane->state->fb; 456 425 struct tegra_plane *p = to_tegra_plane(plane); 457 426 struct tegra_dc_window window; ··· 485 474 window.stride[i] = fb->pitches[i]; 486 475 } 487 476 488 - tegra_dc_setup_window(dc, p->index, &window); 477 + tegra_dc_setup_window(p, &window); 489 478 } 490 479 491 480 static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = { ··· 520 509 if (!plane) 521 510 return ERR_PTR(-ENOMEM); 522 511 523 - num_formats = dc->soc->num_primary_formats; 524 - formats = dc->soc->primary_formats; 525 - 526 - /* 527 - * XXX compute offset so that we can directly access windows. 528 - * 529 - * Always use window A as primary window. 530 - */ 531 - plane->offset = 0; 512 + /* Always use window A as primary window */ 513 + plane->offset = 0xa00; 532 514 plane->index = 0; 533 515 plane->depth = 255; 516 + plane->dc = dc; 517 + 518 + num_formats = dc->soc->num_primary_formats; 519 + formats = dc->soc->primary_formats; 534 520 535 521 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, 536 522 &tegra_plane_funcs, formats, ··· 681 673 * need to special-casing the cursor plane. 682 674 */ 683 675 plane->index = 6; 676 + plane->dc = dc; 684 677 685 678 num_formats = ARRAY_SIZE(tegra_cursor_plane_formats); 686 679 formats = tegra_cursor_plane_formats; ··· 784 775 if (!plane) 785 776 return ERR_PTR(-ENOMEM); 786 777 787 - /* XXX compute offset so that we can directly access windows */ 788 - plane->offset = 0; 778 + plane->offset = 0xa00 + 0x200 * index; 789 779 plane->index = index; 790 780 plane->depth = 0; 781 + plane->dc = dc; 791 782 792 783 num_formats = dc->soc->num_overlay_formats; 793 784 formats = dc->soc->overlay_formats;
+21 -24
drivers/gpu/drm/tegra/hub.c
··· 49 49 DRM_FORMAT_YUV422, 50 50 }; 51 51 52 - static inline unsigned int tegra_plane_offset(struct tegra_shared_plane *plane, 52 + static inline unsigned int tegra_plane_offset(struct tegra_plane *plane, 53 53 unsigned int offset) 54 54 { 55 - struct tegra_plane *p = &plane->base; 56 - 57 55 if (offset >= 0x500 && offset <= 0x581) { 58 56 offset = 0x000 + (offset - 0x500); 59 - return p->offset + offset; 57 + return plane->offset + offset; 60 58 } 61 59 62 60 if (offset >= 0x700 && offset <= 0x73c) { 63 61 offset = 0x180 + (offset - 0x700); 64 - return p->offset + offset; 62 + return plane->offset + offset; 65 63 } 66 64 67 65 if (offset >= 0x800 && offset <= 0x83e) { 68 66 offset = 0x1c0 + (offset - 0x800); 69 - return p->offset + offset; 67 + return plane->offset + offset; 70 68 } 71 69 72 70 dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset); 73 71 74 - return p->offset + offset; 72 + return plane->offset + offset; 75 73 } 76 74 77 - static inline u32 tegra_plane_readl(struct tegra_shared_plane *plane, 75 + static inline u32 tegra_plane_readl(struct tegra_plane *plane, 78 76 unsigned int offset) 79 77 { 80 78 return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset)); 81 79 } 82 80 83 - static inline void tegra_plane_writel(struct tegra_shared_plane *plane, 84 - u32 value, unsigned int offset) 81 + static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value, 82 + unsigned int offset) 85 83 { 86 84 tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset)); 87 85 } ··· 153 155 } 154 156 } 155 157 156 - static void tegra_shared_plane_update(struct tegra_shared_plane *plane) 158 + static void tegra_shared_plane_update(struct tegra_plane *plane) 157 159 { 158 160 struct tegra_dc *dc = plane->dc; 159 161 unsigned long timeout; ··· 173 175 } 174 176 } 175 177 176 - static void tegra_shared_plane_activate(struct tegra_shared_plane *plane) 178 + static void tegra_shared_plane_activate(struct tegra_plane *plane) 177 179 { 178 180 struct tegra_dc *dc = plane->dc; 179 181 unsigned long timeout; ··· 194 196 } 195 197 196 198 static unsigned int 197 - tegra_shared_plane_get_owner(struct tegra_shared_plane *plane, 198 - struct tegra_dc *dc) 199 + tegra_shared_plane_get_owner(struct tegra_plane *plane, struct tegra_dc *dc) 199 200 { 200 201 unsigned int offset = 201 202 tegra_plane_offset(plane, DC_WIN_CORE_WINDOWGROUP_SET_CONTROL); ··· 203 206 } 204 207 205 208 static bool tegra_dc_owns_shared_plane(struct tegra_dc *dc, 206 - struct tegra_shared_plane *plane) 209 + struct tegra_plane *plane) 207 210 { 208 211 struct device *dev = dc->dev; 209 212 ··· 212 215 return true; 213 216 214 217 dev_WARN(dev, "head %u owns window %u but is not attached\n", 215 - dc->pipe, plane->base.index); 218 + dc->pipe, plane->index); 216 219 } 217 220 218 221 return false; 219 222 } 220 223 221 - static int tegra_shared_plane_set_owner(struct tegra_shared_plane *plane, 224 + static int tegra_shared_plane_set_owner(struct tegra_plane *plane, 222 225 struct tegra_dc *new) 223 226 { 224 227 unsigned int offset = 225 228 tegra_plane_offset(plane, DC_WIN_CORE_WINDOWGROUP_SET_CONTROL); 226 229 struct tegra_dc *old = plane->dc, *dc = new ? new : old; 227 230 struct device *dev = new ? new->dev : old->dev; 228 - unsigned int owner, index = plane->base.index; 231 + unsigned int owner, index = plane->index; 229 232 u32 value; 230 233 231 234 value = tegra_dc_readl(dc, offset); ··· 243 246 */ 244 247 if (old && owner == OWNER_MASK) 245 248 dev_dbg(dev, "window %u not owned by head %u but %u\n", index, 246 - old->pipe, owner); 249 + old->pipe, owner); 247 250 248 251 value &= ~OWNER_MASK; 249 252 ··· 260 263 } 261 264 262 265 static void tegra_dc_assign_shared_plane(struct tegra_dc *dc, 263 - struct tegra_shared_plane *plane) 266 + struct tegra_plane *plane) 264 267 { 265 268 u32 value; 266 269 int err; ··· 309 312 } 310 313 311 314 static void tegra_dc_remove_shared_plane(struct tegra_dc *dc, 312 - struct tegra_shared_plane *plane) 315 + struct tegra_plane *plane) 313 316 { 314 317 tegra_shared_plane_set_owner(plane, NULL); 315 318 } ··· 367 370 static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, 368 371 struct drm_plane_state *old_state) 369 372 { 370 - struct tegra_shared_plane *p = to_tegra_shared_plane(plane); 371 373 struct tegra_dc *dc = to_tegra_dc(old_state->crtc); 374 + struct tegra_plane *p = to_tegra_plane(plane); 372 375 u32 value; 373 376 374 377 /* rien ne va plus */ ··· 398 401 struct drm_plane_state *old_state) 399 402 { 400 403 struct tegra_plane_state *state = to_tegra_plane_state(plane->state); 401 - struct tegra_shared_plane *p = to_tegra_shared_plane(plane); 402 404 struct tegra_dc *dc = to_tegra_dc(plane->state->crtc); 403 405 struct drm_framebuffer *fb = plane->state->fb; 406 + struct tegra_plane *p = to_tegra_plane(plane); 404 407 struct tegra_bo *bo; 405 408 dma_addr_t base; 406 409 u32 value; ··· 431 434 BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC; 432 435 tegra_plane_writel(p, value, DC_WIN_BLEND_NOMATCH_SELECT); 433 436 434 - value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(p->base.depth); 437 + value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(p->depth); 435 438 tegra_plane_writel(p, value, DC_WIN_BLEND_LAYER_CONTROL); 436 439 437 440 /* bypass scaling */
-1
drivers/gpu/drm/tegra/hub.h
··· 28 28 struct tegra_shared_plane { 29 29 struct tegra_plane base; 30 30 struct tegra_windowgroup *wgrp; 31 - struct tegra_dc *dc; 32 31 }; 33 32 34 33 static inline struct tegra_shared_plane *
+2
drivers/gpu/drm/tegra/plane.h
··· 12 12 #include <drm/drm_plane.h> 13 13 14 14 struct tegra_bo; 15 + struct tegra_dc; 15 16 16 17 struct tegra_plane { 17 18 struct drm_plane base; 19 + struct tegra_dc *dc; 18 20 unsigned int offset; 19 21 unsigned int index; 20 22 unsigned int depth;
+2
drivers/gpu/drm/tegra/sor.c
··· 3047 3047 name, err); 3048 3048 goto remove; 3049 3049 } 3050 + } else { 3051 + sor->clk_out = sor->clk; 3050 3052 } 3051 3053 3052 3054 sor->clk_parent = devm_clk_get(&pdev->dev, "parent");