cregit-Linux how code gets into the kernel

Release 4.16 drivers/clk/samsung/clk.c

/*
 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
 * Copyright (c) 2013 Linaro Ltd.
 * Author: Thomas Abraham <thomas.ab@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This file includes utility functions to register clocks to common
 * clock framework for Samsung platforms.
*/

#include <linux/slab.h>
#include <linux/clkdev.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>

#include "clk.h"

static LIST_HEAD(clock_reg_cache_list);


void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, unsigned int num_regs) { for (; num_regs > 0; --num_regs, ++rd) rd->value = readl(base + rd->offset); }

Contributors

PersonTokensPropCommitsCommitProp
Tomasz Figa45100.00%1100.00%
Total45100.00%1100.00%


void samsung_clk_restore(void __iomem *base, const struct samsung_clk_reg_dump *rd, unsigned int num_regs) { for (; num_regs > 0; --num_regs, ++rd) writel(rd->value, base + rd->offset); }

Contributors

PersonTokensPropCommitsCommitProp
Tomasz Figa46100.00%1100.00%
Total46100.00%1100.00%


struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( const unsigned long *rdump, unsigned long nr_rdump) { struct samsung_clk_reg_dump *rd; unsigned int i; rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL); if (!rd) return NULL; for (i = 0; i < nr_rdump; ++i) rd[i].offset = rdump[i]; return rd; }

Contributors

PersonTokensPropCommitsCommitProp
Tomasz Figa77100.00%2100.00%
Total77100.00%2100.00%

/* setup the essentials required to support clock lookup using ccf */
struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, void __iomem *base, unsigned long nr_clks) { struct samsung_clk_provider *ctx; int i; ctx = kzalloc(sizeof(struct samsung_clk_provider) + sizeof(*ctx->clk_data.hws) * nr_clks, GFP_KERNEL); if (!ctx) panic("could not allocate clock provider context.\n"); for (i = 0; i < nr_clks; ++i) ctx->clk_data.hws[i] = ERR_PTR(-ENOENT); ctx->reg_base = base; ctx->clk_data.num = nr_clks; spin_lock_init(&ctx->lock); return ctx; }

Contributors

PersonTokensPropCommitsCommitProp
Rahul Sharma3327.97%116.67%
Tomasz Figa2521.19%116.67%
Heiko Stübner2117.80%116.67%
Thomas Abraham1916.10%116.67%
Marek Szyprowski1613.56%116.67%
Sylwester Nawrocki43.39%116.67%
Total118100.00%6100.00%


void __init samsung_clk_of_add_provider(struct device_node *np, struct samsung_clk_provider *ctx) { if (np) { if (of_clk_add_hw_provider(np, of_clk_hw_onecell_get, &ctx->clk_data)) panic("could not register clk provider\n"); } }

Contributors

PersonTokensPropCommitsCommitProp
Sylwester Nawrocki2048.78%120.00%
Rahul Sharma1126.83%120.00%
Heiko Stübner717.07%120.00%
Marek Szyprowski24.88%120.00%
Thomas Abraham12.44%120.00%
Total41100.00%5100.00%

/* add a clock instance to the clock lookup table used for dt based lookup */
void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk_hw *clk_hw, unsigned int id) { if (id) ctx->clk_data.hws[id] = clk_hw; }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham2161.76%133.33%
Rahul Sharma926.47%133.33%
Marek Szyprowski411.76%133.33%
Total34100.00%3100.00%

/* register a list of aliases */
void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx, const struct samsung_clock_alias *list, unsigned int nr_clk) { struct clk_hw *clk_hw; unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { if (!list->id) { pr_err("%s: clock id missing for index %d\n", __func__, idx); continue; } clk_hw = ctx->clk_data.hws[list->id]; if (!clk_hw) { pr_err("%s: failed to find clock %d\n", __func__, list->id); continue; } ret = clk_hw_register_clkdev(clk_hw, list->alias, list->dev_name); if (ret) pr_err("%s: failed to register lookup %s\n", __func__, list->alias); } }

Contributors

PersonTokensPropCommitsCommitProp
Heiko Stübner11487.02%125.00%
Rahul Sharma96.87%125.00%
Marek Szyprowski75.34%125.00%
Uwe Kleine-König10.76%125.00%
Total131100.00%4100.00%

