Merge branches 'depends/asoc-dma', 'depends/dma-of' and 'depends/tegra-clk' into next/cleanup

Merging in external dependencies for the Tegra DMA and reset controller
refactoring from external trees.

Per Stephen Warren, the stability of these branches have been negotiated
with the relevant parties (Vinod/Mark/Mike)

* depends/asoc-dma:
  ASoC: dmaengine: fix deferred probe detection
  ASoC: dmaengine: support deferred probe for DMA channels
  dma: add channel request API that supports deferred probe
  ASoC: dmaengine: add custom DMA config to snd_dmaengine_pcm_config
  ASoC: don't leak on error in snd_dmaengine_pcm_register
  ASoC: restructure dmaengine_pcm_request_chan_of()
  ASoC: generic-dmaengine-pcm: Set BATCH flag when residue reporting is not supported
  ASoC: Add resource managed snd_dmaengine_pcm_register()

* depends/dma-of:
  dma: add dma_get_any_slave_channel(), for use in of_xlate()

* depends/tegra-clk: (42 commits)
  clk: tegra: fix __clk_lookup() return value checks
  clk: tegra: Do not print errors for clk_round_rate()
  clk: tegra: Initialize DSI low-power clocks
  clk: tegra: add FUSE clock device
  clk: tegra: Properly setup PWM clock on Tegra30
  clk: tegra: Initialize secondary gr3d clock on Tegra30
  clk: tegra114: Initialize clocks needed for HDMI
  clk: tegra124: add suspend/resume function for tegra_cpu_car_ops
  clk: tegra124: add wait_for_reset and disable_clock for tegra_cpu_car_ops
  clk: tegra124: Add support for Tegra124 clocks
  clk: tegra124: Add new peripheral clocks
  clk: tegra124: Add common clk IDs to clk-id.h
  clk: tegra: add TEGRA_PERIPH_NO_GATE
  clk: tegra: add locking to periph clks
  clk: tegra: Add periph regs bank X
  clk: tegra: Add support for PLLSS
  clk: tegra: move tegra20 to common infra
  clk: tegra: move tegra30 to common infra
  clk: tegra: introduce common gen4 super clock
  clk: tegra: move PMC, fixed clocks to common files
  ...

Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
Olof Johansson 2013-12-26 10:32:35 -08:00
commit 1c7af42fe5
27 changed files with 5296 additions and 3066 deletions

View File

@ -0,0 +1,59 @@
NVIDIA Tegra124 Clock And Reset Controller
This binding uses the common clock binding:
Documentation/devicetree/bindings/clock/clock-bindings.txt
The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
for muxing and gating Tegra's clocks, and setting their rates.
Required properties :
- compatible : Should be "nvidia,tegra124-car"
- reg : Should contain CAR registers location and length
- clocks : Should contain phandle and clock specifiers for two clocks:
the 32 KHz "32k_in", and the board-specific oscillator "osc".
- #clock-cells : Should be 1.
In clock consumers, this cell represents the clock ID exposed by the
CAR. The assignments may be found in header file
<dt-bindings/clock/tegra124-car.h>.
Example SoC include file:
/ {
tegra_car: clock {
compatible = "nvidia,tegra124-car";
reg = <0x60006000 0x1000>;
#clock-cells = <1>;
};
usb@c5004000 {
clocks = <&tegra_car TEGRA124_CLK_USB2>;
};
};
Example board file:
/ {
clocks {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
osc: clock@0 {
compatible = "fixed-clock";
reg = <0>;
#clock-cells = <0>;
clock-frequency = <112400000>;
};
clk_32k: clock@1 {
compatible = "fixed-clock";
reg = <1>;
#clock-cells = <0>;
clock-frequency = <32768>;
};
};
&tegra_car {
clocks = <&clk_32k> <&osc>;
};
};

View File

@ -6,7 +6,12 @@ obj-y += clk-periph-gate.o
obj-y += clk-pll.o
obj-y += clk-pll-out.o
obj-y += clk-super.o
obj-y += clk-tegra-audio.o
obj-y += clk-tegra-periph.o
obj-y += clk-tegra-pmc.o
obj-y += clk-tegra-fixed.o
obj-y += clk-tegra-super-gen4.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o

235
drivers/clk/tegra/clk-id.h Normal file
View File

@ -0,0 +1,235 @@
/*
* This header provides IDs for clocks common between several Tegra SoCs
*/
#ifndef _TEGRA_CLK_ID_H
#define _TEGRA_CLK_ID_H
enum clk_id {
tegra_clk_actmon,
tegra_clk_adx,
tegra_clk_adx1,
tegra_clk_afi,
tegra_clk_amx,
tegra_clk_amx1,
tegra_clk_apbdma,
tegra_clk_apbif,
tegra_clk_audio0,
tegra_clk_audio0_2x,
tegra_clk_audio0_mux,
tegra_clk_audio1,
tegra_clk_audio1_2x,
tegra_clk_audio1_mux,
tegra_clk_audio2,
tegra_clk_audio2_2x,
tegra_clk_audio2_mux,
tegra_clk_audio3,
tegra_clk_audio3_2x,
tegra_clk_audio3_mux,
tegra_clk_audio4,
tegra_clk_audio4_2x,
tegra_clk_audio4_mux,
tegra_clk_blink,
tegra_clk_bsea,
tegra_clk_bsev,
tegra_clk_cclk_g,
tegra_clk_cclk_lp,
tegra_clk_cilab,
tegra_clk_cilcd,
tegra_clk_cile,
tegra_clk_clk_32k,
tegra_clk_clk72Mhz,
tegra_clk_clk_m,
tegra_clk_clk_m_div2,
tegra_clk_clk_m_div4,
tegra_clk_clk_out_1,
tegra_clk_clk_out_1_mux,
tegra_clk_clk_out_2,
tegra_clk_clk_out_2_mux,
tegra_clk_clk_out_3,
tegra_clk_clk_out_3_mux,
tegra_clk_cml0,
tegra_clk_cml1,
tegra_clk_csi,
tegra_clk_csite,
tegra_clk_csus,
tegra_clk_cve,
tegra_clk_dam0,
tegra_clk_dam1,
tegra_clk_dam2,
tegra_clk_d_audio,
tegra_clk_dds,
tegra_clk_dfll_ref,
tegra_clk_dfll_soc,
tegra_clk_disp1,
tegra_clk_disp2,
tegra_clk_dp2,
tegra_clk_dpaux,
tegra_clk_dsia,
tegra_clk_dsialp,
tegra_clk_dsia_mux,
tegra_clk_dsib,
tegra_clk_dsiblp,
tegra_clk_dsib_mux,
tegra_clk_dtv,
tegra_clk_emc,
tegra_clk_entropy,
tegra_clk_epp,
tegra_clk_epp_8,
tegra_clk_extern1,
tegra_clk_extern2,
tegra_clk_extern3,
tegra_clk_fuse,
tegra_clk_fuse_burn,
tegra_clk_gpu,
tegra_clk_gr2d,
tegra_clk_gr2d_8,
tegra_clk_gr3d,
tegra_clk_gr3d_8,
tegra_clk_hclk,
tegra_clk_hda,
tegra_clk_hda2codec_2x,
tegra_clk_hda2hdmi,
tegra_clk_hdmi,
tegra_clk_hdmi_audio,
tegra_clk_host1x,
tegra_clk_host1x_8,
tegra_clk_i2c1,
tegra_clk_i2c2,
tegra_clk_i2c3,
tegra_clk_i2c4,
tegra_clk_i2c5,
tegra_clk_i2c6,
tegra_clk_i2cslow,
tegra_clk_i2s0,
tegra_clk_i2s0_sync,
tegra_clk_i2s1,
tegra_clk_i2s1_sync,
tegra_clk_i2s2,
tegra_clk_i2s2_sync,
tegra_clk_i2s3,
tegra_clk_i2s3_sync,
tegra_clk_i2s4,
tegra_clk_i2s4_sync,
tegra_clk_isp,
tegra_clk_isp_8,
tegra_clk_ispb,
tegra_clk_kbc,
tegra_clk_kfuse,
tegra_clk_la,
tegra_clk_mipi,
tegra_clk_mipi_cal,
tegra_clk_mpe,
tegra_clk_mselect,
tegra_clk_msenc,
tegra_clk_ndflash,
tegra_clk_ndflash_8,
tegra_clk_ndspeed,
tegra_clk_ndspeed_8,
tegra_clk_nor,
tegra_clk_owr,
tegra_clk_pcie,
tegra_clk_pclk,
tegra_clk_pll_a,
tegra_clk_pll_a_out0,
tegra_clk_pll_c,
tegra_clk_pll_c2,
tegra_clk_pll_c3,
tegra_clk_pll_c4,
tegra_clk_pll_c_out1,
tegra_clk_pll_d,
tegra_clk_pll_d2,
tegra_clk_pll_d2_out0,
tegra_clk_pll_d_out0,
tegra_clk_pll_dp,
tegra_clk_pll_e_out0,
tegra_clk_pll_m,
tegra_clk_pll_m_out1,
tegra_clk_pll_p,
tegra_clk_pll_p_out1,
tegra_clk_pll_p_out2,
tegra_clk_pll_p_out2_int,
tegra_clk_pll_p_out3,
tegra_clk_pll_p_out4,
tegra_clk_pll_p_out5,
tegra_clk_pll_ref,
tegra_clk_pll_re_out,
tegra_clk_pll_re_vco,
tegra_clk_pll_u,
tegra_clk_pll_u_12m,
tegra_clk_pll_u_480m,
tegra_clk_pll_u_48m,
tegra_clk_pll_u_60m,
tegra_clk_pll_x,
tegra_clk_pll_x_out0,
tegra_clk_pwm,
tegra_clk_rtc,
tegra_clk_sata,
tegra_clk_sata_cold,
tegra_clk_sata_oob,
tegra_clk_sbc1,
tegra_clk_sbc1_8,
tegra_clk_sbc2,
tegra_clk_sbc2_8,
tegra_clk_sbc3,
tegra_clk_sbc3_8,
tegra_clk_sbc4,
tegra_clk_sbc4_8,
tegra_clk_sbc5,
tegra_clk_sbc5_8,
tegra_clk_sbc6,
tegra_clk_sbc6_8,
tegra_clk_sclk,
tegra_clk_sdmmc1,
tegra_clk_sdmmc2,
tegra_clk_sdmmc3,
tegra_clk_sdmmc4,
tegra_clk_se,
tegra_clk_soc_therm,
tegra_clk_sor0,
tegra_clk_sor0_lvds,
tegra_clk_spdif,
tegra_clk_spdif_2x,
tegra_clk_spdif_in,
tegra_clk_spdif_in_sync,
tegra_clk_spdif_mux,
tegra_clk_spdif_out,
tegra_clk_timer,
tegra_clk_trace,
tegra_clk_tsec,
tegra_clk_tsensor,
tegra_clk_tvdac,
tegra_clk_tvo,
tegra_clk_uarta,
tegra_clk_uartb,
tegra_clk_uartc,
tegra_clk_uartd,
tegra_clk_uarte,
tegra_clk_usb2,
tegra_clk_usb3,
tegra_clk_usbd,
tegra_clk_vcp,
tegra_clk_vde,
tegra_clk_vde_8,
tegra_clk_vfir,
tegra_clk_vi,
tegra_clk_vi_8,
tegra_clk_vi_9,
tegra_clk_vic03,
tegra_clk_vim2_clk,
tegra_clk_vimclk_sync,
tegra_clk_vi_sensor,
tegra_clk_vi_sensor2,
tegra_clk_vi_sensor_8,
tegra_clk_xusb_dev,
tegra_clk_xusb_dev_src,
tegra_clk_xusb_falcon_src,
tegra_clk_xusb_fs_src,
tegra_clk_xusb_host,
tegra_clk_xusb_host_src,
tegra_clk_xusb_hs_src,
tegra_clk_xusb_ss,
tegra_clk_xusb_ss_src,
tegra_clk_max,
};
#endif /* _TEGRA_CLK_ID_H */

View File

