static int clk_main_rc_osc_is_prepared(struct clk_hw *hw) { struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); struct at91_pmc *pmc = osc->pmc; return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) && (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN)); }
int tegra_powergate_set(int id, bool new_state) { #ifndef CONFIG_TEGRA_SIMULATION_PLATFORM bool status; unsigned long flags; spinlock_t *lock = tegra_get_powergate_lock(); /* 10us timeout for toggle operation if it takes affect*/ int toggle_timeout = 10; /* 100 * 10 = 1000us timeout for toggle command to take affect in case of contention with h/w initiated CPU power gating */ int contention_timeout = 100; spin_lock_irqsave(lock, flags); status = !!(pmc_read(PWRGATE_STATUS) & (1 << id)); if (status == new_state) { spin_unlock_irqrestore(lock, flags); return 0; } if (TEGRA_IS_CPU_POWERGATE_ID(id)) { /* CPU ungated in s/w only during boot/resume with outer waiting loop and no contention from other CPUs */ pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); spin_unlock_irqrestore(lock, flags); return 0; } pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); do { do { udelay(1); status = !!(pmc_read(PWRGATE_STATUS) & (1 << id)); toggle_timeout--; } while ((status != new_state) && (toggle_timeout > 0)); contention_timeout--; } while ((status != new_state) && (contention_timeout > 0)); spin_unlock_irqrestore(lock, flags); if (status != new_state) { WARN(1, "Could not set powergate %d to %d", id, new_state); return -EBUSY; } trace_power_domain_target(tegra_powergate_get_name(id), new_state, smp_processor_id()); #endif return 0; }
static int clk_main_osc_is_prepared(struct clk_hw *hw) { struct clk_main_osc *osc = to_clk_main_osc(hw); struct at91_pmc *pmc = osc->pmc; u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); if (tmp & AT91_PMC_OSCBYPASS) return 1; return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) && (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN)); }
static int clk_sam9x5_main_prepare(struct clk_hw *hw) { struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); struct at91_pmc *pmc = clkmain->pmc; while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { enable_irq(clkmain->irq); wait_event(clkmain->wait, pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); } return clk_main_probe_frequency(pmc); }
static int clk_system_is_prepared(struct clk_hw *hw) { struct clk_system *sys = to_clk_system(hw); struct at91_pmc *pmc = sys->pmc; if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id))) return 0; if (!is_pck(sys->id)) return 1; return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id)); }
static irqreturn_t pmc_irq_handler(int irq, void *data) { struct at91_pmc *pmc = (struct at91_pmc *)data; unsigned long sr; int n; sr = pmc_read(pmc, AT91_PMC_SR) & pmc_read(pmc, AT91_PMC_IMR); if (!sr) return IRQ_NONE; for_each_set_bit(n, &sr, BITS_PER_LONG) generic_handle_irq(irq_find_mapping(pmc->irqdomain, n)); return IRQ_HANDLED; }
int tegra_io_rail_power_off(int id) { unsigned long request, status, value; unsigned int bit, mask; int err; err = tegra_io_rail_prepare(id, &request, &status, &bit); if (err < 0) return err; mask = 1 << bit; value = pmc_read(request); value |= mask; value &= ~IO_DPD_REQ_CODE_MASK; value |= IO_DPD_REQ_CODE_ON; pmc_write(value, request); err = tegra_io_rail_poll(status, mask, mask, 250); if (err < 0) return err; tegra_io_rail_unprepare(); return 0; }
static int clk_programmable_is_ready(struct clk_hw *hw) { struct clk_programmable *prog = to_clk_programmable(hw); struct at91_pmc *pmc = prog->pmc; return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_PCKR(prog->id)); }
static int clk_utmi_is_prepared(struct clk_hw *hw) { struct clk_utmi *utmi = to_clk_utmi(hw); struct at91_pmc *pmc = utmi->pmc; return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); }
int sys_sysarch(struct proc *p, void *v, register_t *retval) { struct sys_sysarch_args /* { syscallarg(int) op; syscallarg(void *) parms; } */ *uap = v; int error = 0; switch(SCARG(uap, op)) { #if defined(USER_LDT) && 0 case AMD64_GET_LDT: error = amd64_get_ldt(p, SCARG(uap, parms), retval); break; case AMD64_SET_LDT: error = amd64_set_ldt(p, SCARG(uap, parms), retval); break; #endif case AMD64_IOPL: error = amd64_iopl(p, SCARG(uap, parms), retval); break; #if 0 case AMD64_GET_IOPERM: error = amd64_get_ioperm(p, SCARG(uap, parms), retval); break; case AMD64_SET_IOPERM: error = amd64_set_ioperm(p, SCARG(uap, parms), retval); break; #endif #ifdef MTRR case AMD64_GET_MTRR: error = amd64_get_mtrr(p, SCARG(uap, parms), retval); break; case AMD64_SET_MTRR: error = amd64_set_mtrr(p, SCARG(uap, parms), retval); break; #endif #if defined(PERFCTRS) && 0 case AMD64_PMC_INFO: error = pmc_info(p, SCARG(uap, parms), retval); break; case AMD64_PMC_STARTSTOP: error = pmc_startstop(p, SCARG(uap, parms), retval); break; case AMD64_PMC_READ: error = pmc_read(p, SCARG(uap, parms), retval); break; #endif default: error = EINVAL; break; } return (error); }
static void pmc_irq_suspend(struct irq_data *d) { struct at91_pmc *pmc = irq_data_get_irq_chip_data(d); pmc->imr = pmc_read(pmc, AT91_PMC_IMR); pmc_write(pmc, AT91_PMC_IDR, pmc->imr); }
static int clk_utmi_prepare(struct clk_hw *hw) { struct clk_utmi *utmi = to_clk_utmi(hw); struct at91_pmc *pmc = utmi->pmc; u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; pmc_write(pmc, AT91_CKGR_UCKR, tmp); while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU)) { enable_irq(utmi->irq); wait_event(utmi->wait, pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_LOCKU); } return 0; }
static bool tegra_powergate_is_powered(int id) { u32 status; WARN_ON(id < 0 || id >= TEGRA_NUM_POWERGATE); status = pmc_read(PWRGATE_STATUS) & (1 << id); return !!status; }
int tegra_powergate_is_powered(int id) { u32 status; if (id < 0 || id >= tegra_num_powerdomains) return -EINVAL; status = pmc_read(PWRGATE_STATUS) & (1 << id); return !!status; }
static int clk_programmable_prepare(struct clk_hw *hw) { u32 tmp; struct clk_programmable *prog = to_clk_programmable(hw); struct at91_pmc *pmc = prog->pmc; const struct clk_programmable_layout *layout = prog->layout; u8 id = prog->id; u32 mask = PROG_STATUS_MASK(id); tmp = prog->css | (prog->pres << layout->pres_shift); if (layout->have_slck_mck && prog->slckmck) tmp |= AT91_PMC_CSSMCK_MCK; pmc_write(pmc, AT91_PMC_PCKR(id), tmp); while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) wait_event(prog->wait, pmc_read(pmc, AT91_PMC_SR) & mask); return 0; }
static void clk_audio_pll_pmc_disable(struct clk_hw *hw) { struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); struct at91_pmc *pmc = apmc_ck->pmc; u32 tmp; pmc_lock(pmc); tmp = pmc_read(pmc, AT91_PMC_AUDIO_PLL0) & ~AT91_PMC_AUDIO_PLL_PMCEN; pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp); pmc_unlock(pmc); }
static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw); if (pmc_read(h32mxclk->pmc, AT91_PMC_MCKR) & AT91_PMC_H32MXDIV) return parent_rate / 2; if (parent_rate > H32MX_MAX_FREQ) pr_warn("H32MX clock is too fast\n"); return parent_rate; }
static int clk_main_rc_osc_prepare(struct clk_hw *hw) { struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); struct at91_pmc *pmc = osc->pmc; u32 tmp; tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; if (!(tmp & AT91_PMC_MOSCRCEN)) { tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY; pmc_write(pmc, AT91_CKGR_MOR, tmp); } while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) { enable_irq(osc->irq); wait_event(osc->wait, pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS); } return 0; }
static void clk_main_rc_osc_unprepare(struct clk_hw *hw) { struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); struct at91_pmc *pmc = osc->pmc; u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); if (!(tmp & AT91_PMC_MOSCRCEN)) return; tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN); pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); }
static int clk_system_prepare(struct clk_hw *hw) { struct clk_system *sys = to_clk_system(hw); struct at91_pmc *pmc = sys->pmc; u32 mask = 1 << sys->id; pmc_write(pmc, AT91_PMC_SCER, mask); if (!is_pck(sys->id)) return 0; while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) { if (sys->irq) { enable_irq(sys->irq); wait_event(sys->wait, pmc_read(pmc, AT91_PMC_SR) & mask); } else cpu_relax(); } return 0; }
/* make sure that pll is in reset state beforehand */ static int clk_audio_pll_prepare(struct clk_hw *hw) { struct clk_audio_frac *fck = to_clk_audio_frac(hw); struct at91_pmc *pmc = fck->pmc; u32 tmp; pmc_lock(pmc); tmp = pmc_read(pmc, AT91_PMC_AUDIO_PLL0) & ~AT91_PMC_AUDIO_PLL_RESETN; pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp); pmc_unlock(pmc); return 0; }
static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { u32 tmp; struct clk_programmable *prog = to_clk_programmable(hw); struct at91_pmc *pmc = prog->pmc; const struct clk_programmable_layout *layout = prog->layout; tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); prog->pres = (tmp >> layout->pres_shift) & PROG_PRES_MASK; return parent_rate >> prog->pres; }
static void clk_audio_pll_disable(struct clk_hw *hw) { struct clk_audio_frac *fck = to_clk_audio_frac(hw); struct at91_pmc *pmc = fck->pmc; u32 tmp; pmc_lock(pmc); tmp = pmc_read(pmc, AT91_PMC_AUDIO_PLL0) & ~AT91_PMC_AUDIO_PLL_PLLEN; pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp); /* do it in 2 separated writes */ pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp & ~AT91_PMC_AUDIO_PLL_RESETN); pmc_unlock(pmc); }
static int clk_audio_pll_pmc_enable(struct clk_hw *hw) { struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); struct at91_pmc *pmc = apmc_ck->pmc; u32 tmp; pmc_lock(pmc); tmp = pmc_read(pmc, AT91_PMC_AUDIO_PLL0) & ~AT91_PMC_AUDIO_PLL_QDPMC_MASK; tmp |= AT91_PMC_AUDIO_PLL_PMCEN | AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc); pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp); pmc_unlock(pmc); return 0; }
static int clk_audio_pll_enable(struct clk_hw *hw) { struct clk_audio_frac *fck = to_clk_audio_frac(hw); struct at91_pmc *pmc = fck->pmc; u32 tmp, tmp2; pmc_lock(pmc); tmp = pmc_read(pmc, AT91_PMC_AUDIO_PLL0); pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp | AT91_PMC_AUDIO_PLL_RESETN); tmp2 = pmc_read(pmc, AT91_PMC_AUDIO_PLL1) & ~AT91_PMC_AUDIO_PLL_FRACR_MASK; pmc_write(pmc, AT91_PMC_AUDIO_PLL1, tmp2 | fck->fracr); /* * reset and enabled have to be done in 2 separated writes * for AT91_PMC_AUDIO_PLL0 */ tmp &= ~AT91_PMC_AUDIO_PLL_ND_MASK; pmc_write(pmc, AT91_PMC_AUDIO_PLL0, tmp | AT91_PMC_AUDIO_PLL_RESETN | AT91_PMC_AUDIO_PLL_PLLEN | AT91_PMC_AUDIO_PLL_ND(fck->nd)); pmc_unlock(pmc); return 0; }
static struct clk * __init at91_clk_register_main_osc(struct at91_pmc *pmc, unsigned int irq, const char *name, const char *parent_name, bool bypass) { int ret; struct clk_main_osc *osc; struct clk *clk = NULL; struct clk_init_data init; if (!pmc || !irq || !name || !parent_name) return ERR_PTR(-EINVAL); osc = kzalloc(sizeof(*osc), GFP_KERNEL); if (!osc) return ERR_PTR(-ENOMEM); init.name = name; init.ops = &main_osc_ops; init.parent_names = &parent_name; init.num_parents = 1; init.flags = CLK_IGNORE_UNUSED; osc->hw.init = &init; osc->pmc = pmc; osc->irq = irq; init_waitqueue_head(&osc->wait); irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); ret = request_irq(osc->irq, clk_main_osc_irq_handler, IRQF_TRIGGER_HIGH, name, osc); if (ret) return ERR_PTR(ret); if (bypass) pmc_write(pmc, AT91_CKGR_MOR, (pmc_read(pmc, AT91_CKGR_MOR) & ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) | AT91_PMC_OSCBYPASS | AT91_PMC_KEY); clk = clk_register(NULL, &osc->hw); if (IS_ERR(clk)) { free_irq(irq, osc); kfree(osc); } return clk; }
static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc, unsigned long parent_rate) { u32 tmp; if (parent_rate) return parent_rate; tmp = pmc_read(pmc, AT91_CKGR_MCFR); if (!(tmp & AT91_PMC_MAINRDY)) return 0; return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; }
static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) { struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); struct at91_pmc *pmc = clkmain->pmc; u32 tmp; if (index > 1) return -EINVAL; tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; if (index && !(tmp & AT91_PMC_MOSCSEL)) pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); else if (!index && (tmp & AT91_PMC_MOSCSEL)) pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { enable_irq(clkmain->irq); wait_event(clkmain->wait, pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); } return 0; }
static struct clk * __init at91_clk_register_sam9x5_main(struct at91_pmc *pmc, unsigned int irq, const char *name, const char **parent_names, int num_parents) { int ret; struct clk_sam9x5_main *clkmain; struct clk *clk = NULL; struct clk_init_data init; if (!pmc || !irq || !name) return ERR_PTR(-EINVAL); if (!parent_names || !num_parents) return ERR_PTR(-EINVAL); clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); if (!clkmain) return ERR_PTR(-ENOMEM); init.name = name; init.ops = &sam9x5_main_ops; init.parent_names = parent_names; init.num_parents = num_parents; init.flags = CLK_SET_PARENT_GATE; clkmain->hw.init = &init; clkmain->pmc = pmc; clkmain->irq = irq; clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN); init_waitqueue_head(&clkmain->wait); irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler, IRQF_TRIGGER_HIGH, name, clkmain); if (ret) return ERR_PTR(ret); clk = clk_register(NULL, &clkmain->hw); if (IS_ERR(clk)) { free_irq(clkmain->irq, clkmain); kfree(clkmain); } return clk; }
bool tegra_powergate_is_powered(int id) { u32 status; if (!pg_ops) { pr_info("This SOC doesn't support powergating\n"); return -EINVAL; } if (id < 0 || id >= pg_ops->num_powerdomains) return -EINVAL; status = pmc_read(PWRGATE_STATUS) & (1 << id); return !!status; }