| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | 4 | */ |
|---|
| 10 | 5 | |
|---|
| 11 | 6 | #include <linux/clk-provider.h> |
|---|
| .. | .. |
|---|
| 18 | 13 | #include <linux/syscore_ops.h> |
|---|
| 19 | 14 | |
|---|
| 20 | 15 | #include <asm/proc-fns.h> |
|---|
| 16 | + |
|---|
| 17 | +#include <dt-bindings/clock/at91.h> |
|---|
| 21 | 18 | |
|---|
| 22 | 19 | #include "pmc.h" |
|---|
| 23 | 20 | |
|---|
| .. | .. |
|---|
| 46 | 43 | return 0; |
|---|
| 47 | 44 | } |
|---|
| 48 | 45 | EXPORT_SYMBOL_GPL(of_at91_get_clk_range); |
|---|
| 46 | + |
|---|
| 47 | +struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data) |
|---|
| 48 | +{ |
|---|
| 49 | + unsigned int type = clkspec->args[0]; |
|---|
| 50 | + unsigned int idx = clkspec->args[1]; |
|---|
| 51 | + struct pmc_data *pmc_data = data; |
|---|
| 52 | + |
|---|
| 53 | + switch (type) { |
|---|
| 54 | + case PMC_TYPE_CORE: |
|---|
| 55 | + if (idx < pmc_data->ncore) |
|---|
| 56 | + return pmc_data->chws[idx]; |
|---|
| 57 | + break; |
|---|
| 58 | + case PMC_TYPE_SYSTEM: |
|---|
| 59 | + if (idx < pmc_data->nsystem) |
|---|
| 60 | + return pmc_data->shws[idx]; |
|---|
| 61 | + break; |
|---|
| 62 | + case PMC_TYPE_PERIPHERAL: |
|---|
| 63 | + if (idx < pmc_data->nperiph) |
|---|
| 64 | + return pmc_data->phws[idx]; |
|---|
| 65 | + break; |
|---|
| 66 | + case PMC_TYPE_GCK: |
|---|
| 67 | + if (idx < pmc_data->ngck) |
|---|
| 68 | + return pmc_data->ghws[idx]; |
|---|
| 69 | + break; |
|---|
| 70 | + case PMC_TYPE_PROGRAMMABLE: |
|---|
| 71 | + if (idx < pmc_data->npck) |
|---|
| 72 | + return pmc_data->pchws[idx]; |
|---|
| 73 | + break; |
|---|
| 74 | + default: |
|---|
| 75 | + break; |
|---|
| 76 | + } |
|---|
| 77 | + |
|---|
| 78 | + pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx); |
|---|
| 79 | + |
|---|
| 80 | + return ERR_PTR(-EINVAL); |
|---|
| 81 | +} |
|---|
| 82 | + |
|---|
| 83 | +struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem, |
|---|
| 84 | + unsigned int nperiph, unsigned int ngck, |
|---|
| 85 | + unsigned int npck) |
|---|
| 86 | +{ |
|---|
| 87 | + unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck; |
|---|
| 88 | + struct pmc_data *pmc_data; |
|---|
| 89 | + |
|---|
| 90 | + pmc_data = kzalloc(struct_size(pmc_data, hwtable, num_clks), |
|---|
| 91 | + GFP_KERNEL); |
|---|
| 92 | + if (!pmc_data) |
|---|
| 93 | + return NULL; |
|---|
| 94 | + |
|---|
| 95 | + pmc_data->ncore = ncore; |
|---|
| 96 | + pmc_data->chws = pmc_data->hwtable; |
|---|
| 97 | + |
|---|
| 98 | + pmc_data->nsystem = nsystem; |
|---|
| 99 | + pmc_data->shws = pmc_data->chws + ncore; |
|---|
| 100 | + |
|---|
| 101 | + pmc_data->nperiph = nperiph; |
|---|
| 102 | + pmc_data->phws = pmc_data->shws + nsystem; |
|---|
| 103 | + |
|---|
| 104 | + pmc_data->ngck = ngck; |
|---|
| 105 | + pmc_data->ghws = pmc_data->phws + nperiph; |
|---|
| 106 | + |
|---|
| 107 | + pmc_data->npck = npck; |
|---|
| 108 | + pmc_data->pchws = pmc_data->ghws + ngck; |
|---|
| 109 | + |
|---|
| 110 | + return pmc_data; |
|---|
| 111 | +} |
|---|
| 49 | 112 | |
|---|
| 50 | 113 | #ifdef CONFIG_PM |
|---|
| 51 | 114 | static struct regmap *pmcreg; |
|---|
| .. | .. |
|---|
| 201 | 264 | struct device_node *np; |
|---|
| 202 | 265 | |
|---|
| 203 | 266 | np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids); |
|---|
| 267 | + if (!np) |
|---|
| 268 | + return -ENODEV; |
|---|
| 204 | 269 | |
|---|
| 205 | | - pmcreg = syscon_node_to_regmap(np); |
|---|
| 270 | + if (!of_device_is_available(np)) { |
|---|
| 271 | + of_node_put(np); |
|---|
| 272 | + return -ENODEV; |
|---|
| 273 | + } |
|---|
| 274 | + |
|---|
| 275 | + pmcreg = device_node_to_regmap(np); |
|---|
| 276 | + of_node_put(np); |
|---|
| 206 | 277 | if (IS_ERR(pmcreg)) |
|---|
| 207 | 278 | return PTR_ERR(pmcreg); |
|---|
| 208 | 279 | |
|---|