@ -151,12 +151,16 @@ const struct clk_ops tegra_clk_periph_gate_ops = {
struct clk *tegra_clk_register_periph_gate(const char *name,
const char *parent_name, u8 gate_flags, void __iomem *clk_base,
unsigned long flags, int clk_num,
struct tegra_clk_periph_regs *pregs, int *enable_refcnt)
unsigned long flags, int clk_num, int *enable_refcnt)
{
struct tegra_clk_periph_gate *gate;
struct clk *clk;
struct clk_init_data init;
struct tegra_clk_periph_regs *pregs;
pregs = get_reg_bank(clk_num);
if (!pregs)
return ERR_PTR(-EINVAL);
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate) {

View File

@ -170,27 +170,50 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
.disable = clk_periph_disable,
};
const struct clk_ops tegra_clk_periph_no_gate_ops = {
.get_parent = clk_periph_get_parent,
.set_parent = clk_periph_set_parent,
.recalc_rate = clk_periph_recalc_rate,
.round_rate = clk_periph_round_rate,
.set_rate = clk_periph_set_rate,
};
static struct clk *_tegra_clk_register_periph(const char *name,
const char **parent_names, int num_parents,
struct tegra_clk_periph *periph,
void __iomem *clk_base, u32 offset, bool div,
void __iomem *clk_base, u32 offset,
unsigned long flags)
{
struct clk *clk;
struct clk_init_data init;
struct tegra_clk_periph_regs *bank;
bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
flags |= CLK_SET_RATE_PARENT;
init.ops = &tegra_clk_periph_nodiv_ops;
} else if (periph->gate.flags & TEGRA_PERIPH_NO_GATE)
init.ops = &tegra_clk_periph_no_gate_ops;
else
init.ops = &tegra_clk_periph_ops;
init.name = name;
init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
init.flags = flags;
init.parent_names = parent_names;
init.num_parents = num_parents;
bank = get_reg_bank(periph->gate.clk_num);
if (!bank)
return ERR_PTR(-EINVAL);
/* Data in .init is copied by clk_register(), so stack variable OK */
periph->hw.init = &init;
periph->magic = TEGRA_CLK_PERIPH_MAGIC;
periph->mux.reg = clk_base + offset;
periph->divider.reg = div ? (clk_base + offset) : NULL;
periph->gate.clk_base = clk_base;
periph->gate.regs = bank;
periph->gate.enable_refcnt = periph_clk_enb_refcnt;
clk = clk_register(NULL, &periph->hw);
if (IS_ERR(clk))
@ -209,7 +232,7 @@ struct clk *tegra_clk_register_periph(const char *name,
u32 offset, unsigned long flags)
{
return _tegra_clk_register_periph(name, parent_names, num_parents,
periph, clk_base, offset, true, flags);
periph, clk_base, offset, flags);
}
struct clk *tegra_clk_register_periph_nodiv(const char *name,
@ -217,6 +240,7 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
struct tegra_clk_periph *periph, void __iomem *clk_base,
u32 offset)
{
periph->gate.flags |= TEGRA_PERIPH_NO_DIV;
return _tegra_clk_register_periph(name, parent_names, num_parents,
periph, clk_base, offset, false, CLK_SET_RATE_PARENT);
periph, clk_base, offset, CLK_SET_RATE_PARENT);
}

View File

@ -77,7 +77,23 @@
#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
#define PLLE_SS_CTRL 0x68
#define PLLE_SS_DISABLE (7 << 10)
#define PLLE_SS_CNTL_BYPASS_SS BIT(10)
#define PLLE_SS_CNTL_INTERP_RESET BIT(11)
#define PLLE_SS_CNTL_SSC_BYP BIT(12)
#define PLLE_SS_CNTL_CENTER BIT(14)
#define PLLE_SS_CNTL_INVERT BIT(15)
#define PLLE_SS_DISABLE (PLLE_SS_CNTL_BYPASS_SS | PLLE_SS_CNTL_INTERP_RESET |\
PLLE_SS_CNTL_SSC_BYP)
#define PLLE_SS_MAX_MASK 0x1ff
#define PLLE_SS_MAX_VAL 0x25
#define PLLE_SS_INC_MASK (0xff << 16)
#define PLLE_SS_INC_VAL (0x1 << 16)
#define PLLE_SS_INCINTRV_MASK (0x3f << 24)
#define PLLE_SS_INCINTRV_VAL (0x20 << 24)
#define PLLE_SS_COEFFICIENTS_MASK \
(PLLE_SS_MAX_MASK | PLLE_SS_INC_MASK | PLLE_SS_INCINTRV_MASK)
#define PLLE_SS_COEFFICIENTS_VAL \
(PLLE_SS_MAX_VAL | PLLE_SS_INC_VAL | PLLE_SS_INCINTRV_VAL)
#define PLLE_AUX_PLLP_SEL BIT(2)
#define PLLE_AUX_ENABLE_SWCTL BIT(4)
@ -121,6 +137,36 @@
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
#define PLLSS_MISC_KCP 0
#define PLLSS_MISC_KVCO 0
#define PLLSS_MISC_SETUP 0
#define PLLSS_EN_SDM 0
#define PLLSS_EN_SSC 0
#define PLLSS_EN_DITHER2 0
#define PLLSS_EN_DITHER 1
#define PLLSS_SDM_RESET 0
#define PLLSS_CLAMP 0
#define PLLSS_SDM_SSC_MAX 0
#define PLLSS_SDM_SSC_MIN 0
#define PLLSS_SDM_SSC_STEP 0
#define PLLSS_SDM_DIN 0
#define PLLSS_MISC_DEFAULT ((PLLSS_MISC_KCP << 25) | \
(PLLSS_MISC_KVCO << 24) | \
PLLSS_MISC_SETUP)
#define PLLSS_CFG_DEFAULT ((PLLSS_EN_SDM << 31) | \
(PLLSS_EN_SSC << 30) | \
(PLLSS_EN_DITHER2 << 29) | \
(PLLSS_EN_DITHER << 28) | \
(PLLSS_SDM_RESET) << 27 | \
(PLLSS_CLAMP << 22))
#define PLLSS_CTRL1_DEFAULT \
((PLLSS_SDM_SSC_MAX << 16) | PLLSS_SDM_SSC_MIN)
#define PLLSS_CTRL2_DEFAULT \
((PLLSS_SDM_SSC_STEP << 16) | PLLSS_SDM_DIN)
#define PLLSS_LOCK_OVERRIDE BIT(24)
#define PLLSS_REF_SRC_SEL_SHIFT 25
#define PLLSS_REF_SRC_SEL_MASK (3 << PLLSS_REF_SRC_SEL_SHIFT)
#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
@ -134,7 +180,7 @@
#define mask(w) ((1 << (w)) - 1)
#define divm_mask(p) mask(p->params->div_nmp->divm_width)
#define divn_mask(p) mask(p->params->div_nmp->divn_width)
#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
mask(p->params->div_nmp->divp_width))
#define divm_max(p) (divm_mask(p))
@ -154,10 +200,10 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
{
u32 val;
if (!(pll->flags & TEGRA_PLL_USE_LOCK))
if (!(pll->params->flags & TEGRA_PLL_USE_LOCK))
return;
if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
if (!(pll->params->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
return;
val = pll_readl_misc(pll);
@ -171,13 +217,13 @@ static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
u32 val, lock_mask;
void __iomem *lock_addr;
if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
if (!(pll->params->flags & TEGRA_PLL_USE_LOCK)) {
udelay(pll->params->lock_delay);
return 0;
}
lock_addr = pll->clk_base;
if (pll->flags & TEGRA_PLL_LOCK_MISC)
if (pll->params->flags & TEGRA_PLL_LOCK_MISC)
lock_addr += pll->params->misc_reg;
else
lock_addr += pll->params->base_reg;
@ -204,7 +250,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
struct tegra_clk_pll *pll = to_clk_pll(hw);
u32 val;
if (pll->flags & TEGRA_PLLM) {
if (pll->params->flags & TEGRA_PLLM) {
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
@ -223,12 +269,12 @@ static void _clk_pll_enable(struct clk_hw *hw)
clk_pll_enable_lock(pll);
val = pll_readl_base(pll);
if (pll->flags & TEGRA_PLL_BYPASS)
if (pll->params->flags & TEGRA_PLL_BYPASS)
val &= ~PLL_BASE_BYPASS;
val |= PLL_BASE_ENABLE;
pll_writel_base(val, pll);
if (pll->flags & TEGRA_PLLM) {
if (pll->params->flags & TEGRA_PLLM) {
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
@ -241,12 +287,12 @@ static void _clk_pll_disable(struct clk_hw *hw)
u32 val;
val = pll_readl_base(pll);
if (pll->flags & TEGRA_PLL_BYPASS)
if (pll->params->flags & TEGRA_PLL_BYPASS)
val &= ~PLL_BASE_BYPASS;
val &= ~PLL_BASE_ENABLE;
pll_writel_base(val, pll);
if (pll->flags & TEGRA_PLLM) {
if (pll->params->flags & TEGRA_PLLM) {
val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
@ -326,7 +372,7 @@ static int _get_table_rate(struct clk_hw *hw,
struct tegra_clk_pll *pll = to_clk_pll(hw);
struct tegra_clk_pll_freq_table *sel;
for (sel = pll->freq_table; sel->input_rate != 0; sel++)
for (sel = pll->params->freq_table; sel->input_rate != 0; sel++)
if (sel->input_rate == parent_rate &&
sel->output_rate == rate)
break;
@ -389,12 +435,11 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
(1 << p_div) > divp_max(pll)
|| cfg->output_rate > pll->params->vco_max) {
pr_err("%s: Failed to set %s rate %lu\n",
__func__, __clk_get_name(hw->clk), rate);
WARN_ON(1);
return -EINVAL;
}
cfg->output_rate >>= p_div;
if (pll->params->pdiv_tohw) {
ret = _p_div_to_hw(hw, 1 << p_div);
if (ret < 0)
@ -414,7 +459,7 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
struct tegra_clk_pll_params *params = pll->params;
struct div_nmp *div_nmp = params->div_nmp;
if ((pll->flags & TEGRA_PLLM) &&
if ((params->flags & TEGRA_PLLM) &&
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
val = pll_override_readl(params->pmc_divp_reg, pll);
@ -450,7 +495,7 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
struct tegra_clk_pll_params *params = pll->params;
struct div_nmp *div_nmp = params->div_nmp;
if ((pll->flags & TEGRA_PLLM) &&
if ((params->flags & TEGRA_PLLM) &&
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
val = pll_override_readl(params->pmc_divp_reg, pll);
@ -479,11 +524,11 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll,
val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
if (pll->flags & TEGRA_PLL_SET_LFCON) {
if (pll->params->flags & TEGRA_PLL_SET_LFCON) {
val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
if (cfg->n >= PLLDU_LFCON_SET_DIVN)
val |= 1 << PLL_MISC_LFCON_SHIFT;
} else if (pll->flags & TEGRA_PLL_SET_DCCON) {
} else if (pll->params->flags & TEGRA_PLL_SET_DCCON) {
val &= ~(1 << PLL_MISC_DCCON_SHIFT);
if (rate >= (pll->params->vco_max >> 1))
val |= 1 << PLL_MISC_DCCON_SHIFT;
@ -505,7 +550,7 @@ static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
_update_pll_mnp(pll, cfg);
if (pll->flags & TEGRA_PLL_HAS_CPCON)
if (pll->params->flags & TEGRA_PLL_HAS_CPCON)
_update_pll_cpcon(pll, cfg, rate);
if (state) {
@ -524,11 +569,11 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long flags = 0;
int ret = 0;
if (pll->flags & TEGRA_PLL_FIXED) {
if (rate != pll->fixed_rate) {
if (pll->params->flags & TEGRA_PLL_FIXED) {
if (rate != pll->params->fixed_rate) {
pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
__func__, __clk_get_name(hw->clk),
pll->fixed_rate, rate);
pll->params->fixed_rate, rate);
return -EINVAL;
}
return 0;
@ -536,6 +581,8 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
_calc_rate(hw, &cfg, rate, parent_rate)) {
pr_err("%s: Failed to set %s rate %lu\n", __func__,
__clk_get_name(hw->clk), rate);
WARN_ON(1);
return -EINVAL;
}
@ -559,18 +606,16 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
struct tegra_clk_pll *pll = to_clk_pll(hw);
struct tegra_clk_pll_freq_table cfg;
if (pll->flags & TEGRA_PLL_FIXED)
return pll->fixed_rate;
if (pll->params->flags & TEGRA_PLL_FIXED)
return pll->params->fixed_rate;
/* PLLM is used for memory; we do not change rate */
if (pll->flags & TEGRA_PLLM)
if (pll->params->flags & TEGRA_PLLM)
return __clk_get_rate(hw->clk);
if (_get_table_rate(hw, &cfg, rate, *prate) &&
_calc_rate(hw, &cfg, rate, *prate)) {
WARN_ON(1);
_calc_rate(hw, &cfg, rate, *prate))
return -EINVAL;
}
return cfg.output_rate;
}
@ -586,17 +631,19 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
val = pll_readl_base(pll);
if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
if ((pll->params->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
return parent_rate;
if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
if ((pll->params->flags & TEGRA_PLL_FIXED) &&
!(val & PLL_BASE_OVERRIDE)) {
struct tegra_clk_pll_freq_table sel;
if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {
if (_get_table_rate(hw, &sel, pll->params->fixed_rate,
parent_rate)) {
pr_err("Clock %s has unknown fixed frequency\n",
__clk_get_name(hw->clk));
BUG();
}
return pll->fixed_rate;
return pll->params->fixed_rate;
}
_get_pll_mnp(pll, &cfg);
@ -664,7 +711,7 @@ static int clk_plle_enable(struct clk_hw *hw)
u32 val;
int err;
if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
return -EINVAL;
clk_pll_disable(hw);
@ -680,7 +727,7 @@ static int clk_plle_enable(struct clk_hw *hw)
return err;
}
if (pll->flags & TEGRA_PLLE_CONFIGURE) {
if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {
/* configure dividers */
val = pll_readl_base(pll);
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
@ -744,7 +791,7 @@ const struct clk_ops tegra_clk_plle_ops = {
.enable = clk_plle_enable,
};
#ifdef CONFIG_ARCH_TEGRA_114_SOC
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
unsigned long parent_rate)
@ -755,6 +802,48 @@ static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
return 1;
}
static unsigned long _clip_vco_min(unsigned long vco_min,
unsigned long parent_rate)
{
return DIV_ROUND_UP(vco_min, parent_rate) * parent_rate;
}
static int _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
void __iomem *clk_base,
unsigned long parent_rate)
{
u32 val;
u32 step_a, step_b;
switch (parent_rate) {
case 12000000:
case 13000000:
case 26000000:
step_a = 0x2B;
step_b = 0x0B;
break;
case 16800000:
step_a = 0x1A;
step_b = 0x09;
break;
case 19200000:
step_a = 0x12;
step_b = 0x08;
break;
default:
pr_err("%s: Unexpected reference rate %lu\n",
__func__, parent_rate);
WARN_ON(1);
return -EINVAL;
}
val = step_a << pll_params->stepa_shift;
val |= step_b << pll_params->stepb_shift;
writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
return 0;
}
static int clk_pll_iddq_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
@ -1173,7 +1262,7 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
unsigned long flags = 0;
unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
return -EINVAL;
if (pll->lock)
@ -1217,6 +1306,18 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
if (ret < 0)
goto out;
val = pll_readl(PLLE_SS_CTRL, pll);
val &= ~(PLLE_SS_CNTL_CENTER | PLLE_SS_CNTL_INVERT);
val &= ~PLLE_SS_COEFFICIENTS_MASK;
val |= PLLE_SS_COEFFICIENTS_VAL;
pll_writel(val, PLLE_SS_CTRL, pll);
val &= ~(PLLE_SS_CNTL_SSC_BYP | PLLE_SS_CNTL_BYPASS_SS);
pll_writel(val, PLLE_SS_CTRL, pll);
udelay(1);
val &= ~PLLE_SS_CNTL_INTERP_RESET;
pll_writel(val, PLLE_SS_CTRL, pll);
udelay(1);
/* TODO: enable hw control of xusb brick pll */
out:
@ -1248,9 +1349,8 @@ static void clk_plle_tegra114_disable(struct clk_hw *hw)
#endif
static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
void __iomem *pmc, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
void __iomem *pmc, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
@ -1261,10 +1361,7 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
pll->clk_base = clk_base;
pll->pmc = pmc;
pll->freq_table = freq_table;
pll->params = pll_params;
pll->fixed_rate = fixed_rate;
pll->flags = pll_flags;
pll->lock = lock;
if (!pll_params->div_nmp)
@ -1293,17 +1390,15 @@ static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
unsigned long flags, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
pll_flags |= TEGRA_PLL_BYPASS;
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
freq_table, lock);
pll_params->flags |= TEGRA_PLL_BYPASS;
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
@ -1317,17 +1412,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
unsigned long flags, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
freq_table, lock);
pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
@ -1339,7 +1432,7 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
return clk;
}
#ifdef CONFIG_ARCH_TEGRA_114_SOC
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
const struct clk_ops tegra_clk_pllxc_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pll_iddq_enable,
@ -1386,21 +1479,46 @@ const struct clk_ops tegra_clk_plle_tegra114_ops = {
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
struct clk *clk, *parent;
unsigned long parent_rate;
int err;
u32 val, val_iddq;
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
name, parent_name);
return ERR_PTR(-EINVAL);
}
if (!pll_params->pdiv_tohw)
return ERR_PTR(-EINVAL);
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
freq_table, lock);
parent_rate = __clk_get_rate(parent);
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
err = _setup_dynamic_ramp(pll_params, clk_base, parent_rate);
if (err)
return ERR_PTR(err);
val = readl_relaxed(clk_base + pll_params->base_reg);
val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
if (val & PLL_BASE_ENABLE)
WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
else {
val_iddq |= BIT(pll_params->iddq_bit_idx);
writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
}
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
@ -1414,19 +1532,19 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock, unsigned long parent_rate)
{
u32 val;
struct tegra_clk_pll *pll;
struct clk *clk;
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
freq_table, lock);
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
@ -1461,23 +1579,32 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
struct clk *clk, *parent;
unsigned long parent_rate;
if (!pll_params->pdiv_tohw)
return ERR_PTR(-EINVAL);
pll_flags |= TEGRA_PLL_BYPASS;
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll_flags |= TEGRA_PLLM;
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
freq_table, lock);
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
name, parent_name);
return ERR_PTR(-EINVAL);
}
parent_rate = __clk_get_rate(parent);
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
pll_params->flags |= TEGRA_PLL_BYPASS;
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll_params->flags |= TEGRA_PLLM;
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
@ -1491,10 +1618,8 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock)
{
struct clk *parent, *clk;
@ -1507,20 +1632,21 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
return ERR_PTR(-EINVAL);
parent = __clk_lookup(parent_name);
if (IS_ERR(parent)) {
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
name, parent_name);
return ERR_PTR(-EINVAL);
}
pll_flags |= TEGRA_PLL_BYPASS;
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
freq_table, lock);
parent_rate = __clk_get_rate(parent);
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
pll_params->flags |= TEGRA_PLL_BYPASS;
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
parent_rate = __clk_get_rate(parent);
/*
* Most of PLLC register fields are shadowed, and can not be read
* directly from PLL h/w. Hence, actual PLLC boot state is unknown.
@ -1567,17 +1693,15 @@ struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
struct clk *tegra_clk_register_plle_tegra114(const char *name,
const char *parent_name,
void __iomem *clk_base, unsigned long flags,
unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk;
u32 val, val_aux;
pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params,
TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock);
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
@ -1587,11 +1711,13 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
val_aux = pll_readl(pll_params->aux_reg, pll);
if (val & PLL_BASE_ENABLE) {
if (!(val_aux & PLLE_AUX_PLLRE_SEL))
if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
(val_aux & PLLE_AUX_PLLP_SEL))
WARN(1, "pll_e enabled with unsupported parent %s\n",
(val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");
(val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
"pll_re_vco");
} else {
val_aux |= PLLE_AUX_PLLRE_SEL;
val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
pll_writel(val, pll_params->aux_reg, pll);
}
@ -1603,3 +1729,92 @@ struct clk *tegra_clk_register_plle_tegra114(const char *name,
return clk;
}
#endif
#ifdef CONFIG_ARCH_TEGRA_124_SOC
const struct clk_ops tegra_clk_pllss_ops = {
.is_enabled = clk_pll_is_enabled,
.enable = clk_pll_iddq_enable,
.disable = clk_pll_iddq_disable,
.recalc_rate = clk_pll_recalc_rate,
.round_rate = clk_pll_ramp_round_rate,
.set_rate = clk_pllxc_set_rate,
};
struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
void __iomem *clk_base, unsigned long flags,
struct tegra_clk_pll_params *pll_params,
spinlock_t *lock)
{
struct tegra_clk_pll *pll;
struct clk *clk, *parent;
struct tegra_clk_pll_freq_table cfg;
unsigned long parent_rate;
u32 val;
int i;
if (!pll_params->div_nmp)
return ERR_PTR(-EINVAL);
parent = __clk_lookup(parent_name);
if (!parent) {
WARN(1, "parent clk %s of %s must be registered first\n",
name, parent_name);
return ERR_PTR(-EINVAL);
}
pll_params->flags = TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_USE_LOCK;
pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
val = pll_readl_base(pll);
val &= ~PLLSS_REF_SRC_SEL_MASK;
pll_writel_base(val, pll);
parent_rate = __clk_get_rate(parent);
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
/* initialize PLL to minimum rate */
cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
cfg.n = cfg.m * pll_params->vco_min / parent_rate;
for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++)
;
if (!i) {
kfree(pll);
return ERR_PTR(-EINVAL);
}
cfg.p = pll_params->pdiv_tohw[i-1].hw_val;
_update_pll_mnp(pll, &cfg);
pll_writel_misc(PLLSS_MISC_DEFAULT, pll);
pll_writel(PLLSS_CFG_DEFAULT, pll_params->ext_misc_reg[0], pll);
pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[1], pll);
pll_writel(PLLSS_CTRL1_DEFAULT, pll_params->ext_misc_reg[2], pll);
val = pll_readl_base(pll);
if (val & PLL_BASE_ENABLE) {
if (val & BIT(pll_params->iddq_bit_idx)) {
WARN(1, "%s is on but IDDQ set\n", name);
kfree(pll);
return ERR_PTR(-EINVAL);
}
} else
val |= BIT(pll_params->iddq_bit_idx);
val &= ~PLLSS_LOCK_OVERRIDE;
pll_writel_base(val, pll);
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
&tegra_clk_pllss_ops);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
#endif

View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2012, 2013, 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/>.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clk/tegra.h>
#include "clk.h"
#include "clk-id.h"
#define AUDIO_SYNC_CLK_I2S0 0x4a0
#define AUDIO_SYNC_CLK_I2S1 0x4a4
#define AUDIO_SYNC_CLK_I2S2 0x4a8
#define AUDIO_SYNC_CLK_I2S3 0x4ac
#define AUDIO_SYNC_CLK_I2S4 0x4b0
#define AUDIO_SYNC_CLK_SPDIF 0x4b4
#define AUDIO_SYNC_DOUBLER 0x49c
#define PLLA_OUT 0xb4
struct tegra_sync_source_initdata {
char *name;
unsigned long rate;
unsigned long max_rate;
int clk_id;
};
#define SYNC(_name) \
{\
.name = #_name,\
.rate = 24000000,\
.max_rate = 24000000,\
.clk_id = tegra_clk_ ## _name,\
}
struct tegra_audio_clk_initdata {
char *gate_name;
char *mux_name;
u32 offset;
int gate_clk_id;
int mux_clk_id;
};
#define AUDIO(_name, _offset) \
{\
.gate_name = #_name,\
.mux_name = #_name"_mux",\
.offset = _offset,\
.gate_clk_id = tegra_clk_ ## _name,\
.mux_clk_id = tegra_clk_ ## _name ## _mux,\
}
struct tegra_audio2x_clk_initdata {
char *parent;
char *gate_name;
char *name_2x;
char *div_name;
int clk_id;
int clk_num;
u8 div_offset;
};
#define AUDIO2X(_name, _num, _offset) \
{\
.parent = #_name,\
.gate_name = #_name"_2x",\
.name_2x = #_name"_doubler",\
.div_name = #_name"_div",\
.clk_id = tegra_clk_ ## _name ## _2x,\
.clk_num = _num,\
.div_offset = _offset,\
}
static DEFINE_SPINLOCK(clk_doubler_lock);
static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
};
static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {
SYNC(spdif_in_sync),
SYNC(i2s0_sync),
SYNC(i2s1_sync),
SYNC(i2s2_sync),
SYNC(i2s3_sync),
SYNC(i2s4_sync),
SYNC(vimclk_sync),
};
static struct tegra_audio_clk_initdata audio_clks[] = {
AUDIO(audio0, AUDIO_SYNC_CLK_I2S0),
AUDIO(audio1, AUDIO_SYNC_CLK_I2S1),
AUDIO(audio2, AUDIO_SYNC_CLK_I2S2),
AUDIO(audio3, AUDIO_SYNC_CLK_I2S3),
AUDIO(audio4, AUDIO_SYNC_CLK_I2S4),
AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),
};
static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
AUDIO2X(audio0, 113, 24),
AUDIO2X(audio1, 114, 25),
AUDIO2X(audio2, 115, 26),
AUDIO2X(audio3, 116, 27),
AUDIO2X(audio4, 117, 28),
AUDIO2X(spdif, 118, 29),
};
void __init tegra_audio_clk_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_a_params)
{
struct clk *clk;
struct clk **dt_clk;
int i;
/* PLLA */
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks);
if (dt_clk) {
clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base,
pmc_base, 0, pll_a_params, NULL);
*dt_clk = clk;
}
/* PLLA_OUT0 */
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks);
if (dt_clk) {
clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
8, 8, 1, NULL);
clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
CLK_SET_RATE_PARENT, 0, NULL);
*dt_clk = clk;
}
for (i = 0; i < ARRAY_SIZE(sync_source_clks); i++) {
struct tegra_sync_source_initdata *data;
data = &sync_source_clks[i];
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
if (!dt_clk)
continue;
clk = tegra_clk_register_sync_source(data->name,
data->rate, data->max_rate);
*dt_clk = clk;
}
for (i = 0; i < ARRAY_SIZE(audio_clks); i++) {
struct tegra_audio_clk_initdata *data;
data = &audio_clks[i];
dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
if (!dt_clk)
continue;
clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk,
ARRAY_SIZE(mux_audio_sync_clk),
CLK_SET_RATE_NO_REPARENT,
clk_base + data->offset, 0, 3, 0,
NULL);
*dt_clk = clk;
dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
if (!dt_clk)
continue;
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
0, clk_base + data->offset, 4,
CLK_GATE_SET_TO_DISABLE, NULL);
*dt_clk = clk;
}
for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) {
struct tegra_audio2x_clk_initdata *data;
data = &audio2x_clks[i];
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
if (!dt_clk)
continue;
clk = clk_register_fixed_factor(NULL, data->name_2x,
data->parent, CLK_SET_RATE_PARENT, 2, 1);
clk = tegra_clk_register_divider(data->div_name,
data->name_2x, clk_base + AUDIO_SYNC_DOUBLER,
0, 0, data->div_offset, 1, 0,
&clk_doubler_lock);
clk = tegra_clk_register_periph_gate(data->gate_name,
data->div_name, TEGRA_PERIPH_NO_RESET,
clk_base, CLK_SET_RATE_PARENT, data->clk_num,
periph_clk_enb_refcnt);
*dt_clk = clk;
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2012, 2013, 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/>.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clk/tegra.h>
#include "clk.h"
#include "clk-id.h"
#define OSC_CTRL 0x50
#define OSC_CTRL_OSC_FREQ_SHIFT 28
#define OSC_CTRL_PLL_REF_DIV_SHIFT 26
int __init tegra_osc_clk_init(void __iomem *clk_base,
struct tegra_clk *tegra_clks,
unsigned long *input_freqs, int num,
unsigned long *osc_freq,
unsigned long *pll_ref_freq)
{
struct clk *clk;
struct clk **dt_clk;
u32 val, pll_ref_div;
unsigned osc_idx;
val = readl_relaxed(clk_base + OSC_CTRL);
osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
if (osc_idx < num)
*osc_freq = input_freqs[osc_idx];
else
*osc_freq = 0;
if (!*osc_freq) {
WARN_ON(1);
return -EINVAL;
}
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks);
if (!dt_clk)
return 0;
clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
*osc_freq);
*dt_clk = clk;
/* pll_ref */
val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
pll_ref_div = 1 << val;
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks);
if (!dt_clk)
return 0;
clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
0, 1, pll_ref_div);
*dt_clk = clk;
if (pll_ref_freq)
*pll_ref_freq = *osc_freq / pll_ref_div;
return 0;
}
void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
{
struct clk *clk;
struct clk **dt_clk;
/* clk_32k */
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);
if (dt_clk) {
clk = clk_register_fixed_rate(NULL, "clk_32k", NULL,
CLK_IS_ROOT, 32768);
*dt_clk = clk;
}
/* clk_m_div2 */
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div2, tegra_clks);
if (dt_clk) {
clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
CLK_SET_RATE_PARENT, 1, 2);
*dt_clk = clk;
}
/* clk_m_div4 */
dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m_div4, tegra_clks);
if (dt_clk) {
clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
CLK_SET_RATE_PARENT, 1, 4);
*dt_clk = clk;
}
}

View File

@ -0,0 +1,674 @@
/*
* Copyright (c) 2012, 2013, 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/>.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clk/tegra.h>
#include "clk.h"
#include "clk-id.h"
#define CLK_SOURCE_I2S0 0x1d8
#define CLK_SOURCE_I2S1 0x100
#define CLK_SOURCE_I2S2 0x104
#define CLK_SOURCE_NDFLASH 0x160
#define CLK_SOURCE_I2S3 0x3bc
#define CLK_SOURCE_I2S4 0x3c0
#define CLK_SOURCE_SPDIF_OUT 0x108
#define CLK_SOURCE_SPDIF_IN 0x10c
#define CLK_SOURCE_PWM 0x110
#define CLK_SOURCE_ADX 0x638
#define CLK_SOURCE_ADX1 0x670
#define CLK_SOURCE_AMX 0x63c
#define CLK_SOURCE_AMX1 0x674
#define CLK_SOURCE_HDA 0x428
#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
#define CLK_SOURCE_SBC1 0x134
#define CLK_SOURCE_SBC2 0x118
#define CLK_SOURCE_SBC3 0x11c
#define CLK_SOURCE_SBC4 0x1b4
#define CLK_SOURCE_SBC5 0x3c8
#define CLK_SOURCE_SBC6 0x3cc
#define CLK_SOURCE_SATA_OOB 0x420
#define CLK_SOURCE_SATA 0x424
#define CLK_SOURCE_NDSPEED 0x3f8
#define CLK_SOURCE_VFIR 0x168
#define CLK_SOURCE_SDMMC1 0x150
#define CLK_SOURCE_SDMMC2 0x154
#define CLK_SOURCE_SDMMC3 0x1bc
#define CLK_SOURCE_SDMMC4 0x164
#define CLK_SOURCE_CVE 0x140
#define CLK_SOURCE_TVO 0x188
#define CLK_SOURCE_TVDAC 0x194
#define CLK_SOURCE_VDE 0x1c8
#define CLK_SOURCE_CSITE 0x1d4
#define CLK_SOURCE_LA 0x1f8
#define CLK_SOURCE_TRACE 0x634
#define CLK_SOURCE_OWR 0x1cc
#define CLK_SOURCE_NOR 0x1d0
#define CLK_SOURCE_MIPI 0x174
#define CLK_SOURCE_I2C1 0x124
#define CLK_SOURCE_I2C2 0x198
#define CLK_SOURCE_I2C3 0x1b8
#define CLK_SOURCE_I2C4 0x3c4
#define CLK_SOURCE_I2C5 0x128
#define CLK_SOURCE_I2C6 0x65c
#define CLK_SOURCE_UARTA 0x178
#define CLK_SOURCE_UARTB 0x17c
#define CLK_SOURCE_UARTC 0x1a0
#define CLK_SOURCE_UARTD 0x1c0
#define CLK_SOURCE_UARTE 0x1c4
#define CLK_SOURCE_3D 0x158
#define CLK_SOURCE_2D 0x15c
#define CLK_SOURCE_MPE 0x170
#define CLK_SOURCE_UARTE 0x1c4
#define CLK_SOURCE_VI_SENSOR 0x1a8
#define CLK_SOURCE_VI 0x148
#define CLK_SOURCE_EPP 0x16c
#define CLK_SOURCE_MSENC 0x1f0
#define CLK_SOURCE_TSEC 0x1f4
#define CLK_SOURCE_HOST1X 0x180
#define CLK_SOURCE_HDMI 0x18c
#define CLK_SOURCE_DISP1 0x138
#define CLK_SOURCE_DISP2 0x13c
#define CLK_SOURCE_CILAB 0x614
#define CLK_SOURCE_CILCD 0x618
#define CLK_SOURCE_CILE 0x61c
#define CLK_SOURCE_DSIALP 0x620
#define CLK_SOURCE_DSIBLP 0x624
#define CLK_SOURCE_TSENSOR 0x3b8
#define CLK_SOURCE_D_AUDIO 0x3d0
#define CLK_SOURCE_DAM0 0x3d8
#define CLK_SOURCE_DAM1 0x3dc
#define CLK_SOURCE_DAM2 0x3e0
#define CLK_SOURCE_ACTMON 0x3e8
#define CLK_SOURCE_EXTERN1 0x3ec
#define CLK_SOURCE_EXTERN2 0x3f0
#define CLK_SOURCE_EXTERN3 0x3f4
#define CLK_SOURCE_I2CSLOW 0x3fc
#define CLK_SOURCE_SE 0x42c
#define CLK_SOURCE_MSELECT 0x3b4
#define CLK_SOURCE_DFLL_REF 0x62c
#define CLK_SOURCE_DFLL_SOC 0x630
#define CLK_SOURCE_SOC_THERM 0x644
#define CLK_SOURCE_XUSB_HOST_SRC 0x600
#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
#define CLK_SOURCE_XUSB_FS_SRC 0x608
#define CLK_SOURCE_XUSB_SS_SRC 0x610
#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
#define CLK_SOURCE_ISP 0x144
#define CLK_SOURCE_SOR0 0x414
#define CLK_SOURCE_DPAUX 0x418
#define CLK_SOURCE_SATA_OOB 0x420
#define CLK_SOURCE_SATA 0x424
#define CLK_SOURCE_ENTROPY 0x628
#define CLK_SOURCE_VI_SENSOR2 0x658
#define CLK_SOURCE_HDMI_AUDIO 0x668
#define CLK_SOURCE_VIC03 0x678
#define CLK_SOURCE_CLK72MHZ 0x66c
#define MASK(x) (BIT(x) - 1)
#define MUX(_name, _parents, _offset, \
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, \
_clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
NULL)
#define MUX_FLAGS(_name, _parents, _offset,\
_clk_num, _gate_flags, _clk_id, flags)\
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
_clk_num, _gate_flags, _clk_id, _parents##_idx, flags,\
NULL)
#define MUX8(_name, _parents, _offset, \
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
_clk_num, _gate_flags, _clk_id, _parents##_idx, 0,\
NULL)
#define MUX8_NOGATE_LOCK(_name, _parents, _offset, _clk_id, _lock) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
0, TEGRA_PERIPH_NO_GATE, _clk_id,\
_parents##_idx, 0, _lock)
#define INT(_name, _parents, _offset, \
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
_clk_id, _parents##_idx, 0, NULL)
#define INT_FLAGS(_name, _parents, _offset,\
_clk_num, _gate_flags, _clk_id, flags)\
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
_clk_id, _parents##_idx, flags, NULL)
#define INT8(_name, _parents, _offset,\
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
_clk_id, _parents##_idx, 0, NULL)
#define UART(_name, _parents, _offset,\
_clk_num, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \
TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
_parents##_idx, 0, NULL)
#define I2C(_name, _parents, _offset,\
_clk_num, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\
_clk_num, 0, _clk_id, _parents##_idx, 0, NULL)
#define XUSB(_name, _parents, _offset, \
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset, \
29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT| \
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags,\
_clk_id, _parents##_idx, 0, NULL)
#define AUDIO(_name, _offset, _clk_num,\
_gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, mux_d_audio_clk, \
_offset, 16, 0xE01F, 0, 0, 8, 1, \
TEGRA_DIVIDER_ROUND_UP, _clk_num, _gate_flags, \
_clk_id, mux_d_audio_clk_idx, 0, NULL)
#define NODIV(_name, _parents, _offset, \
_mux_shift, _mux_mask, _clk_num, \
_gate_flags, _clk_id, _lock) \
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
_mux_shift, _mux_mask, 0, 0, 0, 0, 0,\
_clk_num, (_gate_flags) | TEGRA_PERIPH_NO_DIV,\
_clk_id, _parents##_idx, 0, _lock)
#define GATE(_name, _parent_name, \
_clk_num, _gate_flags, _clk_id, _flags) \
{ \
.name = _name, \
.clk_id = _clk_id, \
.p.parent_name = _parent_name, \
.periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 0, 0, 0, \
_clk_num, _gate_flags, 0, NULL), \
.flags = _flags \
}
#define PLLP_BASE 0xa0
#define PLLP_MISC 0xac
#define PLLP_OUTA 0xa4
#define PLLP_OUTB 0xa8
#define PLLP_OUTC 0x67c
#define PLL_BASE_LOCK BIT(27)
#define PLL_MISC_LOCK_ENABLE 18
static DEFINE_SPINLOCK(PLLP_OUTA_lock);
static DEFINE_SPINLOCK(PLLP_OUTB_lock);
static DEFINE_SPINLOCK(PLLP_OUTC_lock);
static DEFINE_SPINLOCK(sor0_lock);
#define MUX_I2S_SPDIF(_id) \
static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
#_id, "pll_p",\
"clk_m"};
MUX_I2S_SPDIF(audio0)
MUX_I2S_SPDIF(audio1)
MUX_I2S_SPDIF(audio2)
MUX_I2S_SPDIF(audio3)
MUX_I2S_SPDIF(audio4)
MUX_I2S_SPDIF(audio)
#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
static const char *mux_pllp_pllc_pllm_clkm[] = {
"pll_p", "pll_c", "pll_m", "clk_m"
};
#define mux_pllp_pllc_pllm_clkm_idx NULL
static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
#define mux_pllp_pllc_pllm_idx NULL
static const char *mux_pllp_pllc_clk32_clkm[] = {
"pll_p", "pll_c", "clk_32k", "clk_m"
};
#define mux_pllp_pllc_clk32_clkm_idx NULL
static const char *mux_plla_pllc_pllp_clkm[] = {
"pll_a_out0", "pll_c", "pll_p", "clk_m"
};
#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
"pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
};
static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
};
static const char *mux_pllp_clkm[] = {
"pll_p", "clk_m"
};
static u32 mux_pllp_clkm_idx[] = {
[0] = 0, [1] = 3,
};
static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
};
#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
"pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
"pll_d2_out0", "clk_m"
};
#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
static const char *mux_pllm_pllc_pllp_plla[] = {
"pll_m", "pll_c", "pll_p", "pll_a_out0"
};
#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
static const char *mux_pllp_pllc_clkm[] = {
"pll_p", "pll_c", "pll_m"
};
static u32 mux_pllp_pllc_clkm_idx[] = {
[0] = 0, [1] = 1, [2] = 3,
};
static const char *mux_pllp_pllc_clkm_clk32[] = {
"pll_p", "pll_c", "clk_m", "clk_32k"
};
#define mux_pllp_pllc_clkm_clk32_idx NULL
static const char *mux_plla_clk32_pllp_clkm_plle[] = {
"pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
};
#define mux_plla_clk32_pllp_clkm_plle_idx NULL
static const char *mux_clkm_pllp_pllc_pllre[] = {
"clk_m", "pll_p", "pll_c", "pll_re_out"
};
static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
[0] = 0, [1] = 1, [2] = 3, [3] = 5,
};
static const char *mux_clkm_48M_pllp_480M[] = {
"clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
};
#define mux_clkm_48M_pllp_480M_idx NULL
static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
"clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
};
static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
};
static const char *mux_d_audio_clk[] = {
"pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
};
static u32 mux_d_audio_clk_idx[] = {
[0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
[5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
};
static const char *mux_pllp_plld_pllc_clkm[] = {
"pll_p", "pll_d_out0", "pll_c", "clk_m"
};
#define mux_pllp_plld_pllc_clkm_idx NULL
static const char *mux_pllm_pllc_pllp_plla_clkm_pllc4[] = {
"pll_m", "pll_c", "pll_p", "pll_a_out0", "clk_m", "pll_c4",
};
static u32 mux_pllm_pllc_pllp_plla_clkm_pllc4_idx[] = {
[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 6, [5] = 7,
};
static const char *mux_pllp_clkm1[] = {
"pll_p", "clk_m",
};
#define mux_pllp_clkm1_idx NULL
static const char *mux_pllp3_pllc_clkm[] = {
"pll_p_out3", "pll_c", "pll_c2", "clk_m",
};
#define mux_pllp3_pllc_clkm_idx NULL
static const char *mux_pllm_pllc_pllp_plla_pllc2_c3_clkm[] = {
"pll_m", "pll_c", "pll_p", "pll_a", "pll_c2", "pll_c3", "clk_m"
};
static u32 mux_pllm_pllc_pllp_plla_pllc2_c3_clkm_idx[] = {
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
};
static const char *mux_pllm_pllc2_c_c3_pllp_plla_pllc4[] = {
"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0", "pll_c4",
};
static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = {
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7,
};
static const char *mux_clkm_plldp_sor0lvds[] = {
"clk_m", "pll_dp", "sor0_lvds",
};
#define mux_clkm_plldp_sor0lvds_idx NULL
static struct tegra_periph_init_data periph_clks[] = {
AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio),
AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0),
AUDIO("dam1", CLK_SOURCE_DAM1, 109, TEGRA_PERIPH_ON_APB, tegra_clk_dam1),
AUDIO("dam2", CLK_SOURCE_DAM2, 110, TEGRA_PERIPH_ON_APB, tegra_clk_dam2),
I2C("i2c1", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, tegra_clk_i2c1),
I2C("i2c2", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, tegra_clk_i2c2),
I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3),
I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4),
I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5),
INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde),
INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi),
INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp),
INT("host1x", mux_pllm_pllc_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x),
INT("mpe", mux_pllm_pllc_pllp_plla, CLK_SOURCE_MPE, 60, 0, tegra_clk_mpe),
INT("2d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d),
INT("3d", mux_pllm_pllc_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d),
INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8),
INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8),
INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9),
INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8),
INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc),
INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec),
INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED),
MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0),
MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1),
MUX("i2s2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, TEGRA_PERIPH_ON_APB, tegra_clk_i2s2),
MUX("i2s3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, TEGRA_PERIPH_ON_APB, tegra_clk_i2s3),
MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4),
MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out),
MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in),
MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm),
MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx),
MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx),
MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda),
MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, 0, tegra_clk_sdmmc1),
MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, 0, tegra_clk_sdmmc2),
MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, 0, tegra_clk_sdmmc3),
MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, 0, tegra_clk_sdmmc4),
MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la),
MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace),
MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr),
MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor),
MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi),
MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor),
MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab),
MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd),
MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile),
MUX("dsialp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, 0, tegra_clk_dsialp),
MUX("dsiblp", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, 0, tegra_clk_dsiblp),
MUX("tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, TEGRA_PERIPH_ON_APB, tegra_clk_tsensor),
MUX("actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, 0, tegra_clk_actmon),
MUX("dfll_ref", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_ref),
MUX("dfll_soc", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, TEGRA_PERIPH_ON_APB, tegra_clk_dfll_soc),
MUX("i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, TEGRA_PERIPH_ON_APB, tegra_clk_i2cslow),
MUX("sbc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1),
MUX("sbc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2),
MUX("sbc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3),
MUX("sbc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4),
MUX("sbc5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5),
MUX("sbc6", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6),
MUX("cve", mux_pllp_plld_pllc_clkm, CLK_SOURCE_CVE, 49, 0, tegra_clk_cve),
MUX("tvo", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVO, 49, 0, tegra_clk_tvo),
MUX("tvdac", mux_pllp_plld_pllc_clkm, CLK_SOURCE_TVDAC, 53, 0, tegra_clk_tvdac),
MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash),
MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed),
MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob),
MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
MUX8("sbc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_8),
MUX8("sbc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_8),
MUX8("sbc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_8),
MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8),
MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8),
MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8),
MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1),
MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy),
MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz),
MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock),
MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED),
NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL),
NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL),
NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock),
UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta),
UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 65, tegra_clk_uarte),
XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src),
XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
};
static struct tegra_periph_init_data gate_clks[] = {
GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0),
GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0),
GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0),
GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0),
GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0),
GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0),
GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0),
GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0),
GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0),
GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0),
GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0),
GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0),
GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0),
GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0),
GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0),
GATE("dtv", "clk_m", 79, TEGRA_PERIPH_ON_APB, tegra_clk_dtv, 0),
GATE("xusb_host", "xusb_host_src", 89, 0, tegra_clk_xusb_host, 0),
GATE("xusb_ss", "xusb_ss_src", 156, 0, tegra_clk_xusb_ss, 0),
GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
GATE("dsia", "dsia_mux", 48, 0, tegra_clk_dsia, 0),
GATE("dsib", "dsib_mux", 82, 0, tegra_clk_dsib, 0),
GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
};
struct pll_out_data {
char *div_name;
char *pll_out_name;
u32 offset;
int clk_id;
u8 div_shift;
u8 div_flags;
u8 rst_shift;
spinlock_t *lock;
};
#define PLL_OUT(_num, _offset, _div_shift, _div_flags, _rst_shift, _id) \
{\
.div_name = "pll_p_out" #_num "_div",\
.pll_out_name = "pll_p_out" #_num,\
.offset = _offset,\
.div_shift = _div_shift,\
.div_flags = _div_flags | TEGRA_DIVIDER_FIXED |\
TEGRA_DIVIDER_ROUND_UP,\
.rst_shift = _rst_shift,\
.clk_id = tegra_clk_ ## _id,\
.lock = &_offset ##_lock,\
}
static struct pll_out_data pllp_out_clks[] = {
PLL_OUT(1, PLLP_OUTA, 8, 0, 0, pll_p_out1),
PLL_OUT(2, PLLP_OUTA, 24, 0, 16, pll_p_out2),
PLL_OUT(2, PLLP_OUTA, 24, TEGRA_DIVIDER_INT, 16, pll_p_out2_int),
PLL_OUT(3, PLLP_OUTB, 8, 0, 0, pll_p_out3),
PLL_OUT(4, PLLP_OUTB, 24, 0, 16, pll_p_out4),
PLL_OUT(5, PLLP_OUTC, 24, 0, 16, pll_p_out5),
};
static void __init periph_clk_init(void __iomem *clk_base,
struct tegra_clk *tegra_clks)
{
int i;
struct clk *clk;
struct clk **dt_clk;
for (i = 0; i < ARRAY_SIZE(periph_clks); i++) {
struct tegra_clk_periph_regs *bank;
struct tegra_periph_init_data *data;
data = periph_clks + i;
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
if (!dt_clk)
continue;
bank = get_reg_bank(data->periph.gate.clk_num);
if (!bank)
continue;
data->periph.gate.regs = bank;
clk = tegra_clk_register_periph(data->name,
data->p.parent_names, data->num_parents,
&data->periph, clk_base, data->offset,
data->flags);
*dt_clk = clk;
}
}
static void __init gate_clk_init(void __iomem *clk_base,
struct tegra_clk *tegra_clks)
{
int i;
struct clk *clk;
struct clk **dt_clk;
for (i = 0; i < ARRAY_SIZE(gate_clks); i++) {
struct tegra_periph_init_data *data;
data = gate_clks + i;
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
if (!dt_clk)
continue;
clk = tegra_clk_register_periph_gate(data->name,
data->p.parent_name, data->periph.gate.flags,
clk_base, data->flags,
data->periph.gate.clk_num,
periph_clk_enb_refcnt);
*dt_clk = clk;
}
}
static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params)
{
struct clk *clk;
struct clk **dt_clk;
int i;
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p, tegra_clks);
if (dt_clk) {
/* PLLP */
clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base,
pmc_base, 0, pll_params, NULL);
clk_register_clkdev(clk, "pll_p", NULL);
*dt_clk = clk;
}
for (i = 0; i < ARRAY_SIZE(pllp_out_clks); i++) {
struct pll_out_data *data;
data = pllp_out_clks + i;
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
if (!dt_clk)
continue;
clk = tegra_clk_register_divider(data->div_name, "pll_p",
clk_base + data->offset, 0, data->div_flags,
data->div_shift, 8, 1, data->lock);
clk = tegra_clk_register_pll_out(data->pll_out_name,
data->div_name, clk_base + data->offset,
data->rst_shift + 1, data->rst_shift,
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
data->lock);
*dt_clk = clk;
}
}
void __init tegra_periph_clk_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params)
{
init_pllp(clk_base, pmc_base, tegra_clks, pll_params);
periph_clk_init(clk_base, tegra_clks);
gate_clk_init(clk_base, tegra_clks);
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2012, 2013, 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/>.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clk/tegra.h>
#include "clk.h"
#include "clk-id.h"
#define PMC_CLK_OUT_CNTRL 0x1a8
#define PMC_DPD_PADS_ORIDE 0x1c
#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
#define PMC_CTRL 0
#define PMC_CTRL_BLINK_ENB 7
#define PMC_BLINK_TIMER 0x40
struct pmc_clk_init_data {
char *mux_name;
char *gate_name;
const char **parents;
int num_parents;
int mux_id;
int gate_id;
char *dev_name;
u8 mux_shift;
u8 gate_shift;
};
#define PMC_CLK(_num, _mux_shift, _gate_shift)\
{\
.mux_name = "clk_out_" #_num "_mux",\
.gate_name = "clk_out_" #_num,\
.parents = clk_out ##_num ##_parents,\
.num_parents = ARRAY_SIZE(clk_out ##_num ##_parents),\
.mux_id = tegra_clk_clk_out_ ##_num ##_mux,\
.gate_id = tegra_clk_clk_out_ ##_num,\
.dev_name = "extern" #_num,\
.mux_shift = _mux_shift,\
.gate_shift = _gate_shift,\
}
static DEFINE_SPINLOCK(clk_out_lock);
static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
"clk_m_div4", "extern1",
};
static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
"clk_m_div4", "extern2",
};
static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
"clk_m_div4", "extern3",
};
static struct pmc_clk_init_data pmc_clks[] = {
PMC_CLK(1, 6, 2),
PMC_CLK(2, 14, 10),
PMC_CLK(3, 22, 18),
};
void __init tegra_pmc_clk_init(void __iomem *pmc_base,
struct tegra_clk *tegra_clks)
{
struct clk *clk;
struct clk **dt_clk;
int i;
for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) {
struct pmc_clk_init_data *data;
data = pmc_clks + i;
dt_clk = tegra_lookup_dt_id(data->mux_id, tegra_clks);
if (!dt_clk)
continue;
clk = clk_register_mux(NULL, data->mux_name, data->parents,
data->num_parents, CLK_SET_RATE_NO_REPARENT,
pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
3, 0, &clk_out_lock);
*dt_clk = clk;
dt_clk = tegra_lookup_dt_id(data->gate_id, tegra_clks);
if (!dt_clk)
continue;
clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
0, pmc_base + PMC_CLK_OUT_CNTRL,
data->gate_shift, 0, &clk_out_lock);
*dt_clk = clk;
clk_register_clkdev(clk, data->dev_name, data->gate_name);
}
/* blink */
writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
pmc_base + PMC_DPD_PADS_ORIDE,
PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
dt_clk = tegra_lookup_dt_id(tegra_clk_blink, tegra_clks);
if (!dt_clk)
return;
clk = clk_register_gate(NULL, "blink", "blink_override", 0,
pmc_base + PMC_CTRL,
PMC_CTRL_BLINK_ENB, 0, NULL);
clk_register_clkdev(clk, "blink", NULL);
*dt_clk = clk;
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2012, 2013, 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/>.
*/
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/clk/tegra.h>
#include "clk.h"
#include "clk-id.h"
#define PLLX_BASE 0xe0
#define PLLX_MISC 0xe4
#define PLLX_MISC2 0x514
#define PLLX_MISC3 0x518
#define CCLKG_BURST_POLICY 0x368
#define CCLKLP_BURST_POLICY 0x370
#define SCLK_BURST_POLICY 0x028
#define SYSTEM_CLK_RATE 0x030
static DEFINE_SPINLOCK(sysrate_lock);
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
"pll_p", "pll_p_out2", "unused",
"clk_32k", "pll_m_out1" };
static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
"pll_p", "pll_p_out4", "unused",
"unused", "pll_x" };
static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
"pll_p", "pll_p_out4", "unused",
"unused", "pll_x", "pll_x_out0" };
static void __init tegra_sclk_init(void __iomem *clk_base,
struct tegra_clk *tegra_clks)
{
struct clk *clk;
struct clk **dt_clk;
/* SCLK */
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
if (dt_clk) {
clk = tegra_clk_register_super_mux("sclk", sclk_parents,
ARRAY_SIZE(sclk_parents),
CLK_SET_RATE_PARENT,
clk_base + SCLK_BURST_POLICY,
0, 4, 0, 0, NULL);
*dt_clk = clk;
}
/* HCLK */
dt_clk = tegra_lookup_dt_id(tegra_clk_hclk, tegra_clks);
if (dt_clk) {
clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
&sysrate_lock);
clk = clk_register_gate(NULL, "hclk", "hclk_div",
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
clk_base + SYSTEM_CLK_RATE,
7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
*dt_clk = clk;
}
/* PCLK */
dt_clk = tegra_lookup_dt_id(tegra_clk_pclk, tegra_clks);
if (!dt_clk)
return;
clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
&sysrate_lock);
clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
*dt_clk = clk;
}
void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
void __iomem *pmc_base,
struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *params)
{
struct clk *clk;
struct clk **dt_clk;
/* CCLKG */
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
if (dt_clk) {
clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
ARRAY_SIZE(cclk_g_parents),
CLK_SET_RATE_PARENT,
clk_base + CCLKG_BURST_POLICY,
0, 4, 0, 0, NULL);
*dt_clk = clk;
}
/* CCLKLP */
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
if (dt_clk) {
clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
ARRAY_SIZE(cclk_lp_parents),
CLK_SET_RATE_PARENT,
clk_base + CCLKLP_BURST_POLICY,
0, 4, 8, 9, NULL);
*dt_clk = clk;
}
tegra_sclk_init(clk_base, tegra_clks);
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
/* PLLX */
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
if (!dt_clk)
return;
clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
pmc_base, CLK_IGNORE_UNUSED, params, NULL);
*dt_clk = clk;
/* PLLX_OUT0 */
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x_out0, tegra_clks);
if (!dt_clk)
return;
clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
CLK_SET_RATE_PARENT, 1, 2);
*dt_clk = clk;
#endif
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -21,10 +21,139 @@
#include "clk.h"
#define CLK_OUT_ENB_L 0x010
#define CLK_OUT_ENB_H 0x014
#define CLK_OUT_ENB_U 0x018
#define CLK_OUT_ENB_V 0x360
#define CLK_OUT_ENB_W 0x364
#define CLK_OUT_ENB_X 0x280
#define CLK_OUT_ENB_SET_L 0x320
#define CLK_OUT_ENB_CLR_L 0x324
#define CLK_OUT_ENB_SET_H 0x328
#define CLK_OUT_ENB_CLR_H 0x32c
#define CLK_OUT_ENB_SET_U 0x330
#define CLK_OUT_ENB_CLR_U 0x334
#define CLK_OUT_ENB_SET_V 0x440
#define CLK_OUT_ENB_CLR_V 0x444
#define CLK_OUT_ENB_SET_W 0x448
#define CLK_OUT_ENB_CLR_W 0x44c
#define CLK_OUT_ENB_SET_X 0x284
#define CLK_OUT_ENB_CLR_X 0x288
#define RST_DEVICES_L 0x004
#define RST_DEVICES_H 0x008
#define RST_DEVICES_U 0x00C
#define RST_DFLL_DVCO 0x2F4
#define RST_DEVICES_V 0x358
#define RST_DEVICES_W 0x35C
#define RST_DEVICES_X 0x28C
#define RST_DEVICES_SET_L 0x300
#define RST_DEVICES_CLR_L 0x304
#define RST_DEVICES_SET_H 0x308
#define RST_DEVICES_CLR_H 0x30c
#define RST_DEVICES_SET_U 0x310
#define RST_DEVICES_CLR_U 0x314
#define RST_DEVICES_SET_V 0x430
#define RST_DEVICES_CLR_V 0x434
#define RST_DEVICES_SET_W 0x438
#define RST_DEVICES_CLR_W 0x43c
#define RST_DEVICES_SET_X 0x290
#define RST_DEVICES_CLR_X 0x294
/* Global data of Tegra CPU CAR ops */
static struct tegra_cpu_car_ops dummy_car_ops;
struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
int *periph_clk_enb_refcnt;
static int periph_banks;
static struct clk **clks;
static int clk_num;
static struct clk_onecell_data clk_data;
static struct tegra_clk_periph_regs periph_regs[] = {
[0] = {
.enb_reg = CLK_OUT_ENB_L,
.enb_set_reg = CLK_OUT_ENB_SET_L,
.enb_clr_reg = CLK_OUT_ENB_CLR_L,
.rst_reg = RST_DEVICES_L,
.rst_set_reg = RST_DEVICES_SET_L,
.rst_clr_reg = RST_DEVICES_CLR_L,
},
[1] = {
.enb_reg = CLK_OUT_ENB_H,
.enb_set_reg = CLK_OUT_ENB_SET_H,
.enb_clr_reg = CLK_OUT_ENB_CLR_H,
.rst_reg = RST_DEVICES_H,
.rst_set_reg = RST_DEVICES_SET_H,
.rst_clr_reg = RST_DEVICES_CLR_H,
},
[2] = {
.enb_reg = CLK_OUT_ENB_U,
.enb_set_reg = CLK_OUT_ENB_SET_U,
.enb_clr_reg = CLK_OUT_ENB_CLR_U,
.rst_reg = RST_DEVICES_U,
.rst_set_reg = RST_DEVICES_SET_U,
.rst_clr_reg = RST_DEVICES_CLR_U,
},
[3] = {
.enb_reg = CLK_OUT_ENB_V,
.enb_set_reg = CLK_OUT_ENB_SET_V,
.enb_clr_reg = CLK_OUT_ENB_CLR_V,
.rst_reg = RST_DEVICES_V,
.rst_set_reg = RST_DEVICES_SET_V,
.rst_clr_reg = RST_DEVICES_CLR_V,
},
[4] = {
.enb_reg = CLK_OUT_ENB_W,
.enb_set_reg = CLK_OUT_ENB_SET_W,
.enb_clr_reg = CLK_OUT_ENB_CLR_W,
.rst_reg = RST_DEVICES_W,
.rst_set_reg = RST_DEVICES_SET_W,
.rst_clr_reg = RST_DEVICES_CLR_W,
},
[5] = {
.enb_reg = CLK_OUT_ENB_X,
.enb_set_reg = CLK_OUT_ENB_SET_X,
.enb_clr_reg = CLK_OUT_ENB_CLR_X,
.rst_reg = RST_DEVICES_X,
.rst_set_reg = RST_DEVICES_SET_X,
.rst_clr_reg = RST_DEVICES_CLR_X,
},
};
struct tegra_clk_periph_regs *get_reg_bank(int clkid)
{
int reg_bank = clkid / 32;
if (reg_bank < periph_banks)
return &periph_regs[reg_bank];
else {
WARN_ON(1);
return NULL;
}
}
struct clk ** __init tegra_clk_init(int num, int banks)
{
if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
return NULL;
periph_clk_enb_refcnt = kzalloc(32 * banks *
sizeof(*periph_clk_enb_refcnt), GFP_KERNEL);
if (!periph_clk_enb_refcnt)
return NULL;
periph_banks = banks;
clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL);
if (!clks)
kfree(periph_clk_enb_refcnt);
clk_num = num;
return clks;
}
void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
struct clk *clks[], int clk_max)
{
@ -74,6 +203,43 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
}
}
void __init tegra_add_of_provider(struct device_node *np)
{
int i;
for (i = 0; i < clk_num; i++) {
if (IS_ERR(clks[i])) {
pr_err
("Tegra clk %d: register failed with %ld\n",
i, PTR_ERR(clks[i]));
}
if (!clks[i])
clks[i] = ERR_PTR(-EINVAL);
}
clk_data.clks = clks;
clk_data.clk_num = clk_num;
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
{
int i;
for (i = 0; i < num; i++, dev_clks++)
clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
dev_clks->dev_id);
}
struct clk ** __init tegra_lookup_dt_id(int clk_id,
struct tegra_clk *tegra_clk)
{
if (tegra_clk[clk_id].present)
return &clks[tegra_clk[clk_id].dt_id];
else
return NULL;
}
tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
void __init tegra_clocks_apply_init_table(void)

View File

@ -37,6 +37,8 @@ struct tegra_clk_sync_source {
container_of(_hw, struct tegra_clk_sync_source, hw)
extern const struct clk_ops tegra_clk_sync_source_ops;
extern int *periph_clk_enb_refcnt;
struct clk *tegra_clk_register_sync_source(const char *name,
unsigned long fixed_rate, unsigned long max_rate);
@ -188,12 +190,15 @@ struct tegra_clk_pll_params {
u32 ext_misc_reg[3];
u32 pmc_divnm_reg;
u32 pmc_divp_reg;
u32 flags;
int stepa_shift;
int stepb_shift;
int lock_delay;
int max_p;
struct pdiv_map *pdiv_tohw;
struct div_nmp *div_nmp;
struct tegra_clk_pll_freq_table *freq_table;
unsigned long fixed_rate;
};
/**
@ -233,10 +238,7 @@ struct tegra_clk_pll {
struct clk_hw hw;
void __iomem *clk_base;
void __iomem *pmc;
u32 flags;
unsigned long fixed_rate;
spinlock_t *lock;
struct tegra_clk_pll_freq_table *freq_table;
struct tegra_clk_pll_params *params;
};
@ -258,56 +260,49 @@ extern const struct clk_ops tegra_clk_pll_ops;
extern const struct clk_ops tegra_clk_plle_ops;
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
unsigned long flags, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock);
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
unsigned long flags, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock);
struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock);
struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock);
struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock);
struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
unsigned long flags,
struct tegra_clk_pll_params *pll_params,
u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock, unsigned long parent_rate);
struct clk *tegra_clk_register_plle_tegra114(const char *name,
const char *parent_name,
void __iomem *clk_base, unsigned long flags,
unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params,
struct tegra_clk_pll_freq_table *freq_table,
spinlock_t *lock);
struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
void __iomem *clk_base, unsigned long flags,
struct tegra_clk_pll_params *pll_params,
spinlock_t *lock);
/**
* struct tegra_clk_pll_out - PLL divider down clock
*
@ -395,13 +390,14 @@ struct tegra_clk_periph_gate {
#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
#define TEGRA_PERIPH_ON_APB BIT(2)
#define TEGRA_PERIPH_WAR_1005168 BIT(3)
#define TEGRA_PERIPH_NO_DIV BIT(4)
#define TEGRA_PERIPH_NO_GATE BIT(5)
void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
extern const struct clk_ops tegra_clk_periph_gate_ops;
struct clk *tegra_clk_register_periph_gate(const char *name,
const char *parent_name, u8 gate_flags, void __iomem *clk_base,
unsigned long flags, int clk_num,
struct tegra_clk_periph_regs *pregs, int *enable_refcnt);
unsigned long flags, int clk_num, int *enable_refcnt);
/**
* struct clk-periph - peripheral clock
@ -443,26 +439,26 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
#define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \
_div_shift, _div_width, _div_frac_width, \
_div_flags, _clk_num, _enb_refcnt, _regs, \
_gate_flags, _table) \
_div_flags, _clk_num,\
_gate_flags, _table, _lock) \
{ \
.mux = { \
.flags = _mux_flags, \
.shift = _mux_shift, \
.mask = _mux_mask, \
.table = _table, \
.lock = _lock, \
}, \
.divider = { \
.flags = _div_flags, \
.shift = _div_shift, \
.width = _div_width, \
.frac_width = _div_frac_width, \
.lock = _lock, \
}, \
.gate = { \
.flags = _gate_flags, \
.clk_num = _clk_num, \
.enable_refcnt = _enb_refcnt, \
.regs = _regs, \
}, \
.mux_ops = &clk_mux_ops, \
.div_ops = &tegra_clk_frac_div_ops, \
@ -472,7 +468,10 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
struct tegra_periph_init_data {
const char *name;
int clk_id;
const char **parent_names;
union {
const char **parent_names;
const char *parent_name;
} p;
int num_parents;
struct tegra_clk_periph periph;
u32 offset;
@ -483,20 +482,19 @@ struct tegra_periph_init_data {
#define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
_mux_shift, _mux_mask, _mux_flags, _div_shift, \
_div_width, _div_frac_width, _div_flags, _regs, \
_clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
_flags) \
_div_width, _div_frac_width, _div_flags, \
_clk_num, _gate_flags, _clk_id, _table, \
_flags, _lock) \
{ \
.name = _name, \
.clk_id = _clk_id, \
.parent_names = _parent_names, \
.p.parent_names = _parent_names, \
.num_parents = ARRAY_SIZE(_parent_names), \
.periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \
_mux_flags, _div_shift, \
_div_width, _div_frac_width, \
_div_flags, _clk_num, \
_enb_refcnt, _regs, \
_gate_flags, _table), \
_gate_flags, _table, _lock), \
.offset = _offset, \
.con_id = _con_id, \
.dev_id = _dev_id, \
@ -505,13 +503,13 @@ struct tegra_periph_init_data {
#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
_mux_shift, _mux_width, _mux_flags, _div_shift, \
_div_width, _div_frac_width, _div_flags, _regs, \
_clk_num, _enb_refcnt, _gate_flags, _clk_id) \
_div_width, _div_frac_width, _div_flags, \
_clk_num, _gate_flags, _clk_id) \
TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
_mux_shift, BIT(_mux_width) - 1, _mux_flags, \
_div_shift, _div_width, _div_frac_width, _div_flags, \
_regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
NULL, 0)
_clk_num, _gate_flags, _clk_id,\
NULL, 0, NULL)
/**
* struct clk_super_mux - super clock
@ -581,12 +579,49 @@ struct tegra_clk_duplicate {
}, \
}
struct tegra_clk {
int dt_id;
bool present;
};
struct tegra_devclk {
int dt_id;
char *dev_id;
char *con_id;
};
void tegra_init_from_table(struct tegra_clk_init_table *tbl,
struct clk *clks[], int clk_max);
void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
struct clk *clks[], int clk_max);
struct tegra_clk_periph_regs *get_reg_bank(int clkid);
struct clk **tegra_clk_init(int num, int periph_banks);
struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
void tegra_add_of_provider(struct device_node *np);
void tegra_register_devclks(struct tegra_devclk *dev_clks, int num);
void tegra_audio_clk_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params);
void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base,
struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params);
void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks);
void tegra_fixed_clk_init(struct tegra_clk *tegra_clks);
int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks,
unsigned long *input_freqs, int num,
unsigned long *osc_freq,
unsigned long *pll_ref_freq);
void tegra_super_clk_gen4_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params);
void tegra114_clock_tune_cpu_trimmers_high(void);
void tegra114_clock_tune_cpu_trimmers_low(void);
void tegra114_clock_tune_cpu_trimmers_init(void);

View File

@ -535,11 +535,41 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
}
EXPORT_SYMBOL_GPL(dma_get_slave_channel);
struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
{
dma_cap_mask_t mask;
struct dma_chan *chan;
int err;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
/* lock against __dma_request_channel */
mutex_lock(&dma_list_mutex);
chan = private_candidate(&mask, device, NULL, NULL);
if (chan) {
err = dma_chan_get(chan);
if (err) {
pr_debug("%s: failed to get %s: (%d)\n",
__func__, dma_chan_name(chan), err);
chan = NULL;
}
}
mutex_unlock(&dma_list_mutex);
return chan;
}
EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
/**
* __dma_request_channel - try to allocate an exclusive channel
* @mask: capabilities that the channel must satisfy
* @fn: optional callback to disposition available channels
* @fn_param: opaque parameter to pass to dma_filter_fn
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param)
@ -591,18 +621,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name)
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name)
{
struct dma_chan *chan;
/* If device-tree is present get slave info from here */
if (dev->of_node)
return of_dma_request_slave_channel(dev->of_node, name);
/* If device was enumerated by ACPI get slave info from here */
if (ACPI_HANDLE(dev))
return acpi_dma_request_slave_chan_by_name(dev, name);
if (ACPI_HANDLE(dev)) {
chan = acpi_dma_request_slave_chan_by_name(dev, name);
if (chan)
return chan;
}
return NULL;
return ERR_PTR(-ENODEV);
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel_reason);
/**
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
if (IS_ERR(ch))
return NULL;
return ch;
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);

View File

@ -893,33 +893,17 @@ static struct dma_chan *mmp_pdma_dma_xlate(struct of_phandle_args *dma_spec,
struct of_dma *ofdma)
{
struct mmp_pdma_device *d = ofdma->of_dma_data;
struct dma_chan *chan, *candidate;
struct dma_chan *chan;
struct mmp_pdma_chan *c;
retry:
candidate = NULL;
/* walk the list of channels registered with the current instance and
* find one that is currently unused */
list_for_each_entry(chan, &d->device.channels, device_node)
if (chan->client_count == 0) {
candidate = chan;
break;
}
if (!candidate)
chan = dma_get_any_slave_channel(&d->device);
if (!chan)
return NULL;
/* dma_get_slave_channel will return NULL if we lost a race between
* the lookup and the reservation */
chan = dma_get_slave_channel(candidate);
c = to_mmp_pdma_chan(chan);
c->drcmr = dma_spec->args[0];
if (chan) {
struct mmp_pdma_chan *c = to_mmp_pdma_chan(chan);
c->drcmr = dma_spec->args[0];
return chan;
}
goto retry;
return chan;
}
static int mmp_pdma_probe(struct platform_device *op)

