^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clk/at91_pmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "pmc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) DEFINE_SPINLOCK(pmc_pcr_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define PERIPHERAL_ID_MIN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define PERIPHERAL_ID_MAX 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PERIPHERAL_MAX_SHIFT 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct clk_peripheral {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct clk_sam9x5_peripheral {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct clk_range range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) spinlock_t *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) const struct clk_pcr_layout *layout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) bool auto_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int chg_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define to_clk_sam9x5_peripheral(hw) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) container_of(hw, struct clk_sam9x5_peripheral, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int clk_peripheral_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct clk_peripheral *periph = to_clk_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int offset = AT91_PMC_PCER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 id = periph->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (id > PERIPHERAL_ID_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) offset = AT91_PMC_PCER1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void clk_peripheral_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct clk_peripheral *periph = to_clk_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int offset = AT91_PMC_PCDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 id = periph->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (id > PERIPHERAL_ID_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) offset = AT91_PMC_PCDR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) regmap_write(periph->regmap, offset, PERIPHERAL_MASK(id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int clk_peripheral_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct clk_peripheral *periph = to_clk_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int offset = AT91_PMC_PCSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u32 id = periph->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (id > PERIPHERAL_ID_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) offset = AT91_PMC_PCSR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) regmap_read(periph->regmap, offset, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return status & PERIPHERAL_MASK(id) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static const struct clk_ops peripheral_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .enable = clk_peripheral_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .disable = clk_peripheral_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .is_enabled = clk_peripheral_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct clk_hw * __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) at91_clk_register_peripheral(struct regmap *regmap, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) const char *parent_name, u32 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct clk_peripheral *periph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (!name || !parent_name || id > PERIPHERAL_ID_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) periph = kzalloc(sizeof(*periph), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (!periph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) init.ops = &peripheral_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) init.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) periph->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) periph->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) periph->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) hw = &periph->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ret = clk_hw_register(NULL, &periph->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) kfree(periph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) hw = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct clk_hw *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned long parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!periph->auto_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (periph->range.max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) parent = clk_hw_get_parent_by_index(&periph->hw, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (!parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (parent_rate >> shift <= periph->range.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) periph->auto_div = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) periph->div = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (periph->id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) spin_lock_irqsave(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) regmap_write(periph->regmap, periph->layout->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) (periph->id & periph->layout->pid_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) regmap_update_bits(periph->regmap, periph->layout->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) periph->layout->div_mask | periph->layout->cmd |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) AT91_PMC_PCR_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) field_prep(periph->layout->div_mask, periph->div) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) periph->layout->cmd |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) AT91_PMC_PCR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) spin_unlock_irqrestore(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (periph->id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) spin_lock_irqsave(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) regmap_write(periph->regmap, periph->layout->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) (periph->id & periph->layout->pid_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) regmap_update_bits(periph->regmap, periph->layout->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) AT91_PMC_PCR_EN | periph->layout->cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) periph->layout->cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) spin_unlock_irqrestore(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (periph->id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_lock_irqsave(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) regmap_write(periph->regmap, periph->layout->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (periph->id & periph->layout->pid_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) regmap_read(periph->regmap, periph->layout->offset, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) spin_unlock_irqrestore(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return !!(status & AT91_PMC_PCR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (periph->id < PERIPHERAL_ID_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) spin_lock_irqsave(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) regmap_write(periph->regmap, periph->layout->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) (periph->id & periph->layout->pid_mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) regmap_read(periph->regmap, periph->layout->offset, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) spin_unlock_irqrestore(periph->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (status & AT91_PMC_PCR_EN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) periph->div = field_get(periph->layout->div_mask, status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) periph->auto_div = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) clk_sam9x5_peripheral_autodiv(periph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return parent_rate >> periph->div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static void clk_sam9x5_peripheral_best_diff(struct clk_rate_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct clk_hw *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) u32 shift, long *best_diff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) long *best_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) unsigned long tmp_rate = parent_rate >> shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned long tmp_diff = abs(req->rate - tmp_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (*best_diff < 0 || *best_diff >= tmp_diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *best_rate = tmp_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *best_diff = tmp_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) req->best_parent_rate = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) req->best_parent_hw = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int clk_sam9x5_peripheral_determine_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct clk_hw *parent = clk_hw_get_parent(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct clk_rate_request req_parent = *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) unsigned long parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned long tmp_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) long best_rate = LONG_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) long best_diff = LONG_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u32 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Fist step: check the available dividers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) tmp_rate = parent_rate >> shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (periph->range.max && tmp_rate > periph->range.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) clk_sam9x5_peripheral_best_diff(req, parent, parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) shift, &best_diff, &best_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (!best_diff || best_rate <= req->rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (periph->chg_pid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Step two: try to request rate from parent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) parent = clk_hw_get_parent_by_index(hw, periph->chg_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) req_parent.rate = req->rate << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (__clk_determine_rate(parent, &req_parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) clk_sam9x5_peripheral_best_diff(req, parent, req_parent.rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) shift, &best_diff, &best_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (!best_diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (best_rate < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) (periph->range.max && best_rate > periph->range.max))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) pr_debug("PCK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) __func__, best_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) __clk_get_name((req->best_parent_hw)->clk),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) req->best_parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) req->rate = best_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) unsigned long best_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) unsigned long best_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) unsigned long cur_rate = *parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) unsigned long cur_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return *parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (periph->range.max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) cur_rate = *parent_rate >> shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (cur_rate <= periph->range.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (rate >= cur_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return cur_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) best_diff = cur_rate - rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) best_rate = cur_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) cur_rate = *parent_rate >> shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (cur_rate < rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) cur_diff = rate - cur_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) cur_diff = cur_rate - rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (cur_diff < best_diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) best_diff = cur_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) best_rate = cur_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!best_diff || cur_rate < rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return best_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (parent_rate == rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (periph->range.max && rate > periph->range.max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (parent_rate >> shift == rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) periph->auto_div = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) periph->div = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static const struct clk_ops sam9x5_peripheral_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .enable = clk_sam9x5_peripheral_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .disable = clk_sam9x5_peripheral_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .is_enabled = clk_sam9x5_peripheral_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .round_rate = clk_sam9x5_peripheral_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .set_rate = clk_sam9x5_peripheral_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static const struct clk_ops sam9x5_peripheral_chg_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .enable = clk_sam9x5_peripheral_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .disable = clk_sam9x5_peripheral_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .is_enabled = clk_sam9x5_peripheral_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .determine_rate = clk_sam9x5_peripheral_determine_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .set_rate = clk_sam9x5_peripheral_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct clk_hw * __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) const struct clk_pcr_layout *layout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) const char *name, const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) u32 id, const struct clk_range *range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int chg_pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct clk_sam9x5_peripheral *periph;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (!name || !parent_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) periph = kzalloc(sizeof(*periph), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!periph)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) init.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (chg_pid < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) init.ops = &sam9x5_peripheral_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) CLK_SET_RATE_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) init.ops = &sam9x5_peripheral_chg_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) periph->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) periph->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) periph->div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) periph->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) periph->lock = lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (layout->div_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) periph->auto_div = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) periph->layout = layout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) periph->range = *range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) periph->chg_pid = chg_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) hw = &periph->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ret = clk_hw_register(NULL, &periph->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) kfree(periph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) hw = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) clk_sam9x5_peripheral_autodiv(periph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) pmc_register_id(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }