mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-27 18:41:56 +07:00
93340a2294
The maximum DPLL multiplier (M) values for OMAP2xxx and OMAP3xxx are one increment higher than they should be. See for example the OMAP242x TRM Rev X Section 5.10.6 "Clock Generator Registers" and the OMAP36xx TRM Rev C Table 3-202 "CM_CLKSEL1_PLL". Programming a 0 into the DPLL's M register bitfield is valid for OMAP2/3 and indicates that the DPLL should enter MN-bypass mode. Also, increase the minimum multiplier (M) value for the DPLL rate rounding code from 1 to 2, to ensure that it does not inadvertently put the DPLL into bypass. Note that the register documentation in the OMAP2xxx and OMAP3xxx TRMs does not make clear that the actual DPLL divider value (the "N") is the content of the appropriate register bitfield for the N value, _plus one_. (In other words, an N register bitfield of 0 indicates a DPLL divider value of 1.) This is only clearly documented in the OMAP4430 TRM, in, for example, OMAP4430 TRM Rev A Table 3-1167 "CM_CLKSEL_DPLL_USB". While here, update copyrights, add kerneldoc for struct dpll_data, drop the unused struct dpll_data.max_tolerance field, remove some unnecessary #includes in DPLL-related code, and replace the #include of <linux/module.h> with <linux/list.h>, which is what was really needed. The OMAP4 clock autogenerator script has been updated accordingly. Signed-off-by: Paul Walmsley <paul@pwsan.com> Cc: Benoît Cousson <b-cousson@ti.com> Cc: Rajendra Nayak <rnayak@ti.com>
218 lines
7.2 KiB
C
218 lines
7.2 KiB
C
/*
|
|
* OMAP clock: data structure definitions, function prototypes, shared macros
|
|
*
|
|
* Copyright (C) 2004-2005, 2008-2010 Nokia Corporation
|
|
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
|
|
* Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#ifndef __ARCH_ARM_OMAP_CLOCK_H
|
|
#define __ARCH_ARM_OMAP_CLOCK_H
|
|
|
|
#include <linux/list.h>
|
|
|
|
struct module;
|
|
struct clk;
|
|
struct clockdomain;
|
|
|
|
struct clkops {
|
|
int (*enable)(struct clk *);
|
|
void (*disable)(struct clk *);
|
|
void (*find_idlest)(struct clk *, void __iomem **,
|
|
u8 *, u8 *);
|
|
void (*find_companion)(struct clk *, void __iomem **,
|
|
u8 *);
|
|
};
|
|
|
|
#ifdef CONFIG_ARCH_OMAP2PLUS
|
|
|
|
struct clksel_rate {
|
|
u32 val;
|
|
u8 div;
|
|
u8 flags;
|
|
};
|
|
|
|
struct clksel {
|
|
struct clk *parent;
|
|
const struct clksel_rate *rates;
|
|
};
|
|
|
|
/**
|
|
* struct dpll_data - DPLL registers and integration data
|
|
* @mult_div1_reg: register containing the DPLL M and N bitfields
|
|
* @mult_mask: mask of the DPLL M bitfield in @mult_div1_reg
|
|
* @div1_mask: mask of the DPLL N bitfield in @mult_div1_reg
|
|
* @clk_bypass: struct clk pointer to the clock's bypass clock input
|
|
* @clk_ref: struct clk pointer to the clock's reference clock input
|
|
* @control_reg: register containing the DPLL mode bitfield
|
|
* @enable_mask: mask of the DPLL mode bitfield in @control_reg
|
|
* @rate_tolerance: maximum variance allowed from target rate (in Hz)
|
|
* @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
|
|
* @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
|
|
* @max_multiplier: maximum valid non-bypass multiplier value (actual)
|
|
* @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
|
|
* @min_divider: minimum valid non-bypass divider value (actual)
|
|
* @max_divider: maximum valid non-bypass divider value (actual)
|
|
* @modes: possible values of @enable_mask
|
|
* @autoidle_reg: register containing the DPLL autoidle mode bitfield
|
|
* @idlest_reg: register containing the DPLL idle status bitfield
|
|
* @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
|
|
* @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
|
|
* @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
|
|
* @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
|
|
* @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
|
|
* @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
|
|
* @flags: DPLL type/features (see below)
|
|
*
|
|
* Possible values for @flags:
|
|
* DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
|
|
* NO_DCO_SEL: don't program DCO (only for some J-type DPLLs)
|
|
|
|
* @freqsel_mask is only used on the OMAP34xx family and AM35xx.
|
|
*
|
|
* XXX Some DPLLs have multiple bypass inputs, so it's not technically
|
|
* correct to only have one @clk_bypass pointer.
|
|
*
|
|
* XXX @rate_tolerance should probably be deprecated - currently there
|
|
* don't seem to be any usecases for DPLL rounding that is not exact.
|
|
*
|
|
* XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
|
|
* @last_rounded_n) should be separated from the runtime-fixed fields
|
|
* and placed into a differenct structure, so that the runtime-fixed data
|
|
* can be placed into read-only space.
|
|
*/
|
|
struct dpll_data {
|
|
void __iomem *mult_div1_reg;
|
|
u32 mult_mask;
|
|
u32 div1_mask;
|
|
struct clk *clk_bypass;
|
|
struct clk *clk_ref;
|
|
void __iomem *control_reg;
|
|
u32 enable_mask;
|
|
unsigned int rate_tolerance;
|
|
unsigned long last_rounded_rate;
|
|
u16 last_rounded_m;
|
|
u16 max_multiplier;
|
|
u8 last_rounded_n;
|
|
u8 min_divider;
|
|
u8 max_divider;
|
|
u8 modes;
|
|
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
|
|
void __iomem *autoidle_reg;
|
|
void __iomem *idlest_reg;
|
|
u32 autoidle_mask;
|
|
u32 freqsel_mask;
|
|
u32 idlest_mask;
|
|
u8 auto_recal_bit;
|
|
u8 recal_en_bit;
|
|
u8 recal_st_bit;
|
|
u8 flags;
|
|
# endif
|
|
};
|
|
|
|
#endif
|
|
|
|
struct clk {
|
|
struct list_head node;
|
|
const struct clkops *ops;
|
|
const char *name;
|
|
int id;
|
|
struct clk *parent;
|
|
struct list_head children;
|
|
struct list_head sibling; /* node for children */
|
|
unsigned long rate;
|
|
__u32 flags;
|
|
void __iomem *enable_reg;
|
|
unsigned long (*recalc)(struct clk *);
|
|
int (*set_rate)(struct clk *, unsigned long);
|
|
long (*round_rate)(struct clk *, unsigned long);
|
|
void (*init)(struct clk *);
|
|
__u8 enable_bit;
|
|
__s8 usecount;
|
|
u8 fixed_div;
|
|
#ifdef CONFIG_ARCH_OMAP2PLUS
|
|
void __iomem *clksel_reg;
|
|
u32 clksel_mask;
|
|
const struct clksel *clksel;
|
|
struct dpll_data *dpll_data;
|
|
const char *clkdm_name;
|
|
struct clockdomain *clkdm;
|
|
#else
|
|
__u8 rate_offset;
|
|
__u8 src_offset;
|
|
#endif
|
|
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
|
|
struct dentry *dent; /* For visible tree hierarchy */
|
|
#endif
|
|
};
|
|
|
|
struct cpufreq_frequency_table;
|
|
|
|
struct clk_functions {
|
|
int (*clk_enable)(struct clk *clk);
|
|
void (*clk_disable)(struct clk *clk);
|
|
long (*clk_round_rate)(struct clk *clk, unsigned long rate);
|
|
int (*clk_set_rate)(struct clk *clk, unsigned long rate);
|
|
int (*clk_set_parent)(struct clk *clk, struct clk *parent);
|
|
void (*clk_allow_idle)(struct clk *clk);
|
|
void (*clk_deny_idle)(struct clk *clk);
|
|
void (*clk_disable_unused)(struct clk *clk);
|
|
#ifdef CONFIG_CPU_FREQ
|
|
void (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **);
|
|
void (*clk_exit_cpufreq_table)(struct cpufreq_frequency_table **);
|
|
#endif
|
|
};
|
|
|
|
extern int mpurate;
|
|
|
|
extern int clk_init(struct clk_functions *custom_clocks);
|
|
extern void clk_preinit(struct clk *clk);
|
|
extern int clk_register(struct clk *clk);
|
|
extern void clk_reparent(struct clk *child, struct clk *parent);
|
|
extern void clk_unregister(struct clk *clk);
|
|
extern void propagate_rate(struct clk *clk);
|
|
extern void recalculate_root_clocks(void);
|
|
extern unsigned long followparent_recalc(struct clk *clk);
|
|
extern void clk_enable_init_clocks(void);
|
|
unsigned long omap_fixed_divisor_recalc(struct clk *clk);
|
|
#ifdef CONFIG_CPU_FREQ
|
|
extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
|
extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
|
#endif
|
|
|
|
extern const struct clkops clkops_null;
|
|
|
|
/* Clock flags */
|
|
/* bit 0 is free */
|
|
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
|
|
/* bits 2-4 are free */
|
|
#define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */
|
|
/* bit 6 is free */
|
|
#define CLOCK_IDLE_CONTROL (1 << 7)
|
|
#define CLOCK_NO_IDLE_PARENT (1 << 8)
|
|
#define DELAYED_APP (1 << 9) /* Delay application of clock */
|
|
#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
|
|
#define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */
|
|
#define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */
|
|
#define CLOCK_IN_OMAP4430 (1 << 13)
|
|
#define ALWAYS_ENABLED (1 << 14)
|
|
/* bits 15-31 are currently free */
|
|
|
|
/* Clksel_rate flags */
|
|
#define DEFAULT_RATE (1 << 0)
|
|
#define RATE_IN_242X (1 << 1)
|
|
#define RATE_IN_243X (1 << 2)
|
|
#define RATE_IN_343X (1 << 3) /* rates common to all 343X */
|
|
#define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */
|
|
#define RATE_IN_36XX (1 << 5)
|
|
#define RATE_IN_4430 (1 << 6)
|
|
|
|
#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
|
|
|
|
|
|
#endif
|