View File

@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
* @np: device node to get DMA request from
* @name: name of desired channel
*
* Returns pointer to appropriate dma channel on success or NULL on error.
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name)
@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
struct of_dma *ofdma;
struct dma_chan *chan;
int count, i;
int ret_no_channel = -ENODEV;
if (!np || !name) {
pr_err("%s: not enough information provided\n", __func__);
return NULL;
return ERR_PTR(-ENODEV);
}
count = of_property_count_strings(np, "dma-names");
if (count < 0) {
pr_err("%s: dma-names property of node '%s' missing or empty\n",
__func__, np->full_name);
return NULL;
return ERR_PTR(-ENODEV);
}
for (i = 0; i < count; i++) {
@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
mutex_lock(&of_dma_lock);
ofdma = of_dma_find_controller(&dma_spec);
if (ofdma)
if (ofdma) {
chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
else
} else {
ret_no_channel = -EPROBE_DEFER;
chan = NULL;
}
mutex_unlock(&of_dma_lock);
@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return chan;
}
return NULL;
return ERR_PTR(ret_no_channel);
}
/**

View File

@ -37,10 +37,10 @@
#define TEGRA114_CLK_I2S2 18
#define TEGRA114_CLK_EPP 19
/* 20 (register bit affects vi and vi_sensor) */
#define TEGRA114_CLK_GR_2D 21
#define TEGRA114_CLK_GR2D 21
#define TEGRA114_CLK_USBD 22
#define TEGRA114_CLK_ISP 23
#define TEGRA114_CLK_GR_3D 24
#define TEGRA114_CLK_GR3D 24
/* 25 */
#define TEGRA114_CLK_DISP2 26
#define TEGRA114_CLK_DISP1 27
@ -289,8 +289,8 @@
#define TEGRA114_CLK_PCLK 261
#define TEGRA114_CLK_CCLK_G 262
#define TEGRA114_CLK_CCLK_LP 263
/* 264 */
/* 265 */
#define TEGRA114_CLK_DFLL_REF 264
#define TEGRA114_CLK_DFLL_SOC 265
/* 266 */
/* 267 */
/* 268 */