/* register a list of fixed clocks */
void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, const struct samsung_fixed_rate_clock *list, unsigned int nr_clk) { struct clk_hw *clk_hw; unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name, list->parent_name, list->flags, list->fixed_rate); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } samsung_clk_add_lookup(ctx, clk_hw, list->id); /* * Unconditionally add a clock lookup for the fixed rate clocks. * There are not many of these on any of Samsung platforms. */ ret = clk_hw_register_clkdev(clk_hw, list->name, NULL); if (ret) pr_err("%s: failed to register clock lookup for %s", __func__, list->name); } }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham11786.03%120.00%
Marek Szyprowski118.09%240.00%
Rahul Sharma75.15%120.00%
Uwe Kleine-König10.74%120.00%
Total136100.00%5100.00%

/* register a list of fixed factor clocks */
void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx, const struct samsung_fixed_factor_clock *list, unsigned int nr_clk) { struct clk_hw *clk_hw; unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_fixed_factor(ctx->dev, list->name, list->parent_name, list->flags, list->mult, list->div); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } samsung_clk_add_lookup(ctx, clk_hw, list->id); } }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham9284.40%120.00%
Marek Szyprowski98.26%240.00%
Rahul Sharma76.42%120.00%
Uwe Kleine-König10.92%120.00%
Total109100.00%5100.00%

/* register a list of mux clocks */
void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, const struct samsung_mux_clock *list, unsigned int nr_clk) { struct clk_hw *clk_hw; unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_mux(ctx->dev, list->name, list->parent_names, list->num_parents, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->mux_flags, &ctx->lock); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } samsung_clk_add_lookup(ctx, clk_hw, list->id); } }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham10983.85%120.00%
Rahul Sharma118.46%120.00%
Marek Szyprowski96.92%240.00%
Uwe Kleine-König10.77%120.00%
Total130100.00%5100.00%

/* register a list of div clocks */
void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, const struct samsung_div_clock *list, unsigned int nr_clk) { struct clk_hw *clk_hw; unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) clk_hw = clk_hw_register_divider_table(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->div_flags, list->table, &ctx->lock); else clk_hw = clk_hw_register_divider(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->shift, list->width, list->div_flags, &ctx->lock); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } samsung_clk_add_lookup(ctx, clk_hw, list->id); } }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham10557.38%116.67%
Heiko Stübner4826.23%116.67%
Rahul Sharma158.20%116.67%
Marek Szyprowski147.65%233.33%
Uwe Kleine-König10.55%116.67%
Total183100.00%6100.00%

/* register a list of gate clocks */
void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, const struct samsung_gate_clock *list, unsigned int nr_clk) { struct clk_hw *clk_hw; unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_gate(ctx->dev, list->name, list->parent_name, list->flags, ctx->reg_base + list->offset, list->bit_idx, list->gate_flags, &ctx->lock); if (IS_ERR(clk_hw)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } samsung_clk_add_lookup(ctx, clk_hw, list->id); } }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham10182.79%120.00%
Rahul Sharma119.02%120.00%
Marek Szyprowski97.38%240.00%
Uwe Kleine-König10.82%120.00%
Total122100.00%5100.00%

/* * obtain the clock speed of all external fixed clock sources from device * tree and register it */
void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, struct samsung_fixed_rate_clock *fixed_rate_clk, unsigned int nr_fixed_rate_clk, const struct of_device_id *clk_matches) { const struct of_device_id *match; struct device_node *clk_np; u32 freq; for_each_matching_node_and_match(clk_np, clk_matches, &match) { if (of_property_read_u32(clk_np, "clock-frequency", &freq)) continue; fixed_rate_clk[(unsigned long)match->data].fixed_rate = freq; } samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham7485.06%125.00%
Rahul Sharma1011.49%125.00%
Pankaj Dubey22.30%125.00%
Krzysztof Kozlowski11.15%125.00%
Total87100.00%4100.00%

/* utility function to get the rate of a specified clock */
unsigned long _get_rate(const char *clk_name) { struct clk *clk; clk = __clk_lookup(clk_name); if (!clk) { pr_err("%s: could not find clock %s\n", __func__, clk_name); return 0; } return clk_get_rate(clk); }

Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham4593.75%150.00%
Tomasz Figa36.25%150.00%
Total48100.00%2100.00%

#ifdef CONFIG_PM_SLEEP
static int samsung_clk_suspend(void) { struct samsung_clock_reg_cache *reg_cache; list_for_each_entry(reg_cache, &clock_reg_cache_list, node) samsung_clk_save(reg_cache->reg_base, reg_cache->rdump, reg_cache->rd_num); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Naveen Krishna Chatradhi39100.00%1100.00%
Total39100.00%1100.00%


static void samsung_clk_resume(void) { struct samsung_clock_reg_cache *reg_cache; list_for_each_entry(reg_cache, &clock_reg_cache_list, node) samsung_clk_restore(reg_cache->reg_base, reg_cache->rdump, reg_cache->rd_num); }

Contributors

PersonTokensPropCommitsCommitProp
Naveen Krishna Chatradhi36100.00%1100.00%
Total36100.00%1100.00%

static struct syscore_ops samsung_clk_syscore_ops = { .suspend = samsung_clk_suspend, .resume = samsung_clk_resume, };
void samsung_clk_sleep_init(void __iomem *reg_base, const unsigned long *rdump, unsigned long nr_rdump) { struct samsung_clock_reg_cache *reg_cache; reg_cache = kzalloc(sizeof(struct samsung_clock_reg_cache), GFP_KERNEL); if (!reg_cache) panic("could not allocate register reg_cache.\n"); reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); if (!reg_cache->rdump) panic("could not allocate register dump storage.\n"); if (list_empty(&clock_reg_cache_list)) register_syscore_ops(&samsung_clk_syscore_ops); reg_cache->reg_base = reg_base; reg_cache->rd_num = nr_rdump; list_add_tail(&reg_cache->node, &clock_reg_cache_list); }

Contributors

PersonTokensPropCommitsCommitProp
Naveen Krishna Chatradhi108100.00%1100.00%
Total108100.00%1100.00%

#else
void samsung_clk_sleep_init(void __iomem *reg_base, const unsigned long *rdump, unsigned long nr_rdump) {}

Contributors

PersonTokensPropCommitsCommitProp
Naveen Krishna Chatradhi19100.00%1100.00%
Total19100.00%1100.00%

#endif /* * Common function which registers plls, muxes, dividers and gates * for each CMU. It also add CMU register list to register cache. */
struct samsung_clk_provider * __init samsung_cmu_register_one( struct device_node *np, const struct samsung_cmu_info *cmu) { void __iomem *reg_base; struct samsung_clk_provider *ctx; reg_base = of_iomap(np, 0); if (!reg_base) { panic("%s: failed to map registers\n", __func__); return NULL; } ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); if (!ctx) { panic("%s: unable to allocate ctx\n", __func__); return ctx; } if (cmu->pll_clks) samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, reg_base); if (cmu->mux_clks) samsung_clk_register_mux(ctx, cmu->mux_clks, cmu->nr_mux_clks); if (cmu->div_clks) samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); if (cmu->gate_clks) samsung_clk_register_gate(ctx, cmu->gate_clks, cmu->nr_gate_clks); if (cmu->fixed_clks) samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, cmu->nr_fixed_clks); if (cmu->fixed_factor_clks) samsung_clk_register_fixed_factor(ctx, cmu->fixed_factor_clks, cmu->nr_fixed_factor_clks); if (cmu->clk_regs) samsung_clk_sleep_init(reg_base, cmu->clk_regs, cmu->nr_clk_regs); samsung_clk_of_add_provider(np, ctx); return ctx; }

Contributors

PersonTokensPropCommitsCommitProp
Naveen Krishna Chatradhi21292.17%240.00%
Chanwoo Choi166.96%120.00%
Krzysztof Kozlowski10.43%120.00%
Shailendra Verma10.43%120.00%
Total230100.00%5100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Thomas Abraham70038.85%14.55%
Naveen Krishna Chatradhi44524.69%29.09%
Tomasz Figa19610.88%418.18%
Heiko Stübner19110.60%313.64%
Rahul Sharma1236.83%14.55%
Marek Szyprowski814.50%29.09%
Sylwester Nawrocki241.33%14.55%
Chanwoo Choi160.89%14.55%
Stephen Boyd120.67%14.55%
Uwe Kleine-König60.33%14.55%
Pankaj Dubey50.28%29.09%
Krzysztof Kozlowski20.11%29.09%
Shailendra Verma10.06%14.55%
Total1802100.00%22100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.