diff options
Diffstat (limited to 'include/linux/clk')
| -rw-r--r-- | include/linux/clk/at91_pmc.h | 200 | ||||
| -rw-r--r-- | include/linux/clk/bcm2835.h | 24 | ||||
| -rw-r--r-- | include/linux/clk/clk-conf.h | 22 | ||||
| -rw-r--r-- | include/linux/clk/gdsc.h | 22 | ||||
| -rw-r--r-- | include/linux/clk/msm-clk-provider.h | 270 | ||||
| -rw-r--r-- | include/linux/clk/msm-clk.h | 138 | ||||
| -rw-r--r-- | include/linux/clk/msm-clock-generic.h | 323 | ||||
| -rw-r--r-- | include/linux/clk/mxs.h | 14 | ||||
| -rw-r--r-- | include/linux/clk/shmobile.h | 35 | ||||
| -rw-r--r-- | include/linux/clk/tegra.h | 124 | ||||
| -rw-r--r-- | include/linux/clk/ti.h | 308 | ||||
| -rw-r--r-- | include/linux/clk/zynq.h | 30 |
12 files changed, 1510 insertions, 0 deletions
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h new file mode 100644 index 000000000000..1e6932222e11 --- /dev/null +++ b/include/linux/clk/at91_pmc.h @@ -0,0 +1,200 @@ +/* + * include/linux/clk/at91_pmc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Power Management Controller (PMC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91_PMC_H +#define AT91_PMC_H + +#ifndef __ASSEMBLY__ +extern void __iomem *at91_pmc_base; + +#define at91_pmc_read(field) \ + readl_relaxed(at91_pmc_base + field) + +#define at91_pmc_write(field, value) \ + writel_relaxed(value, at91_pmc_base + field) +#else +.extern at91_pmc_base +#endif + +#define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ +#define AT91_PMC_SCDR 0x04 /* System Clock Disable Register */ + +#define AT91_PMC_SCSR 0x08 /* System Clock Status Register */ +#define AT91_PMC_PCK (1 << 0) /* Processor Clock */ +#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */ +#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */ +#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */ +#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */ +#define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */ +#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_PCK4 (1 << 12) /* Programmable Clock 4 [AT572D940HF only] */ +#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ +#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ + +#define AT91_PMC_PCER 0x10 /* Peripheral Clock Enable Register */ +#define AT91_PMC_PCDR 0x14 /* Peripheral Clock Disable Register */ +#define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */ + +#define AT91_CKGR_UCKR 0x1C /* UTMI Clock Register [some SAM9] */ +#define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */ +#define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */ +#define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */ +#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */ + +#define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */ +#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ +#define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass */ +#define AT91_PMC_MOSCRCEN (1 << 3) /* Main On-Chip RC Oscillator Enable [some SAM9] */ +#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */ +#define AT91_PMC_KEY (0x37 << 16) /* MOR Writing Key */ +#define AT91_PMC_MOSCSEL (1 << 24) /* Main Oscillator Selection [some SAM9] */ +#define AT91_PMC_CFDEN (1 << 25) /* Clock Failure Detector Enable [some SAM9] */ + +#define AT91_CKGR_MCFR 0x24 /* Main Clock Frequency Register */ +#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */ +#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ + +#define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ +#define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ +#define AT91_PMC_DIV (0xff << 0) /* Divider */ +#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ +#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ +#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ +#define AT91_PMC_MUL_GET(n) ((n) >> 16 & 0x7ff) +#define AT91_PMC3_MUL (0x7f << 18) /* PLL Multiplier [SAMA5 only] */ +#define AT91_PMC3_MUL_GET(n) ((n) >> 18 & 0x7f) +#define AT91_PMC_USBDIV (3 << 28) /* USB Divisor (PLLB only) */ +#define AT91_PMC_USBDIV_1 (0 << 28) +#define AT91_PMC_USBDIV_2 (1 << 28) +#define AT91_PMC_USBDIV_4 (2 << 28) +#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */ + +#define AT91_PMC_MCKR 0x30 /* Master Clock Register */ +#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */ +#define AT91_PMC_CSS_SLOW (0 << 0) +#define AT91_PMC_CSS_MAIN (1 << 0) +#define AT91_PMC_CSS_PLLA (2 << 0) +#define AT91_PMC_CSS_PLLB (3 << 0) +#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */ +#define PMC_PRES_OFFSET 2 +#define AT91_PMC_PRES (7 << PMC_PRES_OFFSET) /* Master Clock Prescaler */ +#define AT91_PMC_PRES_1 (0 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_2 (1 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_4 (2 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_8 (3 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_16 (4 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_32 (5 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_64 (6 << PMC_PRES_OFFSET) +#define PMC_ALT_PRES_OFFSET 4 +#define AT91_PMC_ALT_PRES (7 << PMC_ALT_PRES_OFFSET) /* Master Clock Prescaler [alternate location] */ +#define AT91_PMC_ALT_PRES_1 (0 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_2 (1 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_4 (2 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_8 (3 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_16 (4 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_32 (5 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_64 (6 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */ +#define AT91RM9200_PMC_MDIV_1 (0 << 8) /* [AT91RM9200 only] */ +#define AT91RM9200_PMC_MDIV_2 (1 << 8) +#define AT91RM9200_PMC_MDIV_3 (2 << 8) +#define AT91RM9200_PMC_MDIV_4 (3 << 8) +#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9 only] */ +#define AT91SAM9_PMC_MDIV_2 (1 << 8) +#define AT91SAM9_PMC_MDIV_4 (2 << 8) +#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */ +#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */ +#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */ +#define AT91_PMC_PDIV_1 (0 << 12) +#define AT91_PMC_PDIV_2 (1 << 12) +#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */ +#define AT91_PMC_PLLADIV2_OFF (0 << 12) +#define AT91_PMC_PLLADIV2_ON (1 << 12) +#define AT91_PMC_H32MXDIV BIT(24) + +#define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */ +#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */ +#define AT91_PMC_USBS_PLLA (0 << 0) +#define AT91_PMC_USBS_UPLL (1 << 0) +#define AT91_PMC_USBS_PLLB (1 << 0) /* [AT91SAMN12 only] */ +#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */ +#define AT91_PMC_OHCIUSBDIV_1 (0x0 << 8) +#define AT91_PMC_OHCIUSBDIV_2 (0x1 << 8) + +#define AT91_PMC_SMD 0x3c /* Soft Modem Clock Register [some SAM9 only] */ +#define AT91_PMC_SMDS (0x1 << 0) /* SMD input clock selection */ +#define AT91_PMC_SMD_DIV (0x1f << 8) /* SMD input clock divider */ +#define AT91_PMC_SMDDIV(n) (((n) << 8) & AT91_PMC_SMD_DIV) + +#define AT91_PMC_PCKR(n) (0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */ +#define AT91_PMC_ALT_PCKR_CSS (0x7 << 0) /* Programmable Clock Source Selection [alternate length] */ +#define AT91_PMC_CSS_MASTER (4 << 0) /* [some SAM9 only] */ +#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */ +#define AT91_PMC_CSSMCK_CSS (0 << 8) +#define AT91_PMC_CSSMCK_MCK (1 << 8) + +#define AT91_PMC_IER 0x60 /* Interrupt Enable Register */ +#define AT91_PMC_IDR 0x64 /* Interrupt Disable Register */ +#define AT91_PMC_SR 0x68 /* Status Register */ +#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */ +#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */ +#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */ +#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */ +#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9] */ +#define AT91_PMC_OSCSEL (1 << 7) /* Slow Oscillator Selection [some SAM9] */ +#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */ +#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */ +#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */ +#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */ +#define AT91_PMC_MOSCSELS (1 << 16) /* Main Oscillator Selection [some SAM9] */ +#define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */ +#define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ +#define AT91_PMC_GCKRDY (1 << 24) /* Generated Clocks */ +#define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ + +#define AT91_PMC_PLLICPR 0x80 /* PLL Charge Pump Current Register */ + +#define AT91_PMC_PROT 0xe4 /* Write Protect Mode Register [some SAM9] */ +#define AT91_PMC_WPEN (0x1 << 0) /* Write Protect Enable */ +#define AT91_PMC_WPKEY (0xffffff << 8) /* Write Protect Key */ +#define AT91_PMC_PROTKEY (0x504d43 << 8) /* Activation Code */ + +#define AT91_PMC_WPSR 0xe8 /* Write Protect Status Register [some SAM9] */ +#define AT91_PMC_WPVS (0x1 << 0) /* Write Protect Violation Status */ +#define AT91_PMC_WPVSRC (0xffff << 8) /* Write Protect Violation Source */ + +#define AT91_PMC_PCER1 0x100 /* Peripheral Clock Enable Register 1 [SAMA5 only]*/ +#define AT91_PMC_PCDR1 0x104 /* Peripheral Clock Enable Register 1 */ +#define AT91_PMC_PCSR1 0x108 /* Peripheral Clock Enable Register 1 */ + +#define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9 and SAMA5] */ +#define AT91_PMC_PCR_PID_MASK 0x3f +#define AT91_PMC_PCR_GCKCSS_OFFSET 8 +#define AT91_PMC_PCR_GCKCSS_MASK (0x7 << AT91_PMC_PCR_GCKCSS_OFFSET) +#define AT91_PMC_PCR_GCKCSS(n) ((n) << AT91_PMC_PCR_GCKCSS_OFFSET) /* GCK Clock Source Selection */ +#define AT91_PMC_PCR_CMD (0x1 << 12) /* Command (read=0, write=1) */ +#define AT91_PMC_PCR_DIV_OFFSET 16 +#define AT91_PMC_PCR_DIV_MASK (0x3 << AT91_PMC_PCR_DIV_OFFSET) +#define AT91_PMC_PCR_DIV(n) ((n) << AT91_PMC_PCR_DIV_OFFSET) /* Divisor Value */ +#define AT91_PMC_PCR_GCKDIV_OFFSET 20 +#define AT91_PMC_PCR_GCKDIV_MASK (0xff << AT91_PMC_PCR_GCKDIV_OFFSET) +#define AT91_PMC_PCR_GCKDIV(n) ((n) << AT91_PMC_PCR_GCKDIV_OFFSET) /* Generated Clock Divisor Value */ +#define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ +#define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */ + +#endif diff --git a/include/linux/clk/bcm2835.h b/include/linux/clk/bcm2835.h new file mode 100644 index 000000000000..aa937f6c17da --- /dev/null +++ b/include/linux/clk/bcm2835.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2010 Broadcom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_CLK_BCM2835_H_ +#define __LINUX_CLK_BCM2835_H_ + +void __init bcm2835_init_clocks(void); + +#endif diff --git a/include/linux/clk/clk-conf.h b/include/linux/clk/clk-conf.h new file mode 100644 index 000000000000..e0c362363c38 --- /dev/null +++ b/include/linux/clk/clk-conf.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co., Ltd. + * Sylwester Nawrocki <s.nawrocki@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. + */ + +#include <linux/types.h> + +struct device_node; + +#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) +int of_clk_set_defaults(struct device_node *node, bool clk_supplier); +#else +static inline int of_clk_set_defaults(struct device_node *node, + bool clk_supplier) +{ + return 0; +} +#endif diff --git a/include/linux/clk/gdsc.h b/include/linux/clk/gdsc.h new file mode 100644 index 000000000000..b012ed06d3f4 --- /dev/null +++ b/include/linux/clk/gdsc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __GDSC_H +#define __GDSC_H + +#include <linux/regulator/consumer.h> + +/* Allow the clock memories to be turned off */ +void gdsc_allow_clear_retention(struct regulator *regulator); + +#endif diff --git a/include/linux/clk/msm-clk-provider.h b/include/linux/clk/msm-clk-provider.h new file mode 100644 index 000000000000..2fa8916ad356 --- /dev/null +++ b/include/linux/clk/msm-clk-provider.h @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007-2016, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MSM_CLK_PROVIDER_H +#define __MSM_CLK_PROVIDER_H + +#include <linux/types.h> +#include <linux/err.h> +#include <linux/list.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/device.h> +#include <linux/spinlock.h> +#include <linux/platform_device.h> +#include <linux/mutex.h> +#include <linux/regulator/consumer.h> +#include <linux/seq_file.h> +#include <linux/clk/msm-clk.h> + +#if defined(CONFIG_COMMON_CLK_MSM) +/* + * Bit manipulation macros + */ +#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb) +#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb)) + +/* + * Halt/Status Checking Mode Macros + */ +#define HALT 0 /* Bit pol: 1 = halted */ +#define NOCHECK 1 /* No bit to check, do nothing */ +#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */ +#define ENABLE 3 /* Bit pol: 1 = running */ +#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */ +#define DELAY 5 /* No bit to check, just delay */ + +struct clk_register_data { + char *name; + u32 offset; +}; +#ifdef CONFIG_DEBUG_FS +void clk_debug_print_hw(struct clk *clk, struct seq_file *f); +#else +static inline void clk_debug_print_hw(struct clk *clk, struct seq_file *f) {} +#endif + +#define CLK_WARN(clk, cond, fmt, ...) do { \ + clk_debug_print_hw(clk, NULL); \ + WARN(cond, "%s: " fmt, clk_name(clk), ##__VA_ARGS__); \ +} while (0) + +/** + * struct clk_vdd_class - Voltage scaling class + * @class_name: name of the class + * @regulator: array of regulators. + * @num_regulators: size of regulator array. Standard regulator APIs will be + used if this field > 0. + * @set_vdd: function to call when applying a new voltage setting. + * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then + regulator. + * @vdd_ua: sorted 2D array of legal cureent settings. Indexed by level, then + regulator. Optional parameter. + * @level_votes: array of votes for each level. + * @num_levels: specifies the size of level_votes array. + * @skip_handoff: do not vote for the max possible voltage during init + * @use_max_uV: use INT_MAX for max_uV when calling regulator_set_voltage + * This is useful when different vdd_class share same regulator. + * @cur_level: the currently set voltage level + * @lock: lock to protect this struct + */ +struct clk_vdd_class { + const char *class_name; + struct regulator **regulator; + int num_regulators; + int (*set_vdd)(struct clk_vdd_class *v_class, int level); + int *vdd_uv; + int *vdd_ua; + int *level_votes; + int num_levels; + bool skip_handoff; + bool use_max_uV; + unsigned long cur_level; + struct mutex lock; +}; + +#define DEFINE_VDD_CLASS(_name, _set_vdd, _num_levels) \ + struct clk_vdd_class _name = { \ + .class_name = #_name, \ + .set_vdd = _set_vdd, \ + .level_votes = (int [_num_levels]) {}, \ + .num_levels = _num_levels, \ + .cur_level = _num_levels, \ + .lock = __MUTEX_INITIALIZER(_name.lock) \ + } + +#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv, \ + _vdd_ua) \ + struct clk_vdd_class _name = { \ + .class_name = #_name, \ + .vdd_uv = _vdd_uv, \ + .vdd_ua = _vdd_ua, \ + .regulator = (struct regulator * [_num_regulators]) {}, \ + .num_regulators = _num_regulators, \ + .level_votes = (int [_num_levels]) {}, \ + .num_levels = _num_levels, \ + .cur_level = _num_levels, \ + .lock = __MUTEX_INITIALIZER(_name.lock) \ + } + +#define DEFINE_VDD_REGS_INIT(_name, _num_regulators) \ + struct clk_vdd_class _name = { \ + .class_name = #_name, \ + .regulator = (struct regulator * [_num_regulators]) {}, \ + .num_regulators = _num_regulators, \ + .lock = __MUTEX_INITIALIZER(_name.lock) \ + } + +enum handoff { + HANDOFF_ENABLED_CLK, + HANDOFF_DISABLED_CLK, +}; + +struct clk_ops { + int (*prepare)(struct clk *clk); + int (*enable)(struct clk *clk); + void (*disable)(struct clk *clk); + void (*unprepare)(struct clk *clk); + void (*enable_hwcg)(struct clk *clk); + void (*disable_hwcg)(struct clk *clk); + int (*in_hwcg_mode)(struct clk *clk); + enum handoff (*handoff)(struct clk *clk); + int (*reset)(struct clk *clk, enum clk_reset_action action); + int (*pre_set_rate)(struct clk *clk, unsigned long new_rate); + int (*set_rate)(struct clk *clk, unsigned long rate); + void (*post_set_rate)(struct clk *clk, unsigned long old_rate); + int (*set_max_rate)(struct clk *clk, unsigned long rate); + int (*set_flags)(struct clk *clk, unsigned flags); + unsigned long (*get_rate)(struct clk *clk); + long (*list_rate)(struct clk *clk, unsigned n); + int (*is_enabled)(struct clk *clk); + long (*round_rate)(struct clk *clk, unsigned long rate); + int (*set_parent)(struct clk *clk, struct clk *parent); + struct clk *(*get_parent)(struct clk *clk); + bool (*is_local)(struct clk *clk); + void __iomem *(*list_registers)(struct clk *clk, int n, + struct clk_register_data **regs, u32 *size); +}; + +/** + * struct clk + * @prepare_count: prepare refcount + * @prepare_lock: protects clk_prepare()/clk_unprepare() path and @prepare_count + * @count: enable refcount + * @lock: protects clk_enable()/clk_disable() path and @count + * @depends: non-direct parent of clock to enable when this clock is enabled + * @vdd_class: voltage scaling requirement class + * @fmax: maximum frequency in Hz supported at each voltage level + * @parent: the current source of this clock + * @opp_table_populated: tracks if the OPP table of this clock has been filled + */ +struct clk { + uint32_t flags; + struct clk_ops *ops; + const char *dbg_name; + struct clk *depends; + struct clk_vdd_class *vdd_class; + unsigned long *fmax; + int num_fmax; + unsigned long rate; + struct clk *parent; + struct clk_src *parents; + unsigned int num_parents; + + struct list_head children; + struct list_head siblings; + struct list_head list; + + unsigned count; + unsigned notifier_count; + spinlock_t lock; + unsigned prepare_count; + struct mutex prepare_lock; + + unsigned long init_rate; + bool always_on; + bool opp_table_populated; + + struct dentry *clk_dir; +}; + +#define CLK_INIT(name) \ + .lock = __SPIN_LOCK_UNLOCKED((name).lock), \ + .prepare_lock = __MUTEX_INITIALIZER((name).prepare_lock), \ + .children = LIST_HEAD_INIT((name).children), \ + .siblings = LIST_HEAD_INIT((name).siblings), \ + .list = LIST_HEAD_INIT((name).list) + +bool is_rate_valid(struct clk *clk, unsigned long rate); +int vote_vdd_level(struct clk_vdd_class *vdd_class, int level); +int unvote_vdd_level(struct clk_vdd_class *vdd_class, int level); +int __clk_pre_reparent(struct clk *c, struct clk *new, unsigned long *flags); +void __clk_post_reparent(struct clk *c, struct clk *old, unsigned long *flags); + +/* Register clocks with the MSM clock driver */ +int msm_clock_register(struct clk_lookup *table, size_t size); +int of_msm_clock_register(struct device_node *np, struct clk_lookup *table, + size_t size); + +int clock_rcgwr_init(struct platform_device *pdev); +int clock_rcgwr_disable(struct platform_device *pdev); + +extern struct clk dummy_clk; +extern struct clk_ops clk_ops_dummy; + +#define CLK_DUMMY(clk_name, clk_id, clk_dev, flags) { \ + .con_id = clk_name, \ + .dev_id = clk_dev, \ + .clk = &dummy_clk, \ + } + +#define DEFINE_CLK_DUMMY(name, _rate) \ + static struct fixed_clk name = { \ + .c = { \ + .dbg_name = #name, \ + .rate = _rate, \ + .ops = &clk_ops_dummy, \ + CLK_INIT(name.c), \ + }, \ + }; + +#define CLK_LOOKUP(con, c, dev) { .con_id = con, .clk = &c, .dev_id = dev } +#define CLK_LOOKUP_OF(con, _c, dev) { .con_id = con, .clk = &(&_c)->c, \ + .dev_id = dev, .of_idx = clk_##_c } +#define CLK_LIST(_c) { .clk = &(&_c)->c, .of_idx = clk_##_c } + +static inline bool is_better_rate(unsigned long req, unsigned long best, + unsigned long new) +{ + if (IS_ERR_VALUE(new)) + return false; + + return (req <= new && new < best) || (best < req && best < new); +} + +extern int of_clk_add_provider(struct device_node *np, + struct clk *(*clk_src_get)(struct of_phandle_args *args, + void *data), + void *data); +extern void of_clk_del_provider(struct device_node *np); + +static inline const char *clk_name(struct clk *c) +{ + if (IS_ERR_OR_NULL(c)) + return "(null)"; + return c->dbg_name; +}; +#endif /* CONFIG_COMMON_CLK_MSM */ +#endif diff --git a/include/linux/clk/msm-clk.h b/include/linux/clk/msm-clk.h new file mode 100644 index 000000000000..8455fd776246 --- /dev/null +++ b/include/linux/clk/msm-clk.h @@ -0,0 +1,138 @@ +/* Copyright (c) 2009, 2012-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __MACH_CLK_H +#define __MACH_CLK_H + +#include <linux/notifier.h> + +#if defined(CONFIG_COMMON_CLK_QCOM) +enum branch_mem_flags { + CLKFLAG_RETAIN_PERIPH, + CLKFLAG_NORETAIN_PERIPH, + CLKFLAG_RETAIN_MEM, + CLKFLAG_NORETAIN_MEM, + CLKFLAG_PERIPH_OFF_SET, + CLKFLAG_PERIPH_OFF_CLEAR, +}; + +#include <linux/clk.h> + +#elif defined(CONFIG_COMMON_CLK_MSM) +#define CLKFLAG_INVERT 0x00000001 +#define CLKFLAG_NOINVERT 0x00000002 +#define CLKFLAG_NONEST 0x00000004 +#define CLKFLAG_NORESET 0x00000008 +#define CLKFLAG_RETAIN_PERIPH 0x00000010 +#define CLKFLAG_NORETAIN_PERIPH 0x00000020 +#define CLKFLAG_RETAIN_MEM 0x00000040 +#define CLKFLAG_NORETAIN_MEM 0x00000080 +#define CLKFLAG_SKIP_HANDOFF 0x00000100 +#define CLKFLAG_MIN 0x00000400 +#define CLKFLAG_MAX 0x00000800 +#define CLKFLAG_INIT_DONE 0x00001000 +#define CLKFLAG_INIT_ERR 0x00002000 +#define CLKFLAG_NO_RATE_CACHE 0x00004000 +#define CLKFLAG_MEASURE 0x00008000 +#define CLKFLAG_EPROBE_DEFER 0x00010000 +#define CLKFLAG_PERIPH_OFF_SET 0x00020000 +#define CLKFLAG_PERIPH_OFF_CLEAR 0x00040000 + +struct clk_lookup; +struct clk; + +enum clk_reset_action { + CLK_RESET_DEASSERT = 0, + CLK_RESET_ASSERT = 1 +}; + +struct clk_src { + struct clk *src; + int sel; +}; + +/* Rate is maximum clock rate in Hz */ +int clk_set_max_rate(struct clk *clk, unsigned long rate); + +/* Assert/Deassert reset to a hardware block associated with a clock */ +int clk_reset(struct clk *clk, enum clk_reset_action action); + +/* Set clock-specific configuration parameters */ +int clk_set_flags(struct clk *clk, unsigned long flags); + +/* returns the mux selection index associated with a particular parent */ +int parent_to_src_sel(struct clk_src *parents, int num_parents, struct clk *p); + +/* returns the mux selection index associated with a particular parent */ +int clk_get_parent_sel(struct clk *c, struct clk *parent); + +/** + * DOC: clk notifier callback types + * + * PRE_RATE_CHANGE - called immediately before the clk rate is changed, + * to indicate that the rate change will proceed. Drivers must + * immediately terminate any operations that will be affected by the + * rate change. Callbacks may either return NOTIFY_DONE, NOTIFY_OK, + * NOTIFY_STOP or NOTIFY_BAD. + * + * ABORT_RATE_CHANGE: called if the rate change failed for some reason + * after PRE_RATE_CHANGE. In this case, all registered notifiers on + * the clk will be called with ABORT_RATE_CHANGE. Callbacks must + * always return NOTIFY_DONE or NOTIFY_OK. + * + * POST_RATE_CHANGE - called after the clk rate change has successfully + * completed. Callbacks must always return NOTIFY_DONE or NOTIFY_OK. + * + */ +#define PRE_RATE_CHANGE BIT(0) +#define POST_RATE_CHANGE BIT(1) +#define ABORT_RATE_CHANGE BIT(2) + +/** + * struct msm_clk_notifier - associate a clk with a notifier + * @clk: struct clk * to associate the notifier with + * @notifier_head: a blocking_notifier_head for this clk + * @node: linked list pointers + * + * A list of struct clk_notifier is maintained by the notifier code. + * An entry is created whenever code registers the first notifier on a + * particular @clk. Future notifiers on that @clk are added to the + * @notifier_head. + */ +struct msm_clk_notifier { + struct clk *clk; + struct srcu_notifier_head notifier_head; + struct list_head node; +}; + +/** + * struct msm_clk_notifier_data - rate data to pass to the notifier callback + * @clk: struct clk * being changed + * @old_rate: previous rate of this clk + * @new_rate: new rate of this clk + * + * For a pre-notifier, old_rate is the clk's rate before this rate + * change, and new_rate is what the rate will be in the future. For a + * post-notifier, old_rate and new_rate are both set to the clk's + * current rate (this was done to optimize the implementation). + */ +struct msm_clk_notifier_data { + struct clk *clk; + unsigned long old_rate; + unsigned long new_rate; +}; + +int msm_clk_notif_register(struct clk *clk, struct notifier_block *nb); + +int msm_clk_notif_unregister(struct clk *clk, struct notifier_block *nb); + +#endif /* CONFIG_COMMON_CLK_MSM */ +#endif diff --git a/include/linux/clk/msm-clock-generic.h b/include/linux/clk/msm-clock-generic.h new file mode 100644 index 000000000000..cb2d8787b84f --- /dev/null +++ b/include/linux/clk/msm-clock-generic.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MSM_CLOCK_GENERIC_H +#define __MSM_CLOCK_GENERIC_H + +#include <linux/clk/msm-clk-provider.h> +#include <linux/of.h> + +/** + * struct fixed_clk - fixed rate clock + * @c: clk + */ +struct fixed_clk { + struct clk c; +}; + +/* ==================== Mux clock ==================== */ + +struct mux_clk; + +struct clk_mux_ops { + int (*set_mux_sel)(struct mux_clk *clk, int sel); + int (*get_mux_sel)(struct mux_clk *clk); + + /* Optional */ + bool (*is_enabled)(struct mux_clk *clk); + int (*enable)(struct mux_clk *clk); + void (*disable)(struct mux_clk *clk); + void __iomem *(*list_registers)(struct mux_clk *clk, int n, + struct clk_register_data **regs, u32 *size); +}; + +#define MUX_SRC_LIST(...) \ + .parents = (struct clk_src[]){__VA_ARGS__}, \ + .num_parents = ARRAY_SIZE(((struct clk_src[]){__VA_ARGS__})) + +#define MUX_REC_SRC_LIST(...) \ + .rec_parents = (struct clk * []){__VA_ARGS__}, \ + .num_rec_parents = ARRAY_SIZE(((struct clk * []){__VA_ARGS__})) + +struct mux_clk { + /* Parents in decreasing order of preference for obtaining rates. */ + struct clk_src *parents; + int num_parents; + /* Recursively search for the requested parent in rec_parents. */ + struct clk **rec_parents; + int num_rec_parents; + struct clk *safe_parent; + int safe_sel; + unsigned long safe_freq; + /* + * Before attempting a clk_round_rate on available sources, attempt a + * clk_get_rate on all those sources. If one of them is already at the + * necessary rate, that source will be used. + */ + bool try_get_rate; + struct clk_mux_ops *ops; + /* + * Set if you need the mux to try a new parent before falling back to + * the current parent. If the safe_parent field above is set, then the + * safe_sel intermediate source will only be used if we fall back to + * to the current parent during mux_set_rate. + */ + bool try_new_parent; + + /* Fields not used by helper function. */ + void *const __iomem *base; + u32 offset; + u32 en_offset; + u32 mask; + u32 shift; + u32 en_mask; + /* + * Set post divider for debug mux in order to divide the clock + * by post_div + 1. + */ + u32 post_div; + int low_power_sel; + void *priv; + + struct clk c; +}; + +static inline struct mux_clk *to_mux_clk(struct clk *c) +{ + return container_of(c, struct mux_clk, c); +} + +extern struct clk_ops clk_ops_gen_mux; + +/* ==================== Divider clock ==================== */ + +struct div_clk; + +struct clk_div_ops { + int (*set_div)(struct div_clk *clk, int div); + int (*get_div)(struct div_clk *clk); + bool (*is_enabled)(struct div_clk *clk); + int (*enable)(struct div_clk *clk); + void (*disable)(struct div_clk *clk); + void __iomem *(*list_registers)(struct div_clk *clk, int n, + struct clk_register_data **regs, u32 *size); +}; + +struct div_data { + unsigned int div; + unsigned int min_div; + unsigned int max_div; + unsigned long rate_margin; + /* + * Indicate whether this divider clock supports half-interger divider. + * If it is, all the min_div and max_div have been doubled. It means + * they are 2*N. + */ + bool is_half_divider; + /* + * Skip odd dividers since the hardware may not support them. + */ + bool skip_odd_div; + bool skip_even_div; + bool allow_div_one; + unsigned int cached_div; +}; + +struct div_clk { + struct div_data data; + + /* + * Some implementations may require the divider to be set to a "safe" + * value that allows reprogramming of upstream clocks without violating + * voltage constraints. + */ + unsigned long safe_freq; + + /* Optional */ + struct clk_div_ops *ops; + + /* Fields not used by helper function. */ + void *const __iomem *base; + u32 offset; + u32 mask; + u32 shift; + u32 en_mask; + void *priv; + struct clk c; +}; + +static inline struct div_clk *to_div_clk(struct clk *c) +{ + return container_of(c, struct div_clk, c); +} + +extern struct clk_ops clk_ops_div; +extern struct clk_ops clk_ops_slave_div; + +struct ext_clk { + struct clk c; + struct device *dev; + char *clk_id; +}; + +long parent_round_rate(struct clk *c, unsigned long rate); +unsigned long parent_get_rate(struct clk *c); +int parent_set_rate(struct clk *c, unsigned long rate); + +static inline struct ext_clk *to_ext_clk(struct clk *c) +{ + return container_of(c, struct ext_clk, c); +} + +extern struct clk_ops clk_ops_ext; + +#define DEFINE_FIXED_DIV_CLK(clk_name, _div, _parent) \ +static struct div_clk clk_name = { \ + .data = { \ + .max_div = _div, \ + .min_div = _div, \ + .div = _div, \ + }, \ + .c = { \ + .parent = _parent, \ + .dbg_name = #clk_name, \ + .ops = &clk_ops_div, \ + CLK_INIT(clk_name.c), \ + } \ +} + +#define DEFINE_FIXED_SLAVE_DIV_CLK(clk_name, _div, _parent) \ +static struct div_clk clk_name = { \ + .data = { \ + .max_div = _div, \ + .min_div = _div, \ + .div = _div, \ + }, \ + .c = { \ + .parent = _parent, \ + .dbg_name = #clk_name, \ + .ops = &clk_ops_slave_div, \ + CLK_INIT(clk_name.c), \ + } \ +} + +#define DEFINE_EXT_CLK(clk_name, _parent) \ +static struct ext_clk clk_name = { \ + .c = { \ + .parent = _parent, \ + .dbg_name = #clk_name, \ + .ops = &clk_ops_ext, \ + CLK_INIT(clk_name.c), \ + } \ +} + +/* ==================== Mux Div clock ==================== */ + +struct mux_div_clk; + +/* + * struct mux_div_ops + * the enable and disable ops are optional. + */ + +struct mux_div_ops { + int (*set_src_div)(struct mux_div_clk *, u32 src_sel, u32 div); + void (*get_src_div)(struct mux_div_clk *, u32 *src_sel, u32 *div); + int (*enable)(struct mux_div_clk *); + void (*disable)(struct mux_div_clk *); + bool (*is_enabled)(struct mux_div_clk *); + void __iomem *(*list_registers)(struct mux_div_clk *md, int n, + struct clk_register_data **regs, u32 *size); +}; + +/* + * struct mux_div_clk - combined mux/divider clock + * @priv + parameters needed by ops + * @safe_freq + when switching rates from A to B, the mux div clock will + instead switch from A -> safe_freq -> B. This allows the + mux_div clock to change rates while enabled, even if this + behavior is not supported by the parent clocks. + + If changing the rate of parent A also causes the rate of + parent B to change, then safe_freq must be defined. + + safe_freq is expected to have a source clock which is always + on and runs at only one rate. + * @parents + list of parents and mux indicies + * @ops + function pointers for hw specific operations + * @src_sel + the mux index which will be used if the clock is enabled. + * @try_get_rate + Set if you need the mux to directly jump to a source + that is at the desired rate currently. + * @force_enable_md + Set if the mux-div needs to be force enabled/disabled during + clk_enable/disable. + */ + +struct mux_div_clk { + /* Required parameters */ + struct mux_div_ops *ops; + struct div_data data; + struct clk_src *parents; + u32 num_parents; + + struct clk c; + + /* Internal */ + u32 src_sel; + + /* Optional parameters */ + void *priv; + void __iomem *base; + u32 div_mask; + u32 div_offset; + u32 div_shift; + u32 src_mask; + u32 src_offset; + u32 src_shift; + u32 en_mask; + u32 en_offset; + + u32 safe_div; + struct clk *safe_parent; + unsigned long safe_freq; + bool try_get_rate; + bool force_enable_md; +}; + +static inline struct mux_div_clk *to_mux_div_clk(struct clk *clk) +{ + return container_of(clk, struct mux_div_clk, c); +} + +extern struct clk_ops clk_ops_mux_div_clk; + +/* ==================== Virtual clock ==================== */ +struct virtclk_front { + int id; + struct clk c; + u32 flag; +}; + +extern struct clk_ops virtclk_front_ops; + +int msm_virtclk_front_probe(struct platform_device *pdev, + struct clk_lookup *table, + size_t size); + +#endif diff --git a/include/linux/clk/mxs.h b/include/linux/clk/mxs.h new file mode 100644 index 000000000000..5138a90e018c --- /dev/null +++ b/include/linux/clk/mxs.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2013 Freescale Semiconductor, 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 __LINUX_CLK_MXS_H +#define __LINUX_CLK_MXS_H + +int mxs_saif_clkmux_select(unsigned int clkmux); + +#endif diff --git a/include/linux/clk/shmobile.h b/include/linux/clk/shmobile.h new file mode 100644 index 000000000000..cb19cc1865ca --- /dev/null +++ b/include/linux/clk/shmobile.h @@ -0,0 +1,35 @@ +/* + * Copyright 2013 Ideas On Board SPRL + * Copyright 2013, 2014 Horms Solutions Ltd. + * + * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> + * Contact: Simon Horman <horms@verge.net.au> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __LINUX_CLK_SHMOBILE_H_ +#define __LINUX_CLK_SHMOBILE_H_ + +#include <linux/types.h> + +struct device; +struct device_node; +struct generic_pm_domain; + +void r8a7778_clocks_init(u32 mode); +void r8a7779_clocks_init(u32 mode); +void rcar_gen2_clocks_init(u32 mode); + +#ifdef CONFIG_PM_GENERIC_DOMAINS_OF +void cpg_mstp_add_clk_domain(struct device_node *np); +int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev); +void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev); +#else +static inline void cpg_mstp_add_clk_domain(struct device_node *np) {} +#endif + +#endif diff --git a/include/linux/clk/tegra.h b/include/linux/clk/tegra.h new file mode 100644 index 000000000000..57bf7aab4516 --- /dev/null +++ b/include/linux/clk/tegra.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __LINUX_CLK_TEGRA_H_ +#define __LINUX_CLK_TEGRA_H_ + +#include <linux/types.h> +#include <linux/bug.h> + +/* + * Tegra CPU clock and reset control ops + * + * wait_for_reset: + * keep waiting until the CPU in reset state + * put_in_reset: + * put the CPU in reset state + * out_of_reset: + * release the CPU from reset state + * enable_clock: + * CPU clock un-gate + * disable_clock: + * CPU clock gate + * rail_off_ready: + * CPU is ready for rail off + * suspend: + * save the clock settings when CPU go into low-power state + * resume: + * restore the clock settings when CPU exit low-power state + */ +struct tegra_cpu_car_ops { + void (*wait_for_reset)(u32 cpu); + void (*put_in_reset)(u32 cpu); + void (*out_of_reset)(u32 cpu); + void (*enable_clock)(u32 cpu); + void (*disable_clock)(u32 cpu); +#ifdef CONFIG_PM_SLEEP + bool (*rail_off_ready)(void); + void (*suspend)(void); + void (*resume)(void); +#endif +}; + +extern struct tegra_cpu_car_ops *tegra_cpu_car_ops; + +static inline void tegra_wait_cpu_in_reset(u32 cpu) +{ + if (WARN_ON(!tegra_cpu_car_ops->wait_for_reset)) + return; + + tegra_cpu_car_ops->wait_for_reset(cpu); +} + +static inline void tegra_put_cpu_in_reset(u32 cpu) +{ + if (WARN_ON(!tegra_cpu_car_ops->put_in_reset)) + return; + + tegra_cpu_car_ops->put_in_reset(cpu); +} + +static inline void tegra_cpu_out_of_reset(u32 cpu) +{ + if (WARN_ON(!tegra_cpu_car_ops->out_of_reset)) + return; + + tegra_cpu_car_ops->out_of_reset(cpu); +} + +static inline void tegra_enable_cpu_clock(u32 cpu) +{ + if (WARN_ON(!tegra_cpu_car_ops->enable_clock)) + return; + + tegra_cpu_car_ops->enable_clock(cpu); +} + +static inline void tegra_disable_cpu_clock(u32 cpu) +{ + if (WARN_ON(!tegra_cpu_car_ops->disable_clock)) + return; + + tegra_cpu_car_ops->disable_clock(cpu); +} + +#ifdef CONFIG_PM_SLEEP +static inline bool tegra_cpu_rail_off_ready(void) +{ + if (WARN_ON(!tegra_cpu_car_ops->rail_off_ready)) + return false; + + return tegra_cpu_car_ops->rail_off_ready(); +} + +static inline void tegra_cpu_clock_suspend(void) +{ + if (WARN_ON(!tegra_cpu_car_ops->suspend)) + return; + + tegra_cpu_car_ops->suspend(); +} + +static inline void tegra_cpu_clock_resume(void) +{ + if (WARN_ON(!tegra_cpu_car_ops->resume)) + return; + + tegra_cpu_car_ops->resume(); +} +#endif + +#endif /* __LINUX_CLK_TEGRA_H_ */ diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h new file mode 100644 index 000000000000..223be696df27 --- /dev/null +++ b/include/linux/clk/ti.h @@ -0,0 +1,308 @@ +/* + * TI clock drivers support + * + * Copyright (C) 2013 Texas Instruments, 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __LINUX_CLK_TI_H__ +#define __LINUX_CLK_TI_H__ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> + +/** + * 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 + * @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() + * @last_rounded_m4xen: cache of the last M4X result of + * omap4_dpll_regm4xen_round_rate() + * @last_rounded_lpmode: cache of the last lpmode result of + * omap4_dpll_lpmode_recalc() + * @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 + * @dcc_mask: mask of the DPLL DCC correction bitfield @mult_div1_reg + * @dcc_rate: rate atleast which DCC @dcc_mask must be set + * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg + * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg + * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_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) + * + * @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 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 different 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 long last_rounded_rate; + u16 last_rounded_m; + u8 last_rounded_m4xen; + u8 last_rounded_lpmode; + u16 max_multiplier; + u8 last_rounded_n; + u8 min_divider; + u16 max_divider; + u8 modes; + void __iomem *autoidle_reg; + void __iomem *idlest_reg; + u32 autoidle_mask; + u32 freqsel_mask; + u32 idlest_mask; + u32 dco_mask; + u32 sddiv_mask; + u32 dcc_mask; + unsigned long dcc_rate; + u32 lpmode_mask; + u32 m4xen_mask; + u8 auto_recal_bit; + u8 recal_en_bit; + u8 recal_st_bit; + u8 flags; +}; + +struct clk_hw_omap; + +/** + * struct clk_hw_omap_ops - OMAP clk ops + * @find_idlest: find idlest register information for a clock + * @find_companion: find companion clock register information for a clock, + * basically converts CM_ICLKEN* <-> CM_FCLKEN* + * @allow_idle: enables autoidle hardware functionality for a clock + * @deny_idle: prevent autoidle hardware functionality for a clock + */ +struct clk_hw_omap_ops { + void (*find_idlest)(struct clk_hw_omap *oclk, + void __iomem **idlest_reg, + u8 *idlest_bit, u8 *idlest_val); + void (*find_companion)(struct clk_hw_omap *oclk, + void __iomem **other_reg, + u8 *other_bit); + void (*allow_idle)(struct clk_hw_omap *oclk); + void (*deny_idle)(struct clk_hw_omap *oclk); +}; + +/** + * struct clk_hw_omap - OMAP struct clk + * @node: list_head connecting this clock into the full clock list + * @enable_reg: register to write to enable the clock (see @enable_bit) + * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg) + * @flags: see "struct clk.flags possibilities" above + * @clksel_reg: for clksel clks, register va containing src/divisor select + * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector + * @clksel: for clksel clks, pointer to struct clksel for this clock + * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock + * @clkdm_name: clockdomain name that this clock is contained in + * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime + * @ops: clock ops for this clock + */ +struct clk_hw_omap { + struct clk_hw hw; + struct list_head node; + unsigned long fixed_rate; + u8 fixed_div; + void __iomem *enable_reg; + u8 enable_bit; + u8 flags; + void __iomem *clksel_reg; + u32 clksel_mask; + const struct clksel *clksel; + struct dpll_data *dpll_data; + const char *clkdm_name; + struct clockdomain *clkdm; + const struct clk_hw_omap_ops *ops; +}; + +/* + * struct clk_hw_omap.flags possibilities + * + * XXX document the rest of the clock flags here + * + * ENABLE_REG_32BIT: (OMAP1 only) clock control register must be accessed + * with 32bit ops, by default OMAP1 uses 16bit ops. + * CLOCK_IDLE_CONTROL: (OMAP1 only) clock has autoidle support. + * CLOCK_NO_IDLE_PARENT: (OMAP1 only) when clock is enabled, its parent + * clock is put to no-idle mode. + * ENABLE_ON_INIT: Clock is enabled on init. + * INVERT_ENABLE: By default, clock enable bit behavior is '1' enable, '0' + * disable. This inverts the behavior making '0' enable and '1' disable. + * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL + * bits share the same register. This flag allows the + * omap4_dpllmx*() code to determine which GATE_CTRL bit field + * should be used. This is a temporary solution - a better approach + * would be to associate clock type-specific data with the clock, + * similar to the struct dpll_data approach. + * MEMMAP_ADDRESSING: Use memmap addressing to access clock registers. + */ +#define ENABLE_REG_32BIT (1 << 0) /* Use 32-bit access */ +#define CLOCK_IDLE_CONTROL (1 << 1) +#define CLOCK_NO_IDLE_PARENT (1 << 2) +#define ENABLE_ON_INIT (1 << 3) /* Enable upon framework init */ +#define INVERT_ENABLE (1 << 4) /* 0 enables, 1 disables */ +#define CLOCK_CLKOUTX2 (1 << 5) +#define MEMMAP_ADDRESSING (1 << 6) + +/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */ +#define DPLL_LOW_POWER_STOP 0x1 +#define DPLL_LOW_POWER_BYPASS 0x5 +#define DPLL_LOCKED 0x7 + +/* DPLL Type and DCO Selection Flags */ +#define DPLL_J_TYPE 0x1 + +/* Static memmap indices */ +enum { + TI_CLKM_CM = 0, + TI_CLKM_CM2, + TI_CLKM_PRM, + TI_CLKM_SCRM, + TI_CLKM_CTRL, + CLK_MAX_MEMMAPS +}; + +/** + * struct clk_omap_reg - OMAP register declaration + * @offset: offset from the master IP module base address + * @index: index of the master IP module + */ +struct clk_omap_reg { + u16 offset; + u16 index; +}; + +/** + * struct ti_clk_ll_ops - low-level ops for clocks + * @clk_readl: pointer to register read function + * @clk_writel: pointer to register write function + * @clkdm_clk_enable: pointer to clockdomain enable function + * @clkdm_clk_disable: pointer to clockdomain disable function + * @cm_wait_module_ready: pointer to CM module wait ready function + * @cm_split_idlest_reg: pointer to CM module function to split idlest reg + * + * Low-level ops are generally used by the basic clock types (clk-gate, + * clk-mux, clk-divider etc.) to provide support for various low-level + * hadrware interfaces (direct MMIO, regmap etc.), and is initialized + * by board code. Low-level ops also contain some other platform specific + * operations not provided directly by clock drivers. + */ +struct ti_clk_ll_ops { + u32 (*clk_readl)(void __iomem *reg); + void (*clk_writel)(u32 val, void __iomem *reg); + int (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk); + int (*clkdm_clk_disable)(struct clockdomain *clkdm, + struct clk *clk); + int (*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg, + u8 idlest_shift); + int (*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst, + u8 *idlest_reg_id); +}; + +#define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw) + +void omap2_init_clk_clkdm(struct clk_hw *clk); +int omap2_clk_disable_autoidle_all(void); +int omap2_clk_enable_autoidle_all(void); +int omap2_clk_allow_idle(struct clk *clk); +int omap2_clk_deny_idle(struct clk *clk); +unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, + unsigned long parent_rate); +int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate, + unsigned long parent_rate); +void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); +void omap2xxx_clkt_vps_init(void); +unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk); + +void ti_dt_clk_init_retry_clks(void); +void ti_dt_clockdomains_setup(void); +int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops); + +struct regmap; + +int omap2_clk_provider_init(struct device_node *parent, int index, + struct regmap *syscon, void __iomem *mem); +void omap2_clk_legacy_provider_init(int index, void __iomem *mem); + +int omap3430_dt_clk_init(void); +int omap3630_dt_clk_init(void); +int am35xx_dt_clk_init(void); +int dm814x_dt_clk_init(void); +int dm816x_dt_clk_init(void); +int omap4xxx_dt_clk_init(void); +int omap5xxx_dt_clk_init(void); +int dra7xx_dt_clk_init(void); +int am33xx_dt_clk_init(void); +int am43xx_dt_clk_init(void); +int omap2420_dt_clk_init(void); +int omap2430_dt_clk_init(void); + +struct ti_clk_features { + u32 flags; + long fint_min; + long fint_max; + long fint_band1_max; + long fint_band2_min; + u8 dpll_bypass_vals; + u8 cm_idlest_val; +}; + +#define TI_CLK_DPLL_HAS_FREQSEL BIT(0) +#define TI_CLK_DPLL4_DENY_REPROGRAM BIT(1) +#define TI_CLK_DISABLE_CLKDM_CONTROL BIT(2) + +void ti_clk_setup_features(struct ti_clk_features *features); +const struct ti_clk_features *ti_clk_get_features(void); + +extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; + +#ifdef CONFIG_ATAGS +int omap3430_clk_legacy_init(void); +int omap3430es1_clk_legacy_init(void); +int omap36xx_clk_legacy_init(void); +int am35xx_clk_legacy_init(void); +#else +static inline int omap3430_clk_legacy_init(void) { return -ENXIO; } +static inline int omap3430es1_clk_legacy_init(void) { return -ENXIO; } +static inline int omap36xx_clk_legacy_init(void) { return -ENXIO; } +static inline int am35xx_clk_legacy_init(void) { return -ENXIO; } +#endif + + +#endif diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h new file mode 100644 index 000000000000..7a5633b71533 --- /dev/null +++ b/include/linux/clk/zynq.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2013 Xilinx Inc. + * Copyright (C) 2012 National Instruments + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __LINUX_CLK_ZYNQ_H_ +#define __LINUX_CLK_ZYNQ_H_ + +#include <linux/spinlock.h> + +void zynq_clock_init(void); + +struct clk *clk_register_zynq_pll(const char *name, const char *parent, + void __iomem *pll_ctrl, void __iomem *pll_status, u8 lock_index, + spinlock_t *lock); +#endif |