View File

@ -0,0 +1,341 @@
/*
* This header provides constants for binding nvidia,tegra124-car.
*
* The first 192 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
* registers. These IDs often match those in the CAR's RST_DEVICES registers,
* but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
* this case, those clocks are assigned IDs above 185 in order to highlight
* this issue. Implementations that interpret these clock IDs as bit values
* within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
* explicitly handle these special cases.
*
* The balance of the clocks controlled by the CAR are assigned IDs of 185 and
* above.
*/
#ifndef _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
#define _DT_BINDINGS_CLOCK_TEGRA124_CAR_H
/* 0 */
/* 1 */
/* 2 */
#define TEGRA124_CLK_ISPB 3
#define TEGRA124_CLK_RTC 4
#define TEGRA124_CLK_TIMER 5
#define TEGRA124_CLK_UARTA 6
/* 7 (register bit affects uartb and vfir) */
/* 8 */
#define TEGRA124_CLK_SDMMC2 9
/* 10 (register bit affects spdif_in and spdif_out) */
#define TEGRA124_CLK_I2S1 11
#define TEGRA124_CLK_I2C1 12
#define TEGRA124_CLK_NDFLASH 13
#define TEGRA124_CLK_SDMMC1 14
#define TEGRA124_CLK_SDMMC4 15
/* 16 */
#define TEGRA124_CLK_PWM 17
#define TEGRA124_CLK_I2S2 18
/* 20 (register bit affects vi and vi_sensor) */
#define TEGRA124_CLK_GR_2D 21
#define TEGRA124_CLK_USBD 22
#define TEGRA124_CLK_ISP 23
#define TEGRA124_CLK_GR_3D 24
/* 25 */
#define TEGRA124_CLK_DISP2 26
#define TEGRA124_CLK_DISP1 27
#define TEGRA124_CLK_HOST1X 28
#define TEGRA124_CLK_VCP 29
#define TEGRA124_CLK_I2S0 30
/* 31 */
/* 32 */
/* 33 */
#define TEGRA124_CLK_APBDMA 34
/* 35 */
#define TEGRA124_CLK_KBC 36
/* 37 */
/* 38 */
/* 39 (register bit affects fuse and fuse_burn) */
#define TEGRA124_CLK_KFUSE 40
#define TEGRA124_CLK_SBC1 41
#define TEGRA124_CLK_NOR 42
/* 43 */
#define TEGRA124_CLK_SBC2 44
/* 45 */
#define TEGRA124_CLK_SBC3 46
#define TEGRA124_CLK_I2C5 47
#define TEGRA124_CLK_DSIA 48
/* 49 */
#define TEGRA124_CLK_MIPI 50
#define TEGRA124_CLK_HDMI 51
#define TEGRA124_CLK_CSI 52
/* 53 */
#define TEGRA124_CLK_I2C2 54
#define TEGRA124_CLK_UARTC 55
#define TEGRA124_CLK_MIPI_CAL 56
#define TEGRA124_CLK_EMC 57
#define TEGRA124_CLK_USB2 58
#define TEGRA124_CLK_USB3 59
/* 60 */
#define TEGRA124_CLK_VDE 61
#define TEGRA124_CLK_BSEA 62
#define TEGRA124_CLK_BSEV 63
/* 64 */
#define TEGRA124_CLK_UARTD 65
#define TEGRA124_CLK_UARTE 66
#define TEGRA124_CLK_I2C3 67
#define TEGRA124_CLK_SBC4 68
#define TEGRA124_CLK_SDMMC3 69
#define TEGRA124_CLK_PCIE 70
#define TEGRA124_CLK_OWR 71
#define TEGRA124_CLK_AFI 72
#define TEGRA124_CLK_CSITE 73
/* 74 */
/* 75 */
#define TEGRA124_CLK_LA 76
#define TEGRA124_CLK_TRACE 77
#define TEGRA124_CLK_SOC_THERM 78
#define TEGRA124_CLK_DTV 79
#define TEGRA124_CLK_NDSPEED 80
#define TEGRA124_CLK_I2CSLOW 81
#define TEGRA124_CLK_DSIB 82
#define TEGRA124_CLK_TSEC 83
/* 84 */
/* 85 */
/* 86 */
/* 87 */
/* 88 */
#define TEGRA124_CLK_XUSB_HOST 89
/* 90 */
#define TEGRA124_CLK_MSENC 91
#define TEGRA124_CLK_CSUS 92
/* 93 */
/* 94 */
/* 95 (bit affects xusb_dev and xusb_dev_src) */
/* 96 */
/* 97 */
/* 98 */
#define TEGRA124_CLK_MSELECT 99
#define TEGRA124_CLK_TSENSOR 100
#define TEGRA124_CLK_I2S3 101
#define TEGRA124_CLK_I2S4 102
#define TEGRA124_CLK_I2C4 103
#define TEGRA124_CLK_SBC5 104
#define TEGRA124_CLK_SBC6 105
#define TEGRA124_CLK_D_AUDIO 106
#define TEGRA124_CLK_APBIF 107
#define TEGRA124_CLK_DAM0 108
#define TEGRA124_CLK_DAM1 109
#define TEGRA124_CLK_DAM2 110
#define TEGRA124_CLK_HDA2CODEC_2X 111
/* 112 */
#define TEGRA124_CLK_AUDIO0_2X 113
#define TEGRA124_CLK_AUDIO1_2X 114
#define TEGRA124_CLK_AUDIO2_2X 115
#define TEGRA124_CLK_AUDIO3_2X 116
#define TEGRA124_CLK_AUDIO4_2X 117
#define TEGRA124_CLK_SPDIF_2X 118
#define TEGRA124_CLK_ACTMON 119
#define TEGRA124_CLK_EXTERN1 120
#define TEGRA124_CLK_EXTERN2 121
#define TEGRA124_CLK_EXTERN3 122
#define TEGRA124_CLK_SATA_OOB 123
#define TEGRA124_CLK_SATA 124
#define TEGRA124_CLK_HDA 125
/* 126 */
#define TEGRA124_CLK_SE 127
#define TEGRA124_CLK_HDA2HDMI 128
#define TEGRA124_CLK_SATA_COLD 129
/* 130 */
/* 131 */
/* 132 */
/* 133 */
/* 134 */
/* 135 */
/* 136 */
/* 137 */
/* 138 */
/* 139 */
/* 140 */
/* 141 */
/* 142 */
/* 143 (bit affects xusb_falcon_src, xusb_fs_src, */
/* xusb_host_src and xusb_ss_src) */
#define TEGRA124_CLK_CILAB 144
#define TEGRA124_CLK_CILCD 145
#define TEGRA124_CLK_CILE 146
#define TEGRA124_CLK_DSIALP 147
#define TEGRA124_CLK_DSIBLP 148
#define TEGRA124_CLK_ENTROPY 149
#define TEGRA124_CLK_DDS 150
/* 151 */
#define TEGRA124_CLK_DP2 152
#define TEGRA124_CLK_AMX 153
#define TEGRA124_CLK_ADX 154
/* 155 (bit affects dfll_ref and dfll_soc) */
#define TEGRA124_CLK_XUSB_SS 156
/* 157 */
/* 158 */
/* 159 */
/* 160 */
/* 161 */
/* 162 */
/* 163 */
/* 164 */
/* 165 */
#define TEGRA124_CLK_I2C6 166
/* 167 */
/* 168 */
/* 169 */
/* 170 */
#define TEGRA124_CLK_VIM2_CLK 171
/* 172 */
/* 173 */
/* 174 */
/* 175 */
#define TEGRA124_CLK_HDMI_AUDIO 176
#define TEGRA124_CLK_CLK72MHZ 177
#define TEGRA124_CLK_VIC03 178
/* 179 */
#define TEGRA124_CLK_ADX1 180
#define TEGRA124_CLK_DPAUX 181
#define TEGRA124_CLK_SOR0 182
/* 183 */
#define TEGRA124_CLK_GPU 184
#define TEGRA124_CLK_AMX1 185
/* 186 */
/* 187 */
/* 188 */
/* 189 */
/* 190 */
/* 191 */
#define TEGRA124_CLK_UARTB 192
#define TEGRA124_CLK_VFIR 193
#define TEGRA124_CLK_SPDIF_IN 194
#define TEGRA124_CLK_SPDIF_OUT 195
#define TEGRA124_CLK_VI 196
#define TEGRA124_CLK_VI_SENSOR 197
#define TEGRA124_CLK_FUSE 198
#define TEGRA124_CLK_FUSE_BURN 199
#define TEGRA124_CLK_CLK_32K 200
#define TEGRA124_CLK_CLK_M 201
#define TEGRA124_CLK_CLK_M_DIV2 202
#define TEGRA124_CLK_CLK_M_DIV4 203
#define TEGRA124_CLK_PLL_REF 204
#define TEGRA124_CLK_PLL_C 205
#define TEGRA124_CLK_PLL_C_OUT1 206
#define TEGRA124_CLK_PLL_C2 207
#define TEGRA124_CLK_PLL_C3 208
#define TEGRA124_CLK_PLL_M 209
#define TEGRA124_CLK_PLL_M_OUT1 210
#define TEGRA124_CLK_PLL_P 211
#define TEGRA124_CLK_PLL_P_OUT1 212
#define TEGRA124_CLK_PLL_P_OUT2 213
#define TEGRA124_CLK_PLL_P_OUT3 214
#define TEGRA124_CLK_PLL_P_OUT4 215
#define TEGRA124_CLK_PLL_A 216
#define TEGRA124_CLK_PLL_A_OUT0 217
#define TEGRA124_CLK_PLL_D 218
#define TEGRA124_CLK_PLL_D_OUT0 219
#define TEGRA124_CLK_PLL_D2 220
#define TEGRA124_CLK_PLL_D2_OUT0 221
#define TEGRA124_CLK_PLL_U 222
#define TEGRA124_CLK_PLL_U_480M 223
#define TEGRA124_CLK_PLL_U_60M 224
#define TEGRA124_CLK_PLL_U_48M 225
#define TEGRA124_CLK_PLL_U_12M 226
#define TEGRA124_CLK_PLL_X 227
#define TEGRA124_CLK_PLL_X_OUT0 228
#define TEGRA124_CLK_PLL_RE_VCO 229
#define TEGRA124_CLK_PLL_RE_OUT 230
#define TEGRA124_CLK_PLL_E 231
#define TEGRA124_CLK_SPDIF_IN_SYNC 232
#define TEGRA124_CLK_I2S0_SYNC 233
#define TEGRA124_CLK_I2S1_SYNC 234
#define TEGRA124_CLK_I2S2_SYNC 235
#define TEGRA124_CLK_I2S3_SYNC 236
#define TEGRA124_CLK_I2S4_SYNC 237
#define TEGRA124_CLK_VIMCLK_SYNC 238
#define TEGRA124_CLK_AUDIO0 239
#define TEGRA124_CLK_AUDIO1 240
#define TEGRA124_CLK_AUDIO2 241
#define TEGRA124_CLK_AUDIO3 242
#define TEGRA124_CLK_AUDIO4 243
#define TEGRA124_CLK_SPDIF 244
#define TEGRA124_CLK_CLK_OUT_1 245
#define TEGRA124_CLK_CLK_OUT_2 246
#define TEGRA124_CLK_CLK_OUT_3 247
#define TEGRA124_CLK_BLINK 248
/* 249 */
/* 250 */
/* 251 */
#define TEGRA124_CLK_XUSB_HOST_SRC 252
#define TEGRA124_CLK_XUSB_FALCON_SRC 253
#define TEGRA124_CLK_XUSB_FS_SRC 254
#define TEGRA124_CLK_XUSB_SS_SRC 255
#define TEGRA124_CLK_XUSB_DEV_SRC 256
#define TEGRA124_CLK_XUSB_DEV 257
#define TEGRA124_CLK_XUSB_HS_SRC 258
#define TEGRA124_CLK_SCLK 259
#define TEGRA124_CLK_HCLK 260
#define TEGRA124_CLK_PCLK 261
#define TEGRA124_CLK_CCLK_G 262
#define TEGRA124_CLK_CCLK_LP 263
#define TEGRA124_CLK_DFLL_REF 264
#define TEGRA124_CLK_DFLL_SOC 265
#define TEGRA124_CLK_VI_SENSOR2 266
#define TEGRA124_CLK_PLL_P_OUT5 267
#define TEGRA124_CLK_CML0 268
#define TEGRA124_CLK_CML1 269
#define TEGRA124_CLK_PLL_C4 270
#define TEGRA124_CLK_PLL_DP 271
#define TEGRA124_CLK_PLL_E_MUX 272
/* 273 */
/* 274 */
/* 275 */
/* 276 */
/* 277 */
/* 278 */
/* 279 */
/* 280 */
/* 281 */
/* 282 */
/* 283 */
/* 284 */
/* 285 */
/* 286 */
/* 287 */
/* 288 */
/* 289 */
/* 290 */
/* 291 */
/* 292 */
/* 293 */
/* 294 */
/* 295 */
/* 296 */
/* 297 */
/* 298 */
/* 299 */
#define TEGRA124_CLK_AUDIO0_MUX 300
#define TEGRA124_CLK_AUDIO1_MUX 301
#define TEGRA124_CLK_AUDIO2_MUX 302
#define TEGRA124_CLK_AUDIO3_MUX 303
#define TEGRA124_CLK_AUDIO4_MUX 304
#define TEGRA124_CLK_SPDIF_MUX 305
#define TEGRA124_CLK_CLK_OUT_1_MUX 306
#define TEGRA124_CLK_CLK_OUT_2_MUX 307
#define TEGRA124_CLK_CLK_OUT_3_MUX 308
#define TEGRA124_CLK_DSIA_MUX 309
#define TEGRA124_CLK_DSIB_MUX 310
#define TEGRA124_CLK_SOR0_LVDS 311
#define TEGRA124_CLK_CLK_MAX 312
#endif /* _DT_BINDINGS_CLOCK_TEGRA124_CAR_H */

View File

@ -260,6 +260,14 @@
/* 298 */
/* 299 */
#define TEGRA30_CLK_CLK_OUT_1_MUX 300
#define TEGRA30_CLK_CLK_MAX 301
#define TEGRA30_CLK_CLK_OUT_2_MUX 301
#define TEGRA30_CLK_CLK_OUT_3_MUX 302
#define TEGRA30_CLK_AUDIO0_MUX 303
#define TEGRA30_CLK_AUDIO1_MUX 304
#define TEGRA30_CLK_AUDIO2_MUX 305
#define TEGRA30_CLK_AUDIO3_MUX 306
#define TEGRA30_CLK_AUDIO4_MUX 307
#define TEGRA30_CLK_SPDIF_MUX 308
#define TEGRA30_CLK_CLK_MAX 309
#endif /* _DT_BINDINGS_CLOCK_TEGRA30_CAR_H */

View File

@ -22,6 +22,7 @@
#define LINUX_DMAENGINE_H
#include <linux/device.h>
#include <linux/err.h>
#include <linux/uio.h>
#include <linux/bug.h>
#include <linux/scatterlist.h>
@ -1040,6 +1041,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void dma_issue_pending_all(void);
struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
dma_filter_fn fn, void *fn_param);
struct dma_chan *dma_request_slave_channel_reason(struct device *dev,
const char *name);
struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name);
void dma_release_channel(struct dma_chan *chan);
#else
@ -1063,6 +1066,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
{
return NULL;
}
static inline struct dma_chan *dma_request_slave_channel_reason(
struct device *dev, const char *name)
{
return ERR_PTR(-ENODEV);
}
static inline struct dma_chan *dma_request_slave_channel(struct device *dev,
const char *name)
{
@ -1079,6 +1087,7 @@ int dma_async_device_register(struct dma_device *device);
void dma_async_device_unregister(struct dma_device *device);
void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
struct dma_chan *dma_get_slave_channel(struct dma_chan *chan);
struct dma_chan *dma_get_any_slave_channel(struct dma_device *device);
struct dma_chan *net_dma_find_channel(void);
#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
#define dma_request_slave_channel_compat(mask, x, y, dev, name) \

View File

@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
* @dma_dev: If set, request DMA channel on this device rather than the DAI
* device.
* @chan_names: If set, these custom DMA channel names will be requested at
* registration time.
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
* @prealloc_buffer_size: Size of the preallocated audio buffer.
*
@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_substream *substream);
dma_filter_fn compat_filter_fn;
struct device *dma_dev;
const char *chan_names[SNDRV_PCM_STREAM_LAST + 1];
const struct snd_pcm_hardware *pcm_hardware;
unsigned int prealloc_buffer_size;
@ -140,6 +146,10 @@ int snd_dmaengine_pcm_register(struct device *dev,
unsigned int flags);
void snd_dmaengine_pcm_unregister(struct device *dev);
int devm_snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config,
unsigned int flags);
int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct dma_slave_config *slave_config);

View File

@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
static void devm_component_release(struct device *dev, void *res)
{
@ -84,3 +85,43 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
return ret;
}
EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
static void devm_dmaengine_pcm_release(struct device *dev, void *res)
{
snd_dmaengine_pcm_unregister(*(struct device **)res);
}
/**
* devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
* @dev: The parent device for the PCM device
* @config: Platform specific PCM configuration
* @flags: Platform specific quirks
*
* Register a dmaengine based PCM device with automatic unregistration when the
* device is unregistered.
*/
int devm_snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
struct device **ptr;
int ret;
ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = snd_dmaengine_pcm_register(dev, config, flags);
if (ret == 0) {
*ptr = dev;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return ret;
}
EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register);
#endif

View File

@ -137,6 +137,9 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
hw.buffer_bytes_max = SIZE_MAX;
hw.fifo_size = dma_data->fifo_size;
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
hw.info |= SNDRV_PCM_INFO_BATCH;
ret = dma_get_slave_caps(chan, &dma_caps);
if (ret == 0) {
if (dma_caps.cmd_pause)
@ -284,24 +287,67 @@ static const char * const dmaengine_pcm_dma_channel_names[] = {
[SNDRV_PCM_STREAM_CAPTURE] = "rx",
};
static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
struct device *dev)
static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
struct device *dev, const struct snd_dmaengine_pcm_config *config)
{
unsigned int i;
const char *name;
struct dma_chan *chan;
if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
!dev->of_node)
return;
return 0;
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx");
pcm->chan[1] = pcm->chan[0];
} else {
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
pcm->chan[i] = dma_request_slave_channel(dev,
dmaengine_pcm_dma_channel_names[i]);
if (config->dma_dev) {
/*
* If this warning is seen, it probably means that your Linux
* device structure does not match your HW device structure.
* It would be best to refactor the Linux device structure to
* correctly match the HW structure.
*/
dev_warn(dev, "DMA channels sourced from device %s",
dev_name(config->dma_dev));
dev = config->dma_dev;
}
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
i++) {
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
name = "rx-tx";
else
name = dmaengine_pcm_dma_channel_names[i];
if (config->chan_names[i])
name = config->chan_names[i];
chan = dma_request_slave_channel_reason(dev, name);
if (IS_ERR(chan)) {
if (PTR_ERR(chan) == -EPROBE_DEFER)
return -EPROBE_DEFER;
pcm->chan[i] = NULL;
} else {
pcm->chan[i] = chan;
}
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
break;
}
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
pcm->chan[1] = pcm->chan[0];
return 0;
}
static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
{
unsigned int i;
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE;
i++) {
if (!pcm->chan[i])
continue;
dma_release_channel(pcm->chan[i]);
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
break;
}
}
@ -315,6 +361,7 @@ int snd_dmaengine_pcm_register(struct device *dev,
const struct snd_dmaengine_pcm_config *config, unsigned int flags)
{
struct dmaengine_pcm *pcm;
int ret;
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
if (!pcm)
@ -323,14 +370,25 @@ int snd_dmaengine_pcm_register(struct device *dev,
pcm->config = config;
pcm->flags = flags;
dmaengine_pcm_request_chan_of(pcm, dev);
ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
if (ret)
goto err_free_dma;
if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
return snd_soc_add_platform(dev, &pcm->platform,
ret = snd_soc_add_platform(dev, &pcm->platform,
&dmaengine_no_residue_pcm_platform);
else
return snd_soc_add_platform(dev, &pcm->platform,
ret = snd_soc_add_platform(dev, &pcm->platform,
&dmaengine_pcm_platform);
if (ret)
goto err_free_dma;
return 0;
err_free_dma:
dmaengine_pcm_release_chan(pcm);
kfree(pcm);
return ret;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register);
@ -345,7 +403,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
{
struct snd_soc_platform *platform;
struct dmaengine_pcm *pcm;
unsigned int i;
platform = snd_soc_lookup_platform(dev);
if (!platform)
@ -353,15 +410,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
pcm = soc_platform_to_pcm(platform);
for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
if (pcm->chan[i]) {
dma_release_channel(pcm->chan[i]);
if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
break;
}
}
snd_soc_remove_platform(platform);
dmaengine_pcm_release_chan(pcm);
kfree(pcm);
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);