/** * omap_device_set_rate - Set a new rate at which the device is to operate * @req_dev : pointer to the device requesting the scaling. * @dev : pointer to the device that is to be scaled * @rate : the rnew rate for the device. * * This API gets the device opp table associated with this device and * tries putting the device to the requested rate and the voltage domain * associated with the device to the voltage corresponding to the * requested rate. Since multiple devices can be assocciated with a * voltage domain this API finds out the possible voltage the * voltage domain can enter and then decides on the final device * rate. Return 0 on success else the error value */ int omap_device_set_rate(struct device *req_dev, struct device *dev, unsigned long rate) { struct omap_opp *opp; unsigned long volt, freq, min_freq, max_freq, flags; struct voltagedomain *voltdm; struct platform_device *pdev; struct omap_device *od; int ret; pdev = container_of(dev, struct platform_device, dev); od = _find_by_pdev(pdev); /* if in low power DPLL cascading mode, bail out early */ if (cpu_is_omap44xx()) { read_lock_irqsave(&dpll_cascading_lock, flags); if (in_dpll_cascading) { ret = -EINVAL; goto out; } } /* * Figure out if the desired frquency lies between the * maximum and minimum possible for the particular device */ min_freq = 0; if (IS_ERR(opp_find_freq_ceil(dev, &min_freq))) { dev_err(dev, "%s: Unable to find lowest opp\n", __func__); ret = -ENODEV; goto out; } max_freq = ULONG_MAX; if (IS_ERR(opp_find_freq_floor(dev, &max_freq))) { dev_err(dev, "%s: Unable to find highest opp\n", __func__); ret = -ENODEV; goto out; } if (rate < min_freq) freq = min_freq; else if (rate > max_freq) freq = max_freq; else freq = rate; /* Get the possible rate from the opp layer */ opp = opp_find_freq_ceil(dev, &freq); if (IS_ERR(opp)) { dev_dbg(dev, "%s: Unable to find OPP for freq%ld\n", __func__, rate); ret = -ENODEV; goto out; } if (unlikely(freq != rate)) dev_dbg(dev, "%s: Available freq %ld != dpll freq %ld.\n", __func__, freq, rate); /* Get the voltage corresponding to the requested frequency */ volt = opp_get_voltage(opp); /* * Call into the voltage layer to get the final voltage possible * for the voltage domain associated with the device. */ voltdm = od->hwmods[0]->voltdm; ret = omap_voltage_add_userreq(voltdm, req_dev, &volt); if (ret) { dev_err(dev, "%s: Unable to get the final volt for scaling\n", __func__); goto out; } /* Do the actual scaling */ ret = omap_voltage_scale(voltdm); out: if (cpu_is_omap44xx()) read_unlock_irqrestore(&dpll_cascading_lock, flags); return ret; }
/** * omap_serial_init_port() - initialize single serial port * @bdata: port specific board data pointer * @info: platform specific data pointer * * This function initialies serial driver for given port only. * Platforms can call this function instead of omap_serial_init() * if they don't plan to use all available UARTs as serial ports. * * Don't mix calls to omap_serial_init_port() and omap_serial_init(), * use only one of the two. */ void __init omap_serial_init_port(struct omap_board_data *bdata, struct omap_uart_port_info *info) { struct omap_hwmod *oh; struct omap_device *od; struct omap_uart_port_info *pdata; char *name = DRIVER_NAME; if (WARN_ON(!bdata)) return; if (WARN_ON(bdata->id < 0)) return; if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS)) return; oh = omap_uart_hwmod_lookup(bdata->id); if (!oh) return; if (info == NULL) info = omap_serial_default_info; pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (!pdata) { pr_err("Memory allocation for UART pdata failed\n"); return; } if (cpu_is_omap34xx() || cpu_is_omap44xx()) pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS; omap_uart_idle_init(pdata, bdata->id); pdata->uartclk = OMAP24XX_BASE_BAUD * 16; pdata->flags = UPF_BOOT_AUTOCONF; pdata->enable_wakeup = omap_uart_wakeup_enable; pdata->use_dma = info->use_dma; pdata->chk_wakeup = omap_uart_chk_wakeup; pdata->dma_rx_buf_size = info->dma_rx_buf_size; pdata->dma_rx_poll_rate = info->dma_rx_poll_rate; pdata->dma_rx_timeout = info->dma_rx_timeout; pdata->auto_sus_timeout = info->auto_sus_timeout; pdata->wake_peer = info->wake_peer; pdata->rts_mux_driver_control = info->rts_mux_driver_control; pdata->wer = info->wer; if (bdata->id == omap_uart_con_id) { pdata->console_uart = true; #ifdef CONFIG_DEBUG_LL pdata->auto_sus_timeout = -1; #endif } if (pdata->use_dma && cpu_is_omap44xx() && omap_rev() > OMAP4430_REV_ES1_0) pdata->errata |= OMAP4_UART_ERRATA_i659_TX_THR; od = omap_device_build(name, bdata->id, oh, pdata, sizeof(*pdata), omap_uart_latency, ARRAY_SIZE(omap_uart_latency), false); WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n", name, oh->name); oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) || (pdata->wk_en && pdata->wk_mask)) { device_init_wakeup(&od->pdev.dev, true); } kfree(pdata); }
/** * omap3_noncore_dpll_set_rate - set non-core DPLL rate * @clk: struct clk * of DPLL to set * @rate: rounded target rate * * Set the DPLL CLKOUT to the target rate. If the DPLL can enter * low-power bypass, and the target rate is the bypass source clock * rate, then configure the DPLL for bypass. Otherwise, round the * target rate if it hasn't been done already, then program and lock * the DPLL. Returns -EINVAL upon error, or 0 upon success. */ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) { struct clk *new_parent = NULL; u16 freqsel = 0; struct dpll_data *dd; int ret; if (!clk || !rate) return -EINVAL; dd = clk->dpll_data; if (!dd) return -EINVAL; if (rate == omap2_get_dpll_rate(clk)) return 0; /* * Ensure both the bypass and ref clocks are enabled prior to * doing anything; we need the bypass clock running to reprogram * the DPLL. */ omap2_clk_enable(dd->clk_bypass); omap2_clk_enable(dd->clk_ref); if (dd->clk_bypass->rate == rate && (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) { pr_debug("clock: %s: set rate: entering bypass.\n", clk->name); ret = _omap3_noncore_dpll_bypass(clk); if (!ret) new_parent = dd->clk_bypass; } else { if (dd->last_rounded_rate != rate) omap2_dpll_round_rate(clk, rate); if (dd->last_rounded_rate == 0) return -EINVAL; /* No freqsel on OMAP4 or OMAP3630 */ if (!cpu_is_omap44xx() && !cpu_is_omap3630()) { freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n); if (!freqsel) WARN_ON(1); } pr_debug("clock: %s: set rate: locking rate to %lu.\n", clk->name, rate); ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m, dd->last_rounded_n, freqsel); if (!ret) new_parent = dd->clk_ref; } if (!ret) { /* * Switch the parent clock in the heirarchy, and make sure * that the new parent's usecount is correct. Note: we * enable the new parent before disabling the old to avoid * any unnecessary hardware disable->enable transitions. */ if (clk->usecount) { omap2_clk_enable(new_parent); omap2_clk_disable(clk->parent); } clk_reparent(clk, new_parent); clk->rate = rate; } omap2_clk_disable(dd->clk_ref); omap2_clk_disable(dd->clk_bypass); return 0; }
/* * This must be called before _set_clkdiv and _set_sysclk since McBSP register * cache is initialized here */ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; unsigned int temp_fmt = fmt; if (mcbsp_data->configured) return 0; mcbsp_data->fmt = fmt; memset(regs, 0, sizeof(*regs)); /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); /* RFIG and XFIG are not defined in 34xx */ if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { regs->rcr2 |= RFIG; regs->xcr2 |= XFIG; } if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: /* 1-bit data delay */ regs->rcr2 |= RDATDLY(1); regs->xcr2 |= XDATDLY(1); break; case SND_SOC_DAIFMT_LEFT_J: /* 0-bit data delay */ regs->rcr2 |= RDATDLY(0); regs->xcr2 |= XDATDLY(0); regs->spcr1 |= RJUST(2); /* Invert FS polarity configuration */ temp_fmt ^= SND_SOC_DAIFMT_NB_IF; break; case SND_SOC_DAIFMT_DSP_A: /* 1-bit data delay */ regs->rcr2 |= RDATDLY(1); regs->xcr2 |= XDATDLY(1); /* Invert FS polarity configuration */ temp_fmt ^= SND_SOC_DAIFMT_NB_IF; break; case SND_SOC_DAIFMT_DSP_B: /* 0-bit data delay */ regs->rcr2 |= RDATDLY(0); regs->xcr2 |= XDATDLY(0); /* Invert FS polarity configuration */ temp_fmt ^= SND_SOC_DAIFMT_NB_IF; break; default: /* Unsupported data format */ return -EINVAL; } switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* McBSP master. Set FS and bit clocks as outputs */ regs->pcr0 |= FSXM | FSRM | CLKXM | CLKRM; /* Sample rate generator drives the FS */ regs->srgr2 |= FSGM; break; case SND_SOC_DAIFMT_CBM_CFM: /* McBSP slave */ break; default: /* Unsupported master/slave configuration */ return -EINVAL; } /* Set bit clock (CLKX/CLKR) and FS polarities */ switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: /* * Normal BCLK + FS. * FS active low. TX data driven on falling edge of bit clock * and RX data sampled on rising edge of bit clock. */ regs->pcr0 |= FSXP | FSRP | CLKXP | CLKRP; break; case SND_SOC_DAIFMT_NB_IF: regs->pcr0 |= CLKXP | CLKRP; break; case SND_SOC_DAIFMT_IB_NF: regs->pcr0 |= FSXP | FSRP; break; case SND_SOC_DAIFMT_IB_IF: break; default: return -EINVAL; } return 0; }
/** * omap_hsmmc_reset() - Full reset of each HS-MMC controller * * Ensure that each MMC controller is fully reset. Controllers * left in an unknown state (by bootloader) may prevent retention * or OFF-mode. This is especially important in cases where the * MMC driver is not enabled, _or_ built as a module. * * In order for reset to work, interface, functional and debounce * clocks must be enabled. The debounce clock comes from func_32k_clk * and is not under SW control, so we only enable i- and f-clocks. **/ static void __init omap_hsmmc_reset(void) { u32 i, nr_controllers; struct clk *iclk, *fclk; if (cpu_is_omap242x()) return; nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC : (cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC); for (i = 0; i < nr_controllers; i++) { u32 v, base = 0; struct device *dev = &dummy_pdev.dev; switch (i) { case 0: base = OMAP2_MMC1_BASE; break; case 1: base = OMAP2_MMC2_BASE; break; case 2: base = OMAP3_MMC3_BASE; break; case 3: if (!cpu_is_omap44xx()) return; base = OMAP4_MMC4_BASE; break; case 4: if (!cpu_is_omap44xx()) return; base = OMAP4_MMC5_BASE; break; } if (cpu_is_omap44xx()) base += OMAP4_MMC_REG_OFFSET; dummy_pdev.id = i; dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i); iclk = clk_get(dev, "ick"); if (IS_ERR(iclk)) goto err1; if (clk_enable(iclk)) goto err2; fclk = clk_get(dev, "fck"); if (IS_ERR(fclk)) goto err3; if (clk_enable(fclk)) goto err4; omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG); v = omap_readl(base + MMCHS_SYSSTATUS); while (!(omap_readl(base + MMCHS_SYSSTATUS) & MMCHS_SYSSTATUS_RESETDONE)) cpu_relax(); clk_disable(fclk); clk_put(fclk); clk_disable(iclk); clk_put(iclk); } return; err4: clk_put(fclk); err3: clk_disable(iclk); err2: clk_put(iclk); err1: printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, " "cannot reset.\n", __func__, i); }
/* ------------------------------------------------------------------------*//** * @FUNCTION audit_performances * @BRIEF audit performances (CPU Load, C-States, OPP, * memory bandwidth, timers, interrrupts, ...). * @RETURNS 0 in case of success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_ARG * OMAPCONF_ERR_NOT_AVAILABLE * @param[in] stream: output file (NULL: no output (silent)) * @param[in] duration: audit duration, in seconds (>= 1). * @param[in] delay: initial wait delay before starting audit (in sec) * @DESCRIPTION audit performance (CPU Load, C-States, OPP, * memory bandwidth, timers, interrrupts, ...). *//*------------------------------------------------------------------------ */ int audit_performances(FILE *stream, unsigned int duration, unsigned int delay) { int ret = 0; unsigned short skip_proc_stats_audit = 0; unsigned int cpu_cores_cnt = 0, cpu_online_cores_cnt = 0; unsigned short *cpu_online = NULL; unsigned int *idle_t0 = NULL, *iowait_t0 = NULL, *sum_t0 = NULL; unsigned int *idle_t1 = NULL, *iowait_t1 = NULL, *sum_t1 = NULL; unsigned int *idle_cnt = NULL, *iowait_cnt = NULL, *sum_cnt = NULL; double *load = NULL, load_total = 0; unsigned int cstates_nbr = 0; uint64_t cstates_usage[MAX_CSTATE][3] = { {0} }; uint64_t cstates_time[MAX_CSTATE][3] = { {0} }; unsigned short emif = 0; unsigned int emif_busy_cycles[2] = { 0 }; unsigned int emif_cycles[2] = { 0 }; unsigned int emif_delta_cycles = 0, emif_delta_busy_cycles = 0; double emif_load = 0; uint64_t *time_in_opp_t0 = NULL; uint64_t *time_in_opp_t1 = NULL; uint64_t *time_in_opp_cnt = NULL; uint64_t total_trans_t0 = 0, total_trans_t1 = 0, total_trans_cnt = 0; unsigned int i = 0; uint64_t sec = 0, msec = 0, usec = 0, active_c0_time = 0; double pct = 0; char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN]; unsigned int row = 0; char name[16] = { 0 }; FILE *fp = NULL; char perf_summary_file[64]; FILE *fp_irq_1 = NULL, *fp_irq_2 = NULL, *fp_timerstats = NULL; unsigned int irq_total_count = 0, occurred_irq_count = 0, timer_count = 0; genlist occurred_irq_list, timerstats_list; irq_info irq_inf = { 0 }; timerstat_info timer_inf = { 0 }; char irq_snap_file1[32] = { 0 }; char irq_snap_file2[32] = { 0 }; char timerstats_file[32] = { 0 }; char timerstats_summary[256] = { 0 }; unsigned int skip_irq_audit = 0, skip_cstate_audit = 0; int skip_timerstats_audit = 0; char *workdir = NULL; unsigned short skip_cpufreq_audit = 0; unsigned int opp_cnt = 0; if (duration == 0) { fprintf(stream, "Duration should be at least 1 second ...\n\n"); ret = OMAPCONF_ERR_ARG; goto audit_performances_exit; } if (!cpu_is_omap44xx() && !cpu_is_omap54xx()) { fprintf(stream, "Unsupported platform, sorry...\n\n"); ret = OMAPCONF_ERR_CPU; goto audit_performances_exit; } /* Retrieve a writable directory */ workdir = workdir_get(); if (workdir != NULL) { strcpy(irq_snap_file1, workdir); strcpy(irq_snap_file2, workdir); strcpy(timerstats_file, workdir); strcpy(perf_summary_file, workdir); strcat(irq_snap_file1, "proc_interrupts_1"); strcat(irq_snap_file2, "proc_interrupts_2"); strcat(timerstats_file, "proc_timerstats"); strcat(perf_summary_file, "performance_audit_report.txt"); skip_irq_audit = 0; skip_timerstats_audit = 0; } else { skip_irq_audit = 1; skip_timerstats_audit = 1; } /* Open trace output file */ fp = fopen(perf_summary_file, "w"); if (fp == NULL) { fprintf(stderr, "%s(): could not create %s!\n", __func__, perf_summary_file); } else { fprintf(fp, "OMAP Performance Audit Summary\n\n"); omapconf_revision_show(fp); chips_info_show(fp, 1); release_info_show(fp); } /* Retrieve number of CPU cores and allocate buffers */ cpu_cores_cnt = cpu_cores_count_get(); if (cpu_cores_cnt < 1) { skip_proc_stats_audit = 1; } else { dprintf("%s(): found %u cores\n", __func__, cpu_cores_cnt); cpu_online = malloc(cpu_cores_cnt * sizeof(unsigned int)); idle_t0 = malloc(cpu_cores_cnt * sizeof(unsigned int)); iowait_t0 = malloc(cpu_cores_cnt * sizeof(unsigned int)); sum_t0 = malloc(cpu_cores_cnt * sizeof(unsigned int)); idle_t1 = malloc(cpu_cores_cnt * sizeof(unsigned int)); iowait_t1 = malloc(cpu_cores_cnt * sizeof(unsigned int)); sum_t1 = malloc(cpu_cores_cnt * sizeof(unsigned int)); idle_cnt = malloc(cpu_cores_cnt * sizeof(unsigned int)); iowait_cnt = malloc(cpu_cores_cnt * sizeof(unsigned int)); sum_cnt = malloc(cpu_cores_cnt * sizeof(unsigned int)); load = malloc(cpu_cores_cnt * sizeof(double)); if ((cpu_online == NULL) || (idle_t0 == NULL) || (iowait_t0 == NULL) || (sum_t0 == NULL) || (idle_t1 == NULL) || (iowait_t1 == NULL) || (sum_t1 == NULL) || (iowait_cnt == NULL) || (iowait_cnt == NULL) || (sum_cnt == NULL) || (load == NULL)) { fprintf(stderr, "%s(): could not allocate buffers for " "CPU stats!\n", __func__); skip_proc_stats_audit = 1; } dprintf("%s(): CPU stats buffers allocated.\n", __func__); skip_proc_stats_audit = 0; } /* Retrieve number of MPU OPPs and allocate buffers */ opp_cnt = cpufreq_opp_nbr_get(); if (opp_cnt == 0) { skip_cpufreq_audit = 1; } else { dprintf("%s(): found %u MPU OPPs\n", __func__, opp_cnt); time_in_opp_t0 = malloc(opp_cnt * sizeof(uint64_t)); time_in_opp_t1 = malloc(opp_cnt * sizeof(uint64_t)); time_in_opp_cnt = malloc(opp_cnt * sizeof(uint64_t)); if ((time_in_opp_t0 == NULL) || (time_in_opp_t1 == NULL) || (time_in_opp_cnt == NULL)) { fprintf(stderr, "%s(): could not allocate buffers for " "CPUFREQ stats!\n", __func__); skip_cpufreq_audit = 1; } dprintf("%s(): CPUFREQ stats buffers allocated.\n", __func__); skip_cpufreq_audit = 0; } /* Configure EMIF counters to count data bus busy cycles (OMAP4) */ if (cpu_is_omap44xx()) { ret = emif44xx_perf_cnt_configure(EMIF44XX_0, EMIF44XX_PERF_CNT_1, EMIF44XX_PERF_CNT_FILTER_DATA_TRANSFER_CYCLES, -1, EMIF44XX_MEMADDRSPACE_DISABLED); ret |= emif44xx_perf_cnt_configure(EMIF44XX_1, EMIF44XX_PERF_CNT_1, EMIF44XX_PERF_CNT_FILTER_DATA_TRANSFER_CYCLES, -1, EMIF44XX_MEMADDRSPACE_DISABLED); if (ret != 0) { strncpy(timerstats_summary, "Unexpected error occurred while configuring " "EMIF performance counters!!!\n\n", 256); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); ret = OMAPCONF_ERR_NOT_AVAILABLE; goto audit_performances_exit; } dprintf("%s(): EMIF counters configured.\n", __func__); } /* Retrieve number of active C-State(s) */ cstates_nbr = cstate_get_number(); if (cstates_nbr == 0) { cstates_nbr = 0; skip_cstate_audit = 1; } else { skip_cstate_audit = 0; dprintf("%s(): found %u C-State(s)\n", __func__, cstates_nbr); } if (fp != NULL) { fprintf(fp, "Audit duration: %us\n", duration); fprintf(fp, "Audit initial delay: %us\n\n", delay); } /* Initial delay before starting capture */ if (delay >= 1) { if (stream != NULL) fprintf(stream, "Wait for initial delay (%u sec), then" " sample various Key Performance Indicators " "over %u second(s) ...\n\n", delay, duration); sleep(delay); } else { if (stream != NULL) fprintf(stream, "Sampling various Key Performance Indicators " "over %u second(s) ...\n\n", duration); } /* Save current C-State usage & time counters */ if (skip_cstate_audit == 0) { for (i = 0; i < cstates_nbr; i++) { cstates_usage[i][0] = cstate_get_usage(i); cstates_time[i][0] = cstate_get_time(i); } } /* Save current cpufreq stats */ if (skip_cpufreq_audit == 0) { for (i = 0; i < opp_cnt; i++) { time_in_opp_t0[i] = cpufreq_time_in_state_get(i); dprintf("%s(): time_in_opp_t0[%u] = %llu\n", __func__, i, time_in_opp_t0[i]); } total_trans_t0 = cpufreq_total_transitions_get(); } /* Save current cpu usage stats */ if (skip_proc_stats_audit == 0) { for (i = 0; i < cpu_cores_cnt; i++) { ret = cpu_proc_stats_get(i, &idle_t0[i], &iowait_t0[i], &sum_t0[i]); if (ret != 0) { cpu_online[i] = 0; dprintf("%s(): CPU%u offline\n", __func__, i); } else { cpu_online[i] = 1; } } } /* Get current EMIFs total & data transfer cycles */ if (cpu_is_omap44xx()) { emif_busy_cycles[0] = 0; for (emif = 0; emif < EMIF44XX_MAX; emif++) { emif_busy_cycles[0] += emif44xx_perf_cnt_get_count( (emif44xx_ids) emif, EMIF44XX_PERF_CNT_1); } emif_cycles[0] = emif44xx_perf_cnt_get_time(EMIF44XX_0); } /* Save current interrupt stats */ if (skip_irq_audit != 1) { ret = irq_snapshot_save(irq_snap_file1); if (ret != 0) skip_irq_audit = 1; } /* Save current timer stats */ /* Stop timer statistic collector, if enabled */ skip_timerstats_audit = timerstats_stop(); if (skip_timerstats_audit == 0) skip_timerstats_audit = timerstats_start(); /* Sleep for some time before sampling again usage counters */ sleep(duration); /* Get new EMIFs total & data transfer cycles */ if (cpu_is_omap44xx()) { emif_busy_cycles[1] = 0; for (emif = 0; emif < EMIF44XX_MAX; emif++) { emif_busy_cycles[1] += emif44xx_perf_cnt_get_count( (emif44xx_ids) emif, EMIF44XX_PERF_CNT_1); } emif_cycles[1] = emif44xx_perf_cnt_get_time(EMIF44XX_0); } if (skip_timerstats_audit == 0) skip_timerstats_audit = timerstats_stop(); /* Get new interrupts stats */ if (skip_irq_audit == 0) { ret = irq_snapshot_save(irq_snap_file2); if (ret != 0) { skip_irq_audit = 1; remove(irq_snap_file1); } } if (skip_timerstats_audit == 0) timerstats_save(timerstats_file); /* Get new cpu usage stats*/ if (skip_proc_stats_audit == 0) { for (i = 0; i < cpu_cores_cnt; i++) { ret = cpu_proc_stats_get(i, &idle_t1[i], &iowait_t1[i], &sum_t1[i]); if (ret != 0) { cpu_online[i] = 0; dprintf("%s(): CPU%u offline\n", __func__, i); } else { cpu_online[i] = 1; } } } /* Get new cpufreq stats */ if (skip_cpufreq_audit == 0) { for (i = 0; i < opp_cnt; i++) { time_in_opp_t1[i] = cpufreq_time_in_state_get(i); dprintf("%s(): time_in_opp_t1[%u] = %llu\n", __func__, i, time_in_opp_t1[i]); } total_trans_t1 = cpufreq_total_transitions_get(); } /* Get new C-State usage counters */ if (skip_cstate_audit == 0) { for (i = 0; i < cstates_nbr; i++) { cstates_usage[i][1] = cstate_get_usage(i); cstates_time[i][1] = cstate_get_time(i); dprintf("%s(): cstates_usage[%u][0] = " "%llu\n", __func__, i, cstates_usage[i][0]); dprintf("%s(): cstates_usage[%u][1] = " "%llu\n", __func__, i, cstates_usage[i][1]); dprintf("%s(): cstates_time[%u][0] = " "%llu\n", __func__, i, cstates_time[i][0]); dprintf("%s(): cstates_time[%u][1] = " "%llu\n", __func__, i, cstates_time[i][1]); } } /* Process data */ if (cpu_is_omap44xx()) { emif_delta_busy_cycles = count32_delta( emif_busy_cycles[0], emif_busy_cycles[1]); emif_delta_cycles = 2 * count32_delta( emif_cycles[0], emif_cycles[1]); dprintf("%s(): EMIF delta_busy_cycles=%u, delta_cycles=%u\n", __func__, emif_delta_busy_cycles, emif_delta_cycles); emif_load = 100.0 * ( (double) emif_delta_busy_cycles / emif_delta_cycles); dprintf("%s(): EMIF load = %lf%%\n", __func__, emif_load); } if (skip_cpufreq_audit == 0) { total_trans_cnt = count64_delta(total_trans_t0, total_trans_t1); dprintf("CPUFREQ:\n"); dprintf(" total transitions = %llu\n", total_trans_cnt); for (i = 0; i < opp_cnt; i++) { time_in_opp_cnt[i] = count64_delta(time_in_opp_t0[i], time_in_opp_t1[i]); #ifdef AUDIT_DEBUG /* FIXME: retrieve cpufreq sampling rate (variable) */ if (cpu_is_omap44xx()) printf(" time in OPP %s = %llums\n", opp44xx_name_get(i + 1, OMAP4_VDD_MPU), time_in_opp_cnt[i] * 10); else printf(" time in OPP %s = %llums\n", opp54xx_name_get(i + 1), time_in_opp_cnt[i] * 10); #endif } } if (skip_cstate_audit == 0) { for (i = 0; i < cstates_nbr; i++) { cstates_usage[i][2] = count64_delta( cstates_usage[i][0], cstates_usage[i][1]); cstates_time[i][2] = count64_delta( cstates_time[i][0], cstates_time[i][1]); } } /* Compute & Show C-State Statistics */ if (skip_cstate_audit == 1) { strncpy(timerstats_summary, "WARNING: could not retrieve C-State number. " "Skipping C-States audit.\n\n", 256); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); } else { autoadjust_table_init(table); row = 0; strncpy(table[row][0], "C-State", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Entered?", TABLE_MAX_ELT_LEN); strncpy(table[row][2], "Hit Number", TABLE_MAX_ELT_LEN); strncpy(table[row][3], "Time Spent (s)", TABLE_MAX_ELT_LEN); strncpy(table[row][4], "Time Spent (%)", TABLE_MAX_ELT_LEN); row++; strncpy(table[row][0], "Active + \"C0\"", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Yes", TABLE_MAX_ELT_LEN); active_c0_time = duration * 1000000; for (i = 0; i < cstates_nbr; i++) { if (active_c0_time > cstates_time[i][2]) active_c0_time -= cstates_time[i][2]; else /* * It may be possible that * active_c0_time is < cstates_time[i][2] * (duration may fluctuate a little depending on * system load). Make sure it doesn't cross 0 as * it's an unsigned interger. */ active_c0_time = 0; } sec = active_c0_time / 1000000; msec = (active_c0_time % 1000000) / 1000; usec = active_c0_time % 1000; snprintf(table[row][3], TABLE_MAX_ELT_LEN, "%llus %llums %lluus", sec, msec, usec); pct = ((double) active_c0_time / (double) (duration * 1000000)) * 100.0; snprintf(table[row][4], TABLE_MAX_ELT_LEN, "%3.1f%%", pct); row++; for (i = 0; i < cstates_nbr; i++) { snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s", cstate_get_name(i, name)); if (cstates_usage[i][2] != 0) { dprintf("%s(): C%u entered\n", __func__, i + 1); strncpy(table[row][1], "Yes", TABLE_MAX_ELT_LEN); snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%llu", cstates_usage[i][2]); sec = cstates_time[i][2] / 1000000; msec = (cstates_time[i][2] % 1000000) / 1000; usec = cstates_time[i][2] % 1000; snprintf(table[row][3], TABLE_MAX_ELT_LEN, "%llus %llums %lluus", sec, msec, usec); pct = ((double) cstates_time[i][2] / (double) (duration * 1000000)) * 100.0; snprintf(table[row][4], TABLE_MAX_ELT_LEN, "%3.1f%%", pct); } else { dprintf("%s(): C%u not entered\n", __func__, i + 1); strncpy(table[row][1], "No", TABLE_MAX_ELT_LEN); } row++; } /* Print results */ strncpy(timerstats_summary, "NB: this table shows statistics about " "the ATTEMPTED C-States, not the effectively " "entered C-States (not supported by kernel " "idle framework yet).\nAs a consequence, these " "C-States MAY or MAY NOT have been entered, " "depending on HW conditions.\n\n\n", 256); if (stream != NULL) { autoadjust_table_fprint(stream, table, row, 5); fputs(timerstats_summary, stream); } if (fp != NULL) { autoadjust_table_fprint(fp, table, row, 5); fputs(timerstats_summary, fp); } } /* Show CPUFreq stats */ if (skip_cpufreq_audit == 1) { strncpy(timerstats_summary, "WARNING: could not retrieve MPU " "OPP number. CPUFreq audit skipped.\n\n", 256); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); } else { autoadjust_table_init(table); row = 0; strncpy(table[row][0], "MPU OPP", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Time Spent in OPP", TABLE_MAX_ELT_LEN); row++; for (i = 0; i < opp_cnt; i++) { if (cpu_is_omap44xx()) snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s", opp44xx_name_get(i + 1, OMAP4_VDD_MPU)); else snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s", opp54xx_name_get(i + 1)); snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%llus%llums", time_in_opp_cnt[i] / 100, (time_in_opp_cnt[i] % 100) * 10); row++; } cpufreq_scaling_governor_get(name); if (name != NULL) sprintf(timerstats_summary, "CPUFreq Governor: %s\n", name); else sprintf(timerstats_summary, "CPUFreq Governor: not found!\n"); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); sprintf(timerstats_summary, "Total number of OPP transitions: %llu\n\n", total_trans_cnt); if (stream != NULL) { fputs(timerstats_summary, stream); autoadjust_table_fprint(stream, table, row, 2); fprintf(stream, "\n"); } if (fp != NULL) { fputs(timerstats_summary, fp); autoadjust_table_fprint(fp, table, row, 2); fprintf(fp, "\n"); } } /* Show CPU Load stats */ if (skip_proc_stats_audit == 1) { strncpy(timerstats_summary, "WARNING: could not retrieve CPU " "cores number. CPU Load audit skipped.\n\n", 256); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); } else { autoadjust_table_init(table); row = 0; strncpy(table[row][0], "CPU", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Average Load (*)", TABLE_MAX_ELT_LEN); row++; cpu_online_cores_cnt = 0; load_total = 0.0; for (i = 0; i < cpu_cores_cnt; i++) { snprintf(table[row][0], TABLE_MAX_ELT_LEN, "CPU%u", i); if ((i >= 1) && (cpu_online[i] == 0)) { snprintf(table[row][1], TABLE_MAX_ELT_LEN, "Offline"); row++; continue; } idle_cnt[i] = count32_delta(idle_t0[i], idle_t1[i]); iowait_cnt[i] = count32_delta(iowait_t0[i], iowait_t1[i]); sum_cnt[i] = count32_delta(sum_t0[i], sum_t1[i]); dprintf("%s(): idle_cnt[%u] = %u, iowait_cnt[%u] = %u, " "sum_cnt[%u] = %u\n", __func__, i, idle_cnt[i], i, iowait_cnt[i], i, sum_cnt[i]); if (sum_cnt[i] != 0) { load[i] = cpu_load_get(idle_cnt[i], iowait_cnt[i], sum_cnt[i]); cpu_online_cores_cnt++; } else { /* * Due to tickless feature, it is possible that * that no tick occured during this sampling * window and so /proc/stat counters were not * incremented. => cpu load = 0. */ load[i] = 0.0; } load_total += load[i]; dprintf("%s(): CPU%u load=%.2lf%%\n", __func__, i, load[i]); snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%.2lf%%", load[i]); row++; } dprintf("%s(): cpu_online_cores_cnt=%u\n", __func__, cpu_online_cores_cnt); load_total = load_total / cpu_online_cores_cnt; snprintf(table[row][0], TABLE_MAX_ELT_LEN, "Total"); snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%.2lf%%", load_total); row++; strncpy(timerstats_summary, "(*) CANNOT be converted to Mhz. " "OPP may have changed during the audit.\n\n\n", 256); if (stream != NULL) { autoadjust_table_fprint(stream, table, row, 2); fputs(timerstats_summary, stream); } if (fp != NULL) { autoadjust_table_fprint(fp, table, row, 2); fputs(timerstats_summary, fp); } } /* Show EMIF stats */ if (cpu_is_omap44xx()) { autoadjust_table_init(table); row = 0; strncpy(table[row][0], "EMIF", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Average Load (*)", TABLE_MAX_ELT_LEN); row++; strncpy(table[row][0], "Total EMIF Data Bus Load", TABLE_MAX_ELT_LEN); snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%.2lf%%", (double) emif_load); row++; strncpy(timerstats_summary, "(*) CANNOT be converted to memory " "bandwidth (MB/s).\n DDR data busy cycles may be " "commands (not data) and data size is unknown.\n\n\n", 256); if (stream != NULL) { autoadjust_table_fprint(stream, table, row, 2); fputs(timerstats_summary, stream); } if (fp != NULL) { autoadjust_table_fprint(fp, table, row, 2); fputs(timerstats_summary, fp); } } /* Show interrupts stats */ if (skip_irq_audit == 1) { strncpy(timerstats_summary, "WARNING: could not save a snapshot of " "/proc/interrupts file. " "IRQ audit skipped.\n\n", 256); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); } else { fp_irq_1 = fopen(irq_snap_file1, "r"); fp_irq_2 = fopen(irq_snap_file2, "r"); if ((fp_irq_1 == NULL) || (fp_irq_2 == NULL)) { fprintf(stderr, "%s(): could not open interrupts " "snapshot files!\n\n", __func__); ret = OMAPCONF_ERR_NOT_AVAILABLE; goto audit_performances_exit; } autoadjust_table_init(table); row = 0; strncpy(table[row][0], "IRQ #", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Device Name", TABLE_MAX_ELT_LEN); strncpy(table[row][2], "Occurrence", TABLE_MAX_ELT_LEN); strncpy(table[row][3], "Proportion", TABLE_MAX_ELT_LEN); strncpy(table[row][4], "Rate", TABLE_MAX_ELT_LEN); row++; irq_total_count = irq_total_count_get(fp_irq_2) - irq_total_count_get(fp_irq_1); dprintf("%s(): irq_total_count=%d\n", __func__, irq_total_count); occurred_irq_count = irq_occurred_list_get(fp_irq_1, fp_irq_2, &occurred_irq_list); dprintf("%s(): # of irq lines that occurred = %d\n", __func__, occurred_irq_count); irq_occurred_list_sort(&occurred_irq_list); for (i = 0; i < occurred_irq_count; i++) { genlist_get(&occurred_irq_list, i, &irq_inf); snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%d", irq_inf.nbr); strncpy(table[row][1], irq_inf.dev_name, TABLE_MAX_ELT_LEN); pct = (double) irq_inf.count / (double) irq_total_count; pct *= 100.0; snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%u", irq_inf.count); snprintf(table[row][3], TABLE_MAX_ELT_LEN, "%.1lf%%", pct); pct = (double) irq_inf.count / (double) duration; snprintf(table[row][4], TABLE_MAX_ELT_LEN, "%.1lf/sec", pct); row++; } genlist_free(&occurred_irq_list); fclose(fp_irq_1); remove(irq_snap_file1); fclose(fp_irq_2); remove(irq_snap_file2); sprintf(timerstats_summary, "CPU was interrupted %d times by the following %d " "sources:\n", irq_total_count, occurred_irq_count); if (stream != NULL) { fputs(timerstats_summary, stream); autoadjust_table_fprint(stream, table, row, 5); } if (fp != NULL) { fputs(timerstats_summary, fp); autoadjust_table_fprint(fp, table, row, 5); } } /* Show timer stats */ if (skip_timerstats_audit != 0) { strncpy(timerstats_summary, "Timer Statistics: unable to capture kernel timer " "statistics.\nMake sure that CONFIG_TIMER_STATS " "are enabled in the kernel configuration.\n\n", 256); if (stream != NULL) fputs(timerstats_summary, stream); if (fp != NULL) fputs(timerstats_summary, fp); } else { fp_timerstats = fopen(timerstats_file, "r"); if (fp_timerstats == NULL) { fprintf(stderr, "%s(): could not open timer stats " "snapshot file!\n\n", __func__); ret = OMAPCONF_ERR_NOT_AVAILABLE; goto audit_performances_exit; } autoadjust_table_init(table); row = 0; strncpy(table[row][0], "# Timer Events", TABLE_MAX_ELT_LEN); strncpy(table[row][1], "Deferrable", TABLE_MAX_ELT_LEN); strncpy(table[row][2], "Process ID", TABLE_MAX_ELT_LEN); strncpy(table[row][3], "Process Name", TABLE_MAX_ELT_LEN); strncpy(table[row][4], "Init Function", TABLE_MAX_ELT_LEN); strncpy(table[row][5], "Callback Function", TABLE_MAX_ELT_LEN); row++; timer_count = timerstats_list_get(fp_timerstats, &timerstats_list); dprintf("%s(): # of timers that occurred = %d\n", __func__, timer_count); timerstats_list_sort(&timerstats_list); for (i = 0; i < timer_count; i++) { genlist_get(&timerstats_list, i, &timer_inf); snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%d", timer_inf.count); strncpy(table[row][1], timer_inf.deferrable, TABLE_MAX_ELT_LEN); snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%d", timer_inf.pid); strncpy(table[row][3], timer_inf.name, TABLE_MAX_ELT_LEN); strncpy(table[row][4], timer_inf.init_fxn, TABLE_MAX_ELT_LEN); strncpy(table[row][5], timer_inf.callback, TABLE_MAX_ELT_LEN); row++; } timerstats_get_summary(fp_timerstats, &timerstats_summary[0]); genlist_free(&timerstats_list); fclose(fp_timerstats); remove(timerstats_file); if (stream != NULL) { fputs(timerstats_summary, stream); autoadjust_table_fprint(stream, table, row, 6); } if (fp != NULL) { fputs(timerstats_summary, fp); autoadjust_table_fprint(fp, table, row, 6); } } if ((fp != NULL) && (stream != NULL)) fprintf(stream, "Performance Audit data saved into " "\"%s\" file.\n\n", perf_summary_file); ret = 0; audit_performances_exit: if (cpu_online != NULL) free(cpu_online); if (idle_t0 != NULL) free(idle_t0); if (iowait_t0 != NULL) free(iowait_t0); if (sum_t0 != NULL) free(sum_t0); if (idle_t1 != NULL) free(idle_t1); if (iowait_t1 != NULL) free(iowait_t1); if (sum_t1 != NULL) free(sum_t1); if (idle_cnt != NULL) free(idle_cnt); if (iowait_cnt != NULL) free(iowait_cnt); if (sum_cnt != NULL) free(sum_cnt); if (load != NULL) free(load); if (time_in_opp_t0 != NULL) free(time_in_opp_t0); if (time_in_opp_t1 != NULL) free(time_in_opp_t1); if (time_in_opp_cnt != NULL) free(time_in_opp_cnt); if (fp != NULL) fclose(fp); return ret; }
/* * Here we start the McBSP, by enabling transmitter, receiver or both. * If no transmitter or receiver is active prior calling, then sample-rate * generator and frame sync are started. */ void omap_mcbsp_start(unsigned int id, int tx, int rx) { struct omap_mcbsp *mcbsp; int enable_srg = 0; u16 w; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; } mcbsp = id_to_mcbsp_ptr(id); if (cpu_is_omap34xx()) omap_st_start(mcbsp); /* Only enable SRG, if McBSP is master */ w = MCBSP_READ_CACHE(mcbsp, PCR0); if (w & (FSXM | FSRM | CLKXM | CLKRM)) enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) | MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1); if (enable_srg) { /* Start the sample generator */ w = MCBSP_READ_CACHE(mcbsp, SPCR2); MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6)); } /* Enable transmitter and receiver */ tx &= 1; w = MCBSP_READ_CACHE(mcbsp, SPCR2); MCBSP_WRITE(mcbsp, SPCR2, w | tx); rx &= 1; w = MCBSP_READ_CACHE(mcbsp, SPCR1); MCBSP_WRITE(mcbsp, SPCR1, w | rx); /* * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec * REVISIT: 100us may give enough time for two CLKSRG, however * due to some unknown PM related, clock gating etc. reason it * is now at 500us. */ udelay(500); if (enable_srg) { /* Start frame sync */ w = MCBSP_READ_CACHE(mcbsp, SPCR2); MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); } if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { /* Release the transmitter and receiver */ w = MCBSP_READ_CACHE(mcbsp, XCCR); w &= ~(tx ? XDISABLE : 0); MCBSP_WRITE(mcbsp, XCCR, w); w = MCBSP_READ_CACHE(mcbsp, RCCR); w &= ~(rx ? RDISABLE : 0); MCBSP_WRITE(mcbsp, RCCR, w); } /* Dump McBSP Regs */ omap_mcbsp_dump_reg(id); }
/* ------------------------------------------------------------------------*//** * @FUNCTION mod44xx_get_standby_mode * @BRIEF retrieve omap module's standby mode * @RETURNS 1 if success * 0 if omap module's registers NOT accessible * OMAPCONF_ERR_ARG * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_INTERNAL * @param[in] module_id: omap module ID * @param[in,out] mode: returned omap module's standby mode * @DESCRIPTION retrieve omap module's standby mode *//*------------------------------------------------------------------------ */ int mod44xx_get_standby_mode(mod44xx_id module_id, mod_standby_mode *mode) { int ret_val = 0; unsigned int sysconfig; mod_interface_type type; char name[MOD44XX_MAX_NAME_LENGTH]; *mode = MOD_STANDBY_MODE_MAX; if (!cpu_is_omap44xx()) { fprintf(stderr, "%s(): unsupported cpu!!!\n", __func__); ret_val = OMAPCONF_ERR_CPU; goto mod44xx_get_standby_mode_end; } if (module_id >= OMAP4_MODULE_ID_MAX) { fprintf(stderr, "%s(): incorrect module id!!! (%u)\n", __func__, module_id); ret_val = OMAPCONF_ERR_ARG; goto mod44xx_get_standby_mode_end; } mod44xx_get_interface_type(module_id, &type); if ((module_id != OMAP4_MPU_M3) && (type != MOD_INTERFACE_MASTER) && (type != MOD_INTERFACE_DUAL)) { dprintf("%s(): module #%d name = %s has no master interface\n", __func__, module_id, mod44xx_get_name(module_id, name)); ret_val = OMAPCONF_ERR_NOT_AVAILABLE; goto mod44xx_get_standby_mode_end; } ret_val = mod44xx_is_accessible(module_id); if (ret_val == 0) { /* Module is NOT accessible */ ret_val = 0; dprintf("%s(): module #%d name = %s is NOT accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); goto mod44xx_get_standby_mode_end; } else if (ret_val != 1) { /* Internal error */ dprintf("%s(): mod44xx_is_accessible() returned with %d!!!\n", __func__, ret_val); goto mod44xx_get_standby_mode_end; } /* Module is accessible */ dprintf("%s(): module #%d name = %s is accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); if ((module_id != OMAP4_MPU_M3) && (mod44xx_info_table[module_id].sysconfig_addr == NULL)) { fprintf(stderr, "%s(): error module %s interface type is not NONE but SYSCONFIG ADDR == NULL\n", __func__, mod44xx_get_name(module_id, name)); ret_val = OMAPCONF_ERR_INTERNAL; goto mod44xx_get_standby_mode_end; } if (module_id != OMAP4_MPU_M3) { OMAP_READREG((unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); dprintf("%s(): SYSCONFIG ADDR = 0x%08X SYSCONFIG = 0x%08X\n", __func__, (unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); } else { OMAP_READREG((unsigned int) OMAP4430_STANDBY_CORE_SYSCONFIG, sysconfig); dprintf( "%s(): SYSCONFIG ADDR = 0x%08X, STANDBY_CORE_SYSCONFIG = 0x%08X\n", __func__, (unsigned int) OMAP4430_IDLE_CORE_SYSCONFIG, sysconfig); } /* Check module's standby mode */ switch (module_id) { case OMAP4_IVAHD: case OMAP4_ICONT1: case OMAP4_ICONT2: case OMAP4_VDMA: case OMAP4_IME3: case OMAP4_ILF3: case OMAP4_AESS: case OMAP4_ISP5: case OMAP4_SIMCOP: case OMAP4_SIMCOP_DMA: case OMAP4_FDIF: case OMAP4_GFX: case OMAP4_MMC1_HL: case OMAP4_MMC2_HL: case OMAP4_MMC3_HL: case OMAP4_MMC4_HL: case OMAP4_MMC5_HL: case OMAP4_UNIPRO1: case OMAP4_FSUSBHOST: case OMAP4_HSUSBHOST: case OMAP4_ISS: *mode = (mod_standby_mode) extract_bitfield(sysconfig, 4, 2); ret_val = 1; dprintf("%s(): module %s standby mode (bits [5:4])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; case OMAP4_MPU_M3: *mode = (mod_standby_mode) extract_bitfield(sysconfig, 0, 2); ret_val = 1; dprintf("%s(): module %s standby mode (bits [0:12])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; default: *mode = (mod_standby_mode) extract_bitfield(sysconfig, 12, 2); ret_val = 1; dprintf("%s(): module %s standby mode (bits [13:12])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); } mod44xx_get_standby_mode_end: return ret_val; }
void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) { struct omap_hwmod *oh; struct omap_device *od; struct platform_device *pdev; struct device *dev = NULL; int bus_id = -1; const char *oh_name, *name; struct omap_musb_board_data *board_data; if (musb_board_data) board_data = musb_board_data; else board_data = &musb_default_board_data; /* * REVISIT: This line can be removed once all the platforms using * musb_core.c have been converted to use use clkdev. */ musb_plat.clock = "ick"; musb_plat.board_data = board_data; musb_plat.power = board_data->power >> 1; musb_plat.mode = board_data->mode; musb_plat.extvbus = board_data->extvbus; if (cpu_is_omap44xx()) omap4430_phy_init(dev); /* power down the phy */ if (cpu_is_omap3517() || cpu_is_omap3505()) { oh_name = "am35x_otg_hs"; name = "musb-am35x"; } else { oh_name = "usb_otg_hs"; name = "musb-omap2430"; } oh = omap_hwmod_lookup(oh_name); if (!oh) { pr_err("Could not look up %s\n", oh_name); return; } od = omap_device_build(name, bus_id, oh, &musb_plat, sizeof(musb_plat), omap_musb_latency, ARRAY_SIZE(omap_musb_latency), false); if (IS_ERR(od)) { pr_err("Could not build omap_device for %s %s\n", name, oh_name); return; } pdev = &od->pdev; dev = &pdev->dev; get_device(dev); dev->dma_mask = &musb_dmamask; dev->coherent_dma_mask = musb_dmamask; put_device(dev); if (cpu_is_omap44xx()) omap4430_phy_init(dev); #ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE platform_device_register(&android_usb_device); #endif }
/* ------------------------------------------------------------------------*//** * @FUNCTION mod44xx_get_autoidle_mode * @BRIEF retrieve omap module's autoidle mode * @RETURNS 1 if success * 0 if omap module's registers NOT accessible * OMAPCONF_ERR_ARG * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_INTERNAL * @param[in] module_id: omap module ID * @param[in,out] mode: returned omap module's autoidle mode * @DESCRIPTION retrieve omap module's autoidle mode *//*------------------------------------------------------------------------ */ int mod44xx_get_autoidle_mode(mod44xx_id module_id, mod_autoidle_mode *mode) { int ret_val = 0; unsigned int sysconfig; char name[MOD44XX_MAX_NAME_LENGTH]; mod_interface_type type; *mode = MOD_AUTOIDLE_MODE_MAX; if (!cpu_is_omap44xx()) return OMAPCONF_ERR_CPU; if (module_id >= OMAP4_MODULE_ID_MAX) return OMAPCONF_ERR_ARG; mod44xx_get_interface_type(module_id, &type); if (type == MOD_INTERFACE_NONE) { dprintf("%s(): module #%d name = %s has no SYSCONFIG\n", __func__, module_id, mod44xx_get_name(module_id, name)); return OMAPCONF_ERR_NOT_AVAILABLE; } ret_val = mod44xx_is_accessible(module_id); if (ret_val == 1) { /* Module is accessible */ dprintf("%s(): module #%d name = %s is accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); if (mod44xx_info_table[module_id].sysconfig_addr != NULL) { OMAP_READREG((unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); dprintf( "%s(): SYSCONFIG ADDR = 0x%08X SYSCONFIG = 0x%08X\n", __func__, (unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); /* Check module's autoidle bit */ switch (module_id) { case OMAP4_CONTROL_GEN_WKUP: case OMAP4_CONTROL_PADCONF_WKUP: case OMAP4_SYNCTIMER: case OMAP4_WDT2: case OMAP4_WDT3: case OMAP4_TIMER3: case OMAP4_TIMER4: case OMAP4_TIMER5: case OMAP4_TIMER6: case OMAP4_TIMER7: case OMAP4_TIMER8: case OMAP4_TIMER9: case OMAP4_TIMER11: case OMAP4_MCASP: case OMAP4_IVAHD: case OMAP4_ICONT1: case OMAP4_ICONT2: case OMAP4_VDMA: case OMAP4_IME3: case OMAP4_ILF3: case OMAP4_MC3: case OMAP4_CALC3: case OMAP4_ECD3: case OMAP4_SMARTREFLEX_CORE: case OMAP4_SMARTREFLEX_MPU: case OMAP4_SMARTREFLEX_IVA: case OMAP4_CONTROL_GEN_CORE: case OMAP4_CONTROL_PADCONF_CORE: case OMAP4_SYSTEM_MAILBOX: case OMAP4_DMM: case OMAP4_AESS: case OMAP4_SIMCOP: case OMAP4_SIMCOP_DMA: case OMAP4_FDIF: case OMAP4_HDMI: case OMAP4_GFX: case OMAP4_MMC1_HL: case OMAP4_MMC2_HL: case OMAP4_MMC3_HL: case OMAP4_MMC4_HL: case OMAP4_MMC5_HL: case OMAP4_UNIPRO1: case OMAP4_FSUSBHOST: case OMAP4_HSUSBHOST: case OMAP4_MCSPI1_HL: case OMAP4_MCSPI2_HL: case OMAP4_MCSPI3_HL: case OMAP4_MCSPI4_HL: case OMAP4_DMIC: case OMAP4_MCBSP1: case OMAP4_MCBSP2: case OMAP4_MCBSP3: case OMAP4_MCPDM: case OMAP4_SDMA: case OMAP4_ISS: case OMAP4_BTE: case OMAP4_CBUFF: ret_val = OMAPCONF_ERR_NOT_AVAILABLE; dprintf("%s(): module %s has no AUTOIDLE bit\n", __func__, mod44xx_get_name(module_id, name)); break; case OMAP4_SLIMBUS1: case OMAP4_SLIMBUS2: /* * NB: AUTOGATINGDISABLE instead of AUTOGATING, * bit is inverted compared to other modules */ *mode = (mod_autoidle_mode) !extract_bit(sysconfig, 8); ret_val = 1; dprintf("%s(): module %s AUTOIDLE bit 8 = %d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; case OMAP4_SIMCOP_DCT: *mode = (mod_autoidle_mode) extract_bit(sysconfig, 5); ret_val = 1; dprintf("%s(): module %s AUTOIDLE bit 5 = %d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; case OMAP4_SIMCOP_VLCDJ: *mode = (mod_autoidle_mode) extract_bit(sysconfig, 3); ret_val = 1; dprintf("%s(): module %s AUTOIDLE bit 3 = %d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; case OMAP4_SIMCOP_ROT: *mode = (mod_autoidle_mode) extract_bit(sysconfig, 9); ret_val = 1; dprintf("%s(): module %s AUTOIDLE bit 9 = %d\n", mod44xx_get_name(module_id, name), *mode); break; default: *mode = (mod_autoidle_mode) extract_bit(sysconfig, 0); ret_val = 1; dprintf("%s(): module %s AUTOIDLE bit 0 = %d\n", __func__, mod44xx_get_name(module_id, name), *mode); } } else { fprintf(stderr, "omapconf (%s): error module's %s interface type is not NONE but SYSCONFIG ADDR == NULL\n", __func__, mod44xx_get_name(module_id, name)); ret_val = OMAPCONF_ERR_INTERNAL; } } else if (ret_val == 0) { /* Module is NOT accessible */ ret_val = 0; dprintf("%s(): module is NOT accessible\n", __func__); } else { /* internal error */ dprintf("%s(): mod44xx_is_accessible() returned with %d\n", __func__, ret_val); } return ret_val; }
/* ------------------------------------------------------------------------*//** * @FUNCTION mod44xx_get_idle_mode * @BRIEF retrieve omap module's idle mode * @RETURNS 1 if success * 0 if omap module's registers NOT accessible * OMAPCONF_ERR_ARG * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_INTERNAL * @param[in] module_id: omap module ID * @param[in,out] mode: returned omap module's idle mode * @DESCRIPTION retrieve omap module's idle mode *//*------------------------------------------------------------------------ */ int mod44xx_get_idle_mode(mod44xx_id module_id, mod_idle_mode *mode) { int ret_val = 0; unsigned int sysconfig; mod_interface_type type; char name[MOD44XX_MAX_NAME_LENGTH]; *mode = MOD_IDLE_MODE_MAX; if (!cpu_is_omap44xx()) { fprintf(stderr, "%s(): unsupported cpu!!!\n", __func__); ret_val = OMAPCONF_ERR_CPU; goto mod44xx_get_idle_mode_end; } if (module_id >= OMAP4_MODULE_ID_MAX) { fprintf(stderr, "%s(): incorrect module id!!! (%u)\n", __func__, module_id); ret_val = OMAPCONF_ERR_ARG; goto mod44xx_get_idle_mode_end; } mod44xx_get_interface_type(module_id, &type); if ((module_id != OMAP4_MPU_M3) && (type != MOD_INTERFACE_SLAVE) && (type != MOD_INTERFACE_DUAL)) { dprintf("%s(): module #%d name = %s has no slave interface\n", __func__, module_id, mod44xx_get_name(module_id, name)); ret_val = OMAPCONF_ERR_NOT_AVAILABLE; goto mod44xx_get_idle_mode_end; } ret_val = mod44xx_is_accessible(module_id); if (ret_val == 0) { /* Module is NOT accessible */ ret_val = 0; dprintf("%s(): module #%d name = %s is NOT accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); goto mod44xx_get_idle_mode_end; } else if (ret_val != 1) { /* internal error */ dprintf("%s(): mod44xx_is_accessible() returned with %d!!!\n", __func__, ret_val); goto mod44xx_get_idle_mode_end; } /* Module is accessible */ dprintf("%s(): module #%d name = %s is accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); if ((module_id != OMAP4_MPU_M3) && (mod44xx_info_table[module_id].sysconfig_addr == NULL)) { fprintf(stderr, "%s(): error module %s interface type is not NONE but SYSCONFIG ADDR == NULL\n", __func__, mod44xx_get_name(module_id, name)); ret_val = OMAPCONF_ERR_INTERNAL; goto mod44xx_get_idle_mode_end; } if (module_id != OMAP4_MPU_M3) { OMAP_READREG((unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); dprintf("%s(): SYSCONFIG ADDR = 0x%08X, SYSCONFIG = 0x%08X\n", __func__, (unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); } else { OMAP_READREG((unsigned int) OMAP4430_IDLE_CORE_SYSCONFIG, sysconfig); dprintf( "%s(): SYSCONFIG ADDR = 0x%08X, IDLE_CORE_SYSCONFIG = 0x%08X\n", __func__, (unsigned int) OMAP4430_IDLE_CORE_SYSCONFIG, sysconfig); } /* get module's idle mode */ switch (module_id) { case OMAP4_MCASP: case OMAP4_MPU_M3: *mode = (mod_idle_mode) extract_bitfield(sysconfig, 0, 2); ret_val = 1; dprintf("%s(): module %s idle mode (bits [1:0])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; case OMAP4_CONTROL_GEN_WKUP: case OMAP4_CONTROL_PADCONF_WKUP: case OMAP4_SLIMBUS1: case OMAP4_SLIMBUS2: case OMAP4_IVAHD: case OMAP4_ICONT1: case OMAP4_ICONT2: case OMAP4_VDMA: case OMAP4_IME3: case OMAP4_IPE3: case OMAP4_ILF3: case OMAP4_MC3: case OMAP4_CALC3: case OMAP4_ECD3: case OMAP4_CONTROL_GEN_CORE: case OMAP4_CONTROL_PADCONF_CORE: case OMAP4_SYSTEM_MAILBOX: case OMAP4_DMM: case OMAP4_AESS: case OMAP4_BTE: case OMAP4_CBUFF: case OMAP4_FDIF: case OMAP4_HDMI: case OMAP4_GFX: case OMAP4_MMC1_HL: case OMAP4_MMC2_HL: case OMAP4_MMC3_HL: case OMAP4_MMC4_HL: case OMAP4_MMC5_HL: case OMAP4_UNIPRO1: case OMAP4_FSUSBHOST: case OMAP4_HSUSBHOST: case OMAP4_MCSPI1_HL: case OMAP4_MCSPI2_HL: case OMAP4_MCSPI3_HL: case OMAP4_MCSPI4_HL: case OMAP4_DMIC: case OMAP4_MCPDM: case OMAP4_TIMER1: case OMAP4_TIMER2: case OMAP4_TIMER3: case OMAP4_TIMER4: case OMAP4_TIMER5: case OMAP4_TIMER6: case OMAP4_TIMER7: case OMAP4_TIMER8: case OMAP4_TIMER9: case OMAP4_TIMER10: case OMAP4_TIMER11: case OMAP4_ISS: *mode = (mod_idle_mode) extract_bitfield(sysconfig, 2, 2); ret_val = 1; dprintf("%s(): module %s idle mode (bits [3:2])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; case OMAP4_DSP: case OMAP4_DSP_WUGEN: case OMAP4_TCTRL: case OMAP4_RSZ: case OMAP4_SIMCOP_DCT: case OMAP4_SIMCOP_VLCDJ: case OMAP4_SIMCOP_ROT: case OMAP4_HDQ1W: ret_val = OMAPCONF_ERR_NOT_AVAILABLE; dprintf("%s(): module %s does not have IDLE mode\n", __func__, mod44xx_get_name(module_id, name)); break; case OMAP4_SMARTREFLEX_CORE: case OMAP4_SMARTREFLEX_MPU: case OMAP4_SMARTREFLEX_IVA: *mode = (mod_idle_mode) extract_bitfield(sysconfig, 24, 2); ret_val = 1; dprintf("%s(): module %s idle mode (bits [25:24])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; default: *mode = (mod_idle_mode) extract_bitfield(sysconfig, 3, 2); ret_val = 1; dprintf("%s(): module %s idle mode (bits [4:3])=%d\n", __func__, mod44xx_get_name(module_id, name), *mode); } mod44xx_get_idle_mode_end: return ret_val; }
/* ------------------------------------------------------------------------*//** * @FUNCTION mod44xx_is_accessible * @BRIEF check omap module's registers accessibility * @RETURNS 1 if omap module's registers accessible * 0 if omap module's registers NOT accessible * OMAPCONF_ERR_ARG * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * @param[in] module_id: omap module ID * @DESCRIPTION check omap module's registers accessibility *//*------------------------------------------------------------------------ */ int mod44xx_is_accessible(mod44xx_id module_id) { unsigned int cm_clkctrl_addr, cm_clkctrl; int ret = 0; mod_module_mode mmode; #ifdef MODULE44XX_DEBUG char name[MOD44XX_MAX_NAME_LENGTH]; #endif if (!cpu_is_omap44xx()) { fprintf(stderr, "%s(): cpu is not omap44xx!!!\n", __func__); ret = OMAPCONF_ERR_CPU; goto mod44xx_is_accessible_exit; } if (module_id >= OMAP4_MODULE_ID_MAX) { fprintf(stderr, "%s(): module_id >= OMAP4_MODULE_ID_MAX!!!\n", __func__); ret = OMAPCONF_ERR_ARG; goto mod44xx_is_accessible_exit; } /* Retrieve module mode */ mod44xx_get_mode(module_id, &mmode); if (mmode == MOD_DISABLED_MODE) { dprintf( "%s(): module #%d name = %s mode is disabled => NOT accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); ret = 0; goto mod44xx_is_accessible_exit; } else if (mmode == MOD_ENABLED_MODE) { dprintf( "%s(): module #%d name = %s mode is enabled => accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); ret = 1; goto mod44xx_is_accessible_exit; } /* Module mode is HW Auto, need to check status */ /* Retrieve CM_CLKCTRL address */ cm_clkctrl_addr = (unsigned int) mod44xx_info_table[module_id].cm_clkctrl_addr; dprintf("%s(): module #%d name = %s CM_CLKCTRL ADDR = 0x%08X\n", __func__, module_id, mod44xx_get_name(module_id, name), cm_clkctrl_addr); /* Retrieve module state */ if ((void *) cm_clkctrl_addr != NULL) { if (mem_read(cm_clkctrl_addr, &cm_clkctrl) != 0) { fprintf(stderr, "%s(): could not read register!!!\n", __func__); ret = OMAPCONF_ERR_REG_ACCESS; goto mod44xx_is_accessible_exit; } dprintf( "%s(): CM_CLKCTRL ADDR = 0x%08X CM_CLKCTRL = 0x%08X IDLEST = %d\n", __func__, (unsigned int) mod44xx_info_table[module_id].cm_clkctrl_addr, cm_clkctrl, extract_bitfield(cm_clkctrl, 16, 2)); /* Check if module is accessible */ switch (extract_bitfield(cm_clkctrl, 16, 2)) { case 0: /* Module is fully functional, including OCP */ dprintf( "%s(): module is fully functional, including OCP\n", __func__); ret = 1; break; case 1: /* * Module is performing transition: wakeup, or sleep, * or sleep abortion */ dprintf( "%s(): module is performing transition: wakeup, or sleep, or sleep abortion\n", __func__); ret = 0; break; case 2: /* Module is in Idle mode (only OCP part) */ dprintf( "%s(): module is in Idle mode (only OCP part)\n", __func__); ret = 0; break; case 3: /* Module is disabled and cannot be accessed */ dprintf( "%s(): module is disabled and cannot be accessed\n", __func__); ret = 0; } } else { /* mod44xx_is_accessible(): * module has NO CM_CLKCTRL, it's always ON */ dprintf("%s(): module has NO CM_CLKCTRL, always ON\n", __func__); ret = 1; } mod44xx_is_accessible_exit: dprintf("%s(%d) = %d\n", __func__, module_id, ret); return ret; }
/* ------------------------------------------------------------------------*//** * @FUNCTION mod44xx_get_clock_activity_mode * @BRIEF retrieve omap module's clockactivity mode * @RETURNS 1 if success * 0 if omap module's registers NOT accessible * OMAPCONF_ERR_ARG * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_CPU * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_INTERNAL * @param[in] module_id: omap module ID * @param[in,out] mode: returned omap module's clockactivity mode * @DESCRIPTION retrieve omap module's clockactivity mode *//*------------------------------------------------------------------------ */ int mod44xx_get_clock_activity_mode(mod44xx_id module_id, mod_clock_activity_mode *mode) { int ret_val = 0; unsigned int sysconfig; char name[MOD44XX_MAX_NAME_LENGTH]; *mode = MOD_CLOCK_ACTIVITY_MODE_MAX; if (!cpu_is_omap44xx()) return OMAPCONF_ERR_CPU; if (module_id >= OMAP4_MODULE_ID_MAX) return OMAPCONF_ERR_ARG; if (mod44xx_has_clockactivity_bit(module_id) != 1) return OMAPCONF_ERR_NOT_AVAILABLE; ret_val = mod44xx_is_accessible(module_id); if (ret_val == 1) { /* Module is accessible */ dprintf("%s(): module #%d name = %s is accessible\n", __func__, module_id, mod44xx_get_name(module_id, name)); if (mod44xx_info_table[module_id].sysconfig_addr != NULL) { OMAP_READREG((unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); dprintf( "%s(): SYSCONFIG ADDR = 0x%08X SYSCONFIG = 0x%08X\n", __func__, (unsigned int) mod44xx_info_table[module_id].sysconfig_addr, sysconfig); /* Check module's idle mode */ switch (module_id) { case OMAP4_SPINLOCK: case OMAP4_ELM: *mode = (mod_clock_activity_mode) extract_bit(sysconfig, 8); ret_val = 1; dprintf( "%s(): module %s clockactivity bit 8 = %d\n", __func__, mod44xx_get_name(module_id, name), *mode); break; default: *mode = (mod_clock_activity_mode) extract_bitfield(sysconfig, 8, 2); ret_val = 1; dprintf( "%s(): module %s clockactivity (bits [9:8]) = %d\n", __func__, mod44xx_get_name(module_id, name), *mode); } } else { fprintf(stderr, "%s(): error module's %s interface type is not NONE but SYSCONFIG ADDR == NULL\n", __func__, mod44xx_get_name(module_id, name)); ret_val = OMAPCONF_ERR_INTERNAL; } } else if (ret_val == 0) { /* Module is NOT accessible */ ret_val = 0; dprintf("%s(): module is NOT accessible\n", __func__); } else { /* internal error */ dprintf("%s(): mod44xx_is_accessible() returned with %d\n", __func__, ret_val); } return ret_val; }
/* ------------------------------------------------------------------------*//** * @FUNCTION help * @BRIEF display omapconf help * @RETURNS none * @param[in] cat: help category to display * @DESCRIPTION display omapconf help *//*------------------------------------------------------------------------ */ void help(help_category cat) { if (cat >= HELP_CATEGORY_MAX) { fprintf(stderr, "help called with incorrect category!!! (%d)\n", cat); return; } if ((cat == HELP_ALL) || (cat == HELP_USAGE)) { printf("\nNAME\n"); printf("\tomapconf - TI OMAP Configuration Diagnostic Tool\n"); printf("\nSYNOPSIS\n"); printf("\tomapconf [--version] [--help] [--cpuinfo] " "[--buildinfo] [--import <file>] [--force <cpu>] " "[--norw] <command> [<args>]\n"); if (cat == HELP_USAGE) printf("\n\tSee 'omapconf --help' for more " "information.\n\n"); } if (cat == HELP_ALL) { printf("\nDESCRIPTION\n"); printf("\tomaconf is standalone application designed to provide" " a quick'n easy way to diagnose/monitor/debug/audit " "TI OMAP processors configuration at runtime, with no " "particular kernel dependency.\n"); printf("\tomapconf is designed to be as much platform-agnostic " "as possible, being able to run on any Linux platform (" "Ubuntu, Android, ...) and easily ported to " "other OS.\n"); printf("\tEven if omapconf today focuses mainly on " "power management and performances diagnostic, it is " "intended to be extended to any other area.\n"); printf("\nOPTIONS\n"); printf("\t--help\n"); printf("\t Print omapconf help.\n"); printf("\n\t--version\n"); printf("\t Print omapconf version.\n"); printf("\n\t--cpuinfo\n"); printf( "\t Print CPU details (revision, type, DIE ID, ...).\n"); printf("\n\t--buildinfo\n"); printf("\t Print SW Build Details (kernel, release).\n"); printf("\n\t--import <file> (### OMAP5 ONLY ###)\n"); printf("\t Import OMAP registers content from XML <file> " "(generated with command \"export <file>\").\n"); printf("\t Must be used in conjunction with option " "\"--force\".\n"); printf("\n\t--norw\n"); printf("\t Fake memory access (no real R/W done): write " "accesses are discarded, read accesses return physical " "address.\n"); printf("\n\t--trace_read\n"); printf( "\t Enable console tracing of all omapconf memory read access.\n"); printf("\n\t--trace_write\n"); printf( "\t Enable console tracing of all omapconf memory write access.\n"); } if ((cat == HELP_ALL) || (cat == HELP_FORCEDETECT)) { printf("\n\t--force <cpu>\n"); printf("\t Force CPU detection.\n"); printf( "\t Supported supported <cpu>: " "omap4430, omap4460, omap4470, " "omap5430es1, omap5432es1, omap5430, omap5432, " "dra75x, dra72x" "\n"); } if ((cat != HELP_USAGE) && (cat != HELP_FORCEDETECT)) printf("\nCOMMANDS\n"); if ((cat == HELP_ALL) || (cat == HELP_RW)) { printf("\n\t### WARNING ###: use the following [read | write | " "set bit | clear bit | dump] commands at your own " "risk!\n"); printf("\tNo address check done, may generate:\n"); printf("\t - bus error (invalid or not accessible " "<physical address>,\n"); printf("\t - platform crash/hang (bad <value>).\n"); printf("\n\tomapconf read [0x<physical address> | <name>]\n"); printf("\t Read any OMAP memory address (register), given " "its <physical address> or <name> as listed in TRM.\n"); printf("\t e.g: omapconf read 0x4A306300, omapconf read " "PM_MPU_PWRSTCTRL\n"); printf("\n\tomapconf write [0x<physical address> | <name>] " "0x<value>\n"); printf("\t Write <value> at any OMAP memory address " "(register), given its <physical address> or <name> as " "listed in TRM.\n"); printf("\t e.g: omapconf write 0x4A306300 0xDEADBEEF, " "omapconf write PM_MPU_PWRSTCTRL 0xDEADBEEF\n"); printf("\n\tomapconf set bit [0x<physical address> | <name>] " "<position>" "\n"); printf("\t Set bit at <position> into any OMAP memory " "address (register), given its <physical address> " "or <name> as listed in TRM.\n"); printf("\t e.g: omapconf set bit 0x4A306300 1, " "omapconf set bit PM_MPU_PWRSTCTRL 1\n"); printf("\n\tomapconf clear bit [0x<physical address> | <name>] " "<position>\n"); printf("\t Clear bit at <position> into any OMAP memory " "address (register), given its <physical address> " "or <name> as listed in TRM.\n"); printf("\t e.g: omapconf clear bit 0x4A306300 1, " "omapconf clear bit PM_MPU_PWRSTCTRL 1\n"); printf("\n\tomapconf dump 0x<start address> 0x<end address>\n"); printf("\t Dump a range of OMAP memory addresses, from " "<start address> to <end address>.\n"); printf("\t Note all addresses within given range must be " "valid and accessible.\n"); printf("\t e.g: omapconf dump 0x48243400 0x4824340C\n"); } if ((cat == HELP_ALL) || (cat == HELP_RW) || (cat == HELP_I2C_RW)) { printf("\n\t### WARNING ###: use the following I2C " "[read | write] commands at your own risk!\n"); printf("\tNo address check done, may generate:\n"); printf("\t - I2C bus error (invalid or not accessible " "<physical address>,\n"); printf("\t - platform crash/hang (bad <value>).\n"); printf("\n\tomapconf read i2c <bus> 0x<chip-addr> 0x<addr>\n"); printf("\t Read I2C register at address <addr> from I2C chip" " at <chip-addr> on I2C <bus>.\n"); printf("\t e.g: omapconf i2c read 1 0x49 0x02\n"); printf("\n\tomapconf write i2c <bus> 0x<chip-addr> 0x<addr> " "0x<value>\n"); printf("\t Write <value> in I2C register at address <addr> " "from I2C chip at <chip-addr> on I2C <bus>.\n"); printf("\t e.g: omapconf i2c write 1 0x49 0x02 0xAA\n"); } if ((cat == HELP_RW) || (cat == HELP_I2C_RW) || (cat == HELP_FORCEDETECT)) goto help_end; /* OMAP4-specific commands */ if (cpu_is_omap44xx()) help44xx(cat, "all"); /* OMAP5-specific commands */ if (cpu_is_omap54xx()) help54xx(cat, "None"); /* DRA7-specific commands */ if (cpu_is_dra7xx()) help_dra7xx(cat, "None"); if (cat == HELP_ALL) { printf("\nREPORTING BUGS\n"); printf("\tReport bugs to <*****@*****.**> " "mailing-list.\n"); printf("\tYou do not have to be subsribed to the list to send " "a message there.\n"); printf("\nSUGGESTIONS\n"); printf("\tSuggest any new idea to " "<*****@*****.**> mailing-list.\n"); printf("\tYou do not have to be subsribed to the list to send " "a message there.\n"); printf("\nCONTRIBUTIONS\n"); printf("\tSend patch to <*****@*****.**> " "mailing-list.\n"); printf("\tYou do not have to be subsribed to the list to send " "a message there.\n"); printf("\nNOTIFICATIONS\n"); printf("\tSubscribe to <*****@*****.**> " "mailing-list for automatic update notification.\n"); printf("\tYou do not have to be subsribed to the list to send " "a message there.\n"); printf("\nFURTHER DOCUMENTATION\n"); printf("\tVisit omapconf wiki:\n"); printf("\t\t<https://github.com/omapconf/omapconf/wiki>\n"); printf("\n"); } help_end: return; }
static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n) { unsigned long value; static unsigned long prev_mpu_freq = 0; if (sscanf(buf, "%lu", &value) != 1) return -EINVAL; if (attr == &tick_control_attr) { if (value == 1) tick_nohz_disable(1); else if (value == 0) tick_nohz_disable(0); } /* Check locks */ if (attr == &vdd1_lock_attr) { if (vdd1_locked) { /* vdd1 currently locked */ if (value == 0) { omap_pm_cpu_set_freq(prev_mpu_freq * 1000); vdd1_locked = 0; return n; } else { printk(KERN_ERR "%s: vdd1 already locked to %d\n", __func__, vdd1_locked); return -EINVAL; } } else { /* vdd1 currently unlocked */ if (value != 0) { u8 i = 0; unsigned long freq = 0; struct cpufreq_frequency_table *freq_table = *omap_pm_cpu_get_freq_table(); if (freq_table == NULL) { printk(KERN_ERR "%s: Could not get freq_table\n", __func__); return -ENODEV; } for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { if (freq_table[i].index == value - 1) { freq = freq_table[i].frequency; break; } } if (freq_table[i].frequency == CPUFREQ_TABLE_END) { printk(KERN_ERR "%s: Invalid value [0..%d]\n", __func__, i-1); return -EINVAL; } prev_mpu_freq = omap_pm_cpu_get_freq(); omap_pm_cpu_set_freq(freq * 1000); vdd1_locked = value; } else { printk(KERN_ERR "%s: vdd1 already unlocked\n", __func__); return -EINVAL; } } } else if (attr == &vdd2_lock_attr) { if (vdd2_locked) { /* vdd2 currently locked */ if (value == 0) { int tmp_lock = vdd2_locked; vdd2_locked = 0; if (omap_pm_set_min_bus_tput(&sysfs_cpufreq_dev, OCP_INITIATOR_AGENT, -1)) { printk(KERN_ERR "%s: Failed to remove vdd2_lock\n", __func__); vdd2_locked = tmp_lock; /* restore previous lock */ } else { return n; } } else { printk(KERN_ERR "%s: vdd2 already locked to %d\n", __func__, vdd2_locked); return -EINVAL; } } else { /* vdd2 currently unlocked */ if (value != 0) { unsigned long freq = 0; if (cpu_is_omap3630()) { if(value == 1) { freq = 100*1000*4; } else if (value == 2) { freq = 200*1000*4; } else { printk(KERN_ERR "%s: Invalid value [1,2]\n", __func__); return -EINVAL; } } else if (cpu_is_omap44xx()) { if (omap_rev() <= OMAP4430_REV_ES2_0) { if(value == 1) { freq = 100*1000*4; } else if (value == 2) { freq = 200*1000*4; } else { printk(KERN_ERR "%s: Invalid value [1,2]\n", __func__); return -EINVAL; } } else { if(value == 1) { freq = 98304*4; } else if (value == 2) { freq = 100*1000*4; } else if (value == 3) { freq = 200*1000*4; } else { printk(KERN_ERR "%s: Invalid value [1,2,3]\n", __func__); return -EINVAL; } } } else { printk(KERN_ERR "%s: Unsupported HW [OMAP3630, OMAP44XX]\n", __func__); return -ENODEV; } if (omap_pm_set_min_bus_tput(&sysfs_cpufreq_dev, OCP_INITIATOR_AGENT, freq)) { printk(KERN_ERR "%s: Failed to add vdd2_lock\n", __func__); } else { vdd2_locked = value; } return n; } else { printk(KERN_ERR "%s: vdd2 already unlocked\n", __func__); return -EINVAL; } } } else if (attr == &dsp_freq_attr) { u8 i, opp_id = 0; struct omap_opp *opp_table = omap_pm_dsp_get_opp_table(); if (opp_table == NULL) { printk(KERN_ERR "%s: Could not get dsp opp_table\n", __func__); return -ENODEV; } for (i = 1; opp_table[i].rate; i++) { if (opp_table[i].rate >= value) { opp_id = i; break; } } if (opp_id == 0) { printk(KERN_ERR "%s: Invalid value\n", __func__); return -EINVAL; } omap_pm_dsp_set_min_opp(opp_id); } else if (attr == &vdd1_opp_attr) { printk(KERN_ERR "%s: changing vdd1_opp is not supported\n", __func__); return -EINVAL; } else if (attr == &vdd2_opp_attr) { printk(KERN_ERR "%s: changing vdd2_opp is not supported\n", __func__); return -EINVAL; } else { return -EINVAL; } return n; }
void __init usb_musb_init(struct omap_musb_board_data *board_data) { if (cpu_is_omap44xx()) omap4430_phy_init(NULL); }
void dss_init_overlays(struct platform_device *pdev) { int i, r; INIT_LIST_HEAD(&overlay_list); num_overlays = 0; for (i = 0; i < MAX_DSS_OVERLAYS; ++i) { struct omap_overlay *ovl; ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); BUG_ON(ovl == NULL); mutex_init(&ovl->lock); mutex_lock(&ovl->lock); switch (i) { case 0: ovl->name = "gfx"; ovl->id = OMAP_DSS_GFX; ovl->supported_modes = (cpu_is_omap44xx() | cpu_is_omap34xx()) ? OMAP_DSS_COLOR_GFX_OMAP3 : OMAP_DSS_COLOR_GFX_OMAP2; ovl->caps = OMAP_DSS_OVL_CAP_DISPC; ovl->info.global_alpha = 255; ovl->info.zorder = OMAP_DSS_OVL_ZORDER_3; break; case 1: ovl->name = "vid1"; ovl->id = OMAP_DSS_VIDEO1; ovl->supported_modes = (cpu_is_omap44xx() | cpu_is_omap34xx()) ? OMAP_DSS_COLOR_VID1_OMAP3 : OMAP_DSS_COLOR_VID_OMAP2; ovl->caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_DISPC; ovl->info.yuv2rgb_conv.type = OMAP_DSS_COLOR_CONV_BT601_5_LR; ovl->info.yuv2rgb_conv.dirty = true; ovl->info.global_alpha = 255; ovl->info.zorder = OMAP_DSS_OVL_ZORDER_2; break; case 2: ovl->name = "vid2"; ovl->id = OMAP_DSS_VIDEO2; ovl->supported_modes = (cpu_is_omap44xx() | cpu_is_omap34xx()) ? OMAP_DSS_COLOR_VID2_OMAP3 : OMAP_DSS_COLOR_VID_OMAP2; ovl->caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_DISPC; ovl->info.yuv2rgb_conv.type = OMAP_DSS_COLOR_CONV_BT601_5_LR; ovl->info.yuv2rgb_conv.dirty = true; ovl->info.global_alpha = 255; ovl->info.zorder = OMAP_DSS_OVL_ZORDER_1; break; case 3: ovl->name = "vid3"; ovl->id = OMAP_DSS_VIDEO3; ovl->supported_modes = OMAP_DSS_COLOR_VID3_OMAP3; ovl->caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_DISPC; ovl->info.yuv2rgb_conv.type = OMAP_DSS_COLOR_CONV_BT601_5_LR; ovl->info.yuv2rgb_conv.dirty = true; ovl->info.global_alpha = 255; ovl->info.zorder = OMAP_DSS_OVL_ZORDER_0; } ovl->info.min_x_decim = ovl->info.min_y_decim = 1; ovl->info.max_x_decim = ovl->info.max_y_decim = cpu_is_omap44xx() ? 16 : 1; ovl->info_dirty = true; ovl->set_manager = &omap_dss_set_manager; ovl->unset_manager = &omap_dss_unset_manager; ovl->set_overlay_info = &dss_ovl_set_overlay_info; ovl->get_overlay_info = &dss_ovl_get_overlay_info; ovl->wait_for_go = &dss_ovl_wait_for_go; omap_dss_add_overlay(ovl); dispc_overlays[i] = ovl; r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, &pdev->dev.kobj, "overlay%d", i); if (r) DSSERR("failed to create sysfs file\n"); mutex_unlock(&ovl->lock); } #ifdef L4_EXAMPLE { struct omap_overlay *ovl; ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); BUG_ON(ovl == NULL); ovl->name = "l4"; ovl->supported_modes = OMAP_DSS_COLOR_RGB24U; ovl->set_manager = &omap_dss_set_manager; ovl->unset_manager = &omap_dss_unset_manager; ovl->set_overlay_info = &dss_ovl_set_overlay_info; ovl->get_overlay_info = &dss_ovl_get_overlay_info; omap_dss_add_overlay(ovl); r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, &pdev->dev.kobj, "overlayl4"); if (r) DSSERR("failed to create sysfs file\n"); l4_overlays[0] = ovl; } #endif }
static int omap_i2c_init(struct omap_i2c_dev *dev) { u16 psc = 0, scll = 0, sclh = 0, buf = 0; u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; unsigned long fclk_rate = 12000000; unsigned long timeout; unsigned long internal_clk = 0; struct clk *fclk; if (dev->rev >= OMAP_I2C_REV_2) { /* Disable I2C controller before soft reset */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & ~(OMAP_I2C_CON_EN)); omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); /* For some reason we need to set the EN bit before the * reset done bit gets set. */ timeout = jiffies + OMAP_I2C_TIMEOUT; omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & SYSS_RESETDONE_MASK)) { if (time_after(jiffies, timeout)) { dev_warn(dev->dev, "timeout waiting " "for controller reset\n"); return -ETIMEDOUT; } msleep(1); } /* SYSC register is cleared by the reset; rewrite it */ if (dev->rev == OMAP_I2C_REV_ON_2430) { omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_AUTOIDLE_MASK); } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { dev->syscstate = SYSC_AUTOIDLE_MASK; dev->syscstate |= SYSC_ENAWAKEUP_MASK; dev->syscstate |= (SYSC_IDLEMODE_SMART << __ffs(SYSC_SIDLEMODE_MASK)); dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK << __ffs(SYSC_CLOCKACTIVITY_MASK)); omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate); /* * Enabling all wakup sources to stop I2C freezing on * WFI instruction. * REVISIT: Some wkup sources might not be needed. */ dev->westate = OMAP_I2C_WE_ALL; omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); } } omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); if (cpu_class_is_omap1()) { /* * The I2C functional clock is the armxor_ck, so there's * no need to get "armxor_ck" separately. Now, if OMAP2420 * always returns 12MHz for the functional clock, we can * do this bit unconditionally. */ fclk = clk_get(dev->dev, "fck"); fclk_rate = clk_get_rate(fclk); clk_put(fclk); /* TRM for 5912 says the I2C clock must be prescaled to be * between 7 - 12 MHz. The XOR input clock is typically * 12, 13 or 19.2 MHz. So we should have code that produces: * * XOR MHz Divider Prescaler * 12 1 0 * 13 2 1 * 19.2 2 1 */ if (fclk_rate > 12000000) psc = fclk_rate / 12000000; } if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { /* * HSI2C controller internal clk rate should be 19.2 Mhz for * HS and for all modes on 2430. On 34xx we can use lower rate * to get longer filter period for better noise suppression. * The filter is iclk (fclk for HS) period. */ if (dev->speed > 400 || cpu_is_omap2430()) internal_clk = 19200; else if (dev->speed > 100) internal_clk = 9600; else internal_clk = 4000; fclk = clk_get(dev->dev, "fck"); fclk_rate = clk_get_rate(fclk) / 1000; clk_put(fclk); /* Compute prescaler divisor */ psc = fclk_rate / internal_clk; psc = psc - 1; /* If configured for High Speed */ if (dev->speed > 400) { unsigned long scl; /* For first phase of HS mode */ scl = internal_clk / 400; fsscll = scl - (scl / 3) - 7; fssclh = (scl / 3) - 5; /* For second phase of HS mode */ scl = fclk_rate / dev->speed; hsscll = scl - (scl / 3) - 7; hssclh = (scl / 3) - 5; } else if (dev->speed > 100) { unsigned long scl; /* Fast mode */ scl = internal_clk / dev->speed; fsscll = scl - (scl / 3) - 7; fssclh = (scl / 3) - 5; } else { /* Standard mode */ fsscll = internal_clk / (dev->speed * 2) - 7; fssclh = internal_clk / (dev->speed * 2) - 5; } scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; } else { /* Program desired operating rate */ fclk_rate /= (psc + 1) * 1000; if (psc > 2) psc = 2; scll = fclk_rate / (dev->speed * 2) - 7 + psc; sclh = fclk_rate / (dev->speed * 2) - 7 + psc; } /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); /* SCL low and high time values */ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); if (dev->fifo_size) { /* Note: setup required fifo size - 1. RTRSH and XTRSH */ buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR | (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR; omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); } /* Take the I2C module out of reset: */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); dev->errata = 0; if (cpu_is_omap2430() || cpu_is_omap34xx()) dev->errata |= I2C_OMAP_ERRATA_I207; if (cpu_is_omap34xx() || cpu_is_omap44xx()) { dev->pscstate = psc; dev->scllstate = scll; dev->sclhstate = sclh; dev->bufstate = buf; } return 0; }
static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, struct omap_mmc_platform_data *mmc) { char *hc_name; hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL); if (!hc_name) { pr_err("Cannot allocate memory for controller slot name\n"); kfree(hc_name); return -ENOMEM; } if (c->name) strncpy(hc_name, c->name, HSMMC_NAME_LEN); else snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i", c->mmc, 1); mmc->slots[0].name = hc_name; mmc->nr_slots = 1; mmc->slots[0].caps = c->caps; mmc->slots[0].pm_caps = c->pm_caps; mmc->slots[0].internal_clock = !c->ext_clock; mmc->dma_mask = 0xffffffff; mmc->max_freq = c->max_freq; if (cpu_is_omap44xx()) mmc->reg_offset = OMAP4_MMC_REG_OFFSET; else mmc->reg_offset = 0; mmc->get_context_loss_count = hsmmc_get_context_loss; mmc->slots[0].switch_pin = c->gpio_cd; mmc->slots[0].gpio_wp = c->gpio_wp; mmc->slots[0].remux = c->remux; mmc->slots[0].init_card = c->init_card; if (c->cover_only) mmc->slots[0].cover = 1; if (c->nonremovable) mmc->slots[0].nonremovable = 1; if (c->power_saving) mmc->slots[0].power_saving = 1; if (c->no_off) mmc->slots[0].no_off = 1; if (c->no_off_init) mmc->slots[0].no_regulator_off_init = c->no_off_init; if (c->vcc_aux_disable_is_sleep) mmc->slots[0].vcc_aux_disable_is_sleep = 1; /* * NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another * controllable regulator, or a fixed supply. * * temporary HACK: ocr_mask instead of fixed supply */ if (cpu_is_omap3505() || cpu_is_omap3517()) mmc->slots[0].ocr_mask = MMC_VDD_165_195 | MMC_VDD_26_27 | MMC_VDD_27_28 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32; else mmc->slots[0].ocr_mask = c->ocr_mask; if (!cpu_is_omap3517() && !cpu_is_omap3505()) mmc->slots[0].features |= HSMMC_HAS_PBIAS; if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0)) mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET; switch (c->mmc) { case 1: if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { /* on-chip level shifting via PBIAS0/PBIAS1 */ if (cpu_is_omap44xx()) { mmc->slots[0].before_set_reg = omap4_hsmmc1_before_set_reg; mmc->slots[0].after_set_reg = omap4_hsmmc1_after_set_reg; } else { mmc->slots[0].before_set_reg = omap_hsmmc1_before_set_reg; mmc->slots[0].after_set_reg = omap_hsmmc1_after_set_reg; } } if (cpu_is_omap3517() || cpu_is_omap3505()) mmc->slots[0].set_power = nop_mmc_set_power; /* OMAP3630 HSMMC1 supports only 4-bit */ if (cpu_is_omap3630() && (c->caps & MMC_CAP_8_BIT_DATA)) { c->caps &= ~MMC_CAP_8_BIT_DATA; c->caps |= MMC_CAP_4_BIT_DATA; mmc->slots[0].caps = c->caps; } break; case 2: if (cpu_is_omap3517() || cpu_is_omap3505()) mmc->slots[0].set_power = am35x_hsmmc2_set_power; if (c->ext_clock) c->transceiver = 1; if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) { c->caps &= ~MMC_CAP_8_BIT_DATA; c->caps |= MMC_CAP_4_BIT_DATA; } if (mmc->slots[0].features & HSMMC_HAS_PBIAS) { /* off-chip level shifting, or none */ mmc->slots[0].before_set_reg = hsmmc2_before_set_reg; mmc->slots[0].after_set_reg = NULL; } break; case 3: case 4: case 5: mmc->slots[0].before_set_reg = NULL; mmc->slots[0].after_set_reg = NULL; break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); kfree(hc_name); return -ENODEV; } return 0; }
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) { int r; if (cpu_is_omap44xx() && dssdev->channel != OMAP_DSS_CHANNEL_LCD2) { /* Only LCD2 channel is connected to DPI on OMAP4 */ return -EINVAL; } r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); return r; } if (cpu_is_omap34xx() && !cpu_is_omap3630()) { r = regulator_enable(dpi.vdds_dsi_reg); if (r) goto err0; } /* turn on clock(s) */ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; if (!cpu_is_omap44xx()) dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); dss_mainclk_state_enable(); dpi_basic_init(dssdev); #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL r = dsi_pll_init(dssdev, 0, 1); if (r) goto err1; #endif /* CONFIG_OMAP2_DSS_USE_DSI_PLL */ r = dpi_set_mode(dssdev); if (r) goto err2; mdelay(2); if (dssdev->manager) { if (cpu_is_omap44xx()) dpi_start_auto_update(dssdev); dssdev->manager->enable(dssdev->manager); } return 0; err2: #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dsi_pll_uninit(dssdev->channel == OMAP_DSS_CHANNEL_LCD ? DSI1 : DSI2); err1: #endif dssdev->state = OMAP_DSS_DISPLAY_DISABLED; if (!cpu_is_omap44xx()) dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); dss_mainclk_state_disable(true); if (cpu_is_omap34xx() && !cpu_is_omap3630()) regulator_disable(dpi.vdds_dsi_reg); err0: omap_dss_stop_device(dssdev); return r; }
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai) { struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; struct omap_pcm_dma_data *dma_data; int dma, bus_id = mcbsp_data->bus_id; int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; int pkt_size = 0; unsigned long port; unsigned int format, div, framesize, master; dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream]; if (cpu_class_is_omap1()) { dma = omap1_dma_reqs[bus_id][substream->stream]; port = omap1_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap2420()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap2420_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap2430()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap2430_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap34xx()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; } else if (cpu_is_omap44xx()) { dma = omap44xx_dma_reqs[bus_id][substream->stream]; port = omap44xx_mcbsp_port[bus_id][substream->stream]; } else { return -ENODEV; } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; wlen = 16; break; case SNDRV_PCM_FORMAT_S32_LE: dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; wlen = 32; break; default: return -EINVAL; } if (cpu_is_omap34xx()) { dma_data->set_threshold = omap_mcbsp_set_threshold; /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ if (omap_mcbsp_get_dma_op_mode(bus_id) == MCBSP_DMA_MODE_THRESHOLD) { int period_words, max_thrsh; period_words = params_period_bytes(params) / (wlen / 8); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) max_thrsh = omap_mcbsp_get_max_tx_threshold( mcbsp_data->bus_id); else{ max_thrsh = omap_mcbsp_get_max_rx_threshold( mcbsp_data->bus_id); max_thrsh=1; } /* * If the period contains less or equal number of words, * we are using the original threshold mode setup: * McBSP threshold = sDMA frame size = period_size * Otherwise we switch to sDMA packet mode: * McBSP threshold = sDMA packet size * sDMA frame size = period size */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ if (period_words > max_thrsh) { int divider = 0; /* * Look for the biggest threshold value, which * divides the period size evenly. */ divider = period_words / max_thrsh; if (period_words % max_thrsh) divider++; while (period_words % divider && divider < period_words) divider++; if (divider == period_words) return -EINVAL; pkt_size = period_words / divider; sync_mode = OMAP_DMA_SYNC_PACKET; } else { sync_mode = OMAP_DMA_SYNC_FRAME; } } else { printk("DMA Element Sync Mode for recording \n"); sync_mode=OMAP_DMA_SYNC_ELEMENT; } } } dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback"; dma_data->dma_req = dma; dma_data->port_addr = port; dma_data->sync_mode = sync_mode; dma_data->packet_size = pkt_size; snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); if (mcbsp_data->configured) { /* McBSP already configured by another stream */ return 0; } format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; wpf = channels = params_channels(params); if (channels == 2 && (format == SND_SOC_DAIFMT_I2S || format == SND_SOC_DAIFMT_LEFT_J)) { /* Use dual-phase frames */ regs->rcr2 |= RPHASE; regs->xcr2 |= XPHASE; /* Set 1 word per (McBSP) frame for phase1 and phase2 */ wpf--; regs->rcr2 |= RFRLEN2(wpf - 1); regs->xcr2 |= XFRLEN2(wpf - 1); } regs->rcr1 |= RFRLEN1(wpf - 1); regs->xcr1 |= XFRLEN1(wpf - 1); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: /* Set word lengths */ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); break; case SNDRV_PCM_FORMAT_S32_LE: /* Set word lengths */ regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32); regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32); regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32); regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32); break; default: /* Unsupported PCM format */ return -EINVAL; } /* In McBSP master modes, FRAME (i.e. sample rate) is generated * by _counting_ BCLKs. Calculate frame size in BCLKs */ master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK; if (master == SND_SOC_DAIFMT_CBS_CFS) { div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1; framesize = (mcbsp_data->in_freq / div) / params_rate(params); if (framesize < wlen * channels) { printk(KERN_ERR "%s: not enough bandwidth for desired rate and " "channels\n", __func__); return -EINVAL; } } else framesize = wlen * channels; /* Set FS period and length in terms of bit clock periods */ switch (format) { case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_LEFT_J: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID((framesize >> 1) - 1); break; case SND_SOC_DAIFMT_DSP_A: case SND_SOC_DAIFMT_DSP_B: regs->srgr2 |= FPER(framesize - 1); regs->srgr1 |= FWID(0); break; } omap_mcbsp_config(bus_id, &mcbsp_data->regs); mcbsp_data->wlen = wlen; mcbsp_data->configured = 1; return 0; }
int dss_init(struct platform_device *pdev) { int r = 0, dss_irq; u32 rev; struct resource *dss_mem; #if defined(CONFIG_MACH_LGE_OMAP3) // LGE_UPDATE /* to prevent LG logo blinking, it doesn't need to execute below section.*/ bool skip_init = true; // LGE_UPDATE /* to prevent LG logo blinking, it doesn't need to execute below section.*/ #else bool skip_init = false; #endif dss.pdata = pdev->dev.platform_data; dss.pdev = pdev; if (cpu_is_omap44xx()) dss_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); else dss_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!dss_mem) { WARN_ON(1); r = -ENODEV; goto fail0; } dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); if (!dss.base) { DSSERR("can't ioremap DSS\n"); r = -ENOMEM; goto fail0; } dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M | DSS_CLK_96M); dss_mainclk_enable(); #if defined(CONFIG_MACH_LGE_OMAP3) #else #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT /* DISPC_CONTROL */ if (omap_readl(0x48050440) & 1) /* LCD enabled? */ skip_init = true; #endif #endif if (!skip_init) { /* disable LCD and DIGIT output. This seems to fix the synclost * problem that we get, if the bootloader starts the DSS and * the kernel resets it */ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); /* We need to wait here a bit, otherwise we sometimes start to * get synclost errors, and after that only power cycle will * restore DSS functionality. I have no idea why this happens. * And we have to wait _before_ resetting the DSS, but after * enabling clocks. */ msleep(50); } /* autoidle */ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); /* Select DPLL */ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); #ifdef CONFIG_OMAP2_DSS_VENC REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif if (!cpu_is_omap44xx()) r = request_irq(INT_24XX_DSS_IRQ, cpu_is_omap24xx() ? dss_irq_handler_omap2 : dss_irq_handler_omap3, 0, "OMAP DSS", NULL); else { dss_irq = platform_get_irq(pdev, 0); r = request_irq(dss_irq, dss_irq_handler_omap2, 0, "OMAP DSS", NULL); } if (r < 0) { DSSERR("omap2 dss: request_irq failed\n"); goto fail1; } if (cpu_is_omap34xx()) { dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); if (IS_ERR(dss.dpll4_m4_ck)) { DSSERR("Failed to get dpll4_m4_ck\n"); r = PTR_ERR(dss.dpll4_m4_ck); goto fail2; } } dss.dsi1_clk_source = DSS_SRC_DSS1_ALWON_FCLK; dss.dsi2_clk_source = DSS_SRC_DSS1_ALWON_FCLK; dss.lcd1_clk_source = DSS_SRC_DSS1_ALWON_FCLK; dss.lcd2_clk_source = DSS_SRC_DSS1_ALWON_FCLK; dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK; dss_save_context(); rev = dss_read_reg(DSS_REVISION); printk(KERN_INFO "OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M | DSS_CLK_96M); return 0; fail2: if (!cpu_is_omap44xx()) free_irq(INT_24XX_DSS_IRQ, NULL); fail1: iounmap(dss.base); fail0: return r; }
/* ------------------------------------------------------------------------*//** * @FUNCTION powerdm_config_show * @BRIEF decode and display power domain configuration * @RETURNS 0 in case of success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_ARG * OMAPCONF_ERR_NOT_AVAILABLE * @param[in,out] stream: output file * @param[in] powerdm: power domain name * @DESCRIPTION decode and display power domain configuration *//*------------------------------------------------------------------------ */ int powerdm_config_show(FILE *stream, const char *powerdm) { int ret; powerdm_info data; pwrdm_state st_last, st_curr, st_tgt; reg *pm_pwrstctrl; reg *pm_pwrstst; char s[64]; char s1[32], s2[32]; CHECK_NULL_ARG(stream, OMAPCONF_ERR_ARG); CHECK_NULL_ARG(powerdm, OMAPCONF_ERR_ARG); ret = _powerdm_info_get(powerdm, &data); if (ret != 0) { dprintf("%s(%s): could not retrieve powerdm_info struct!\n", __func__, powerdm); return OMAPCONF_ERR_NOT_AVAILABLE; } fprintf(stream, "|----------------------------------------------------------------|\n"); strcpy(s, powerdm); strcat(s, " Power Domain Configuration"); fprintf(stream, "| %-62s |\n", s); fprintf(stream, "|----------------------------------------------------------------|\n"); fprintf(stream, "| %-32s | %-7s | %-7s | %-7s |\n", "Power State", "Current", "Target", "Last"); fprintf(stream, "|----------------------------------|---------|---------|---------|\n"); st_last = powerdm_state_get(powerdm, PWRDM_STATE_PREVIOUS); st_curr = powerdm_state_get(powerdm, PWRDM_STATE_CURRENT); st_tgt = powerdm_state_get(powerdm, PWRDM_STATE_TARGET); fprintf(stream, "| %-32s | %-7s | %-7s | %-7s |\n", "Domain", pwrdm_state_name_get(st_curr), pwrdm_state_name_get(st_tgt), pwrdm_state_name_get(st_last)); if ((!powerdm_has_logic_ret_state_ctrl_bit(powerdm)) && (data.pwrstst == NULL)) goto powerdm_config_show_mem; st_tgt = powerdm_target_logic_ret_state_get(powerdm); if (st_tgt != PWRDM_STATE_MAX) strcpy(s1, pwrdm_state_name_get(st_tgt)); else strcpy(s1, ""); st_curr = powerdm_logic_state_get(powerdm); if (st_curr != PWRDM_STATE_MAX) strcpy(s2, pwrdm_state_name_get(st_curr)); else strcpy(s2, ""); fprintf(stream, "| %-32s | %-7s | %-7s | |\n", "Logic", s2, s1); powerdm_config_show_mem: if (cpu_is_omap44xx()) { pm_pwrstctrl = powerdm_pwrstctrl_reg_get(powerdm); pm_pwrstst = powerdm_pwrstst_reg_get(powerdm); ret = pwrdm44xx_config_show(stream, powerdm, reg_addr_get(pm_pwrstctrl), reg_read(pm_pwrstctrl), reg_addr_get(pm_pwrstst), reg_read(pm_pwrstst)); } else if (cpu_is_omap54xx()) { ret = pwrdm54xx_config_show(stream, data); } else { fprintf(stderr, "omapconf: %s(): cpu not supported!!!\n", __func__); ret = OMAPCONF_ERR_CPU; } if (data.pwrstst != NULL) { fprintf(stream, "|----------------------------------------------------------------|\n"); fprintf(stream, "| %-32s | %-27s |\n", "Ongoing Power Transition?", ((powerdm_in_transition(powerdm) == 1) ? "YES" : "NO")); } fprintf(stream, "|----------------------------------------------------------------|\n\n"); return ret; }
static int omap_i2c_init(struct omap_i2c_dev *dev) { u16 psc = 0, scll = 0, sclh = 0, buf = 0; u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; unsigned long fclk_rate = 12000000; unsigned long internal_clk = 0; struct clk *fclk; int ret; /* Soft reset the I2C module */ ret = omap_i2c_reset(dev); if (ret) { dev_err(dev->dev, "Unable to softreset I2C module\n"); return ret; } if (dev->rev >= OMAP_I2C_REV_ON_3430) { /* * Enabling all wakup sources to stop I2C freezing on * WFI instruction. * REVISIT: Some wkup sources might not be needed. */ dev->westate = OMAP_I2C_WE_ALL; omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); } omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); if (cpu_class_is_omap1()) { /* * The I2C functional clock is the armxor_ck, so there's * no need to get "armxor_ck" separately. Now, if OMAP2420 * always returns 12MHz for the functional clock, we can * do this bit unconditionally. */ fclk = clk_get(dev->dev, "fck"); fclk_rate = clk_get_rate(fclk); clk_put(fclk); /* TRM for 5912 says the I2C clock must be prescaled to be * between 7 - 12 MHz. The XOR input clock is typically * 12, 13 or 19.2 MHz. So we should have code that produces: * * XOR MHz Divider Prescaler * 12 1 0 * 13 2 1 * 19.2 2 1 */ if (fclk_rate > 12000000) psc = fclk_rate / 12000000; } if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { /* * HSI2C controller internal clk rate should be 19.2 Mhz for * HS and for all modes on 2430. On 34xx we can use lower rate * to get longer filter period for better noise suppression. * The filter is iclk (fclk for HS) period. */ if (dev->speed > 400 || cpu_is_omap2430()) internal_clk = 19200; else if (dev->speed > 100) internal_clk = 9600; else internal_clk = 4000; fclk = clk_get(dev->dev, "fck"); fclk_rate = clk_get_rate(fclk) / 1000; clk_put(fclk); /* Compute prescaler divisor */ psc = fclk_rate / internal_clk; psc = psc - 1; /* If configured for High Speed */ if (dev->speed > 400) { unsigned long scl; /* For first phase of HS mode */ scl = internal_clk / 400; fsscll = scl - (scl / 3) - 7; fssclh = (scl / 3) - 5; /* For second phase of HS mode */ scl = fclk_rate / dev->speed; hsscll = scl - (scl / 3) - 7; hssclh = (scl / 3) - 5; } else if (dev->speed > 100) { unsigned long scl; /* Fast mode */ scl = internal_clk / dev->speed; fsscll = scl - (scl / 3) - 7; fssclh = (scl / 3) - 5; } else { /* Standard mode */ fsscll = internal_clk / (dev->speed * 2) - 7; fssclh = internal_clk / (dev->speed * 2) - 5; } scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; } else { /* Program desired operating rate */ fclk_rate /= (psc + 1) * 1000; if (psc > 2) psc = 2; scll = fclk_rate / (dev->speed * 2) - 7 + psc; sclh = fclk_rate / (dev->speed * 2) - 7 + psc; } /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); /* SCL low and high time values */ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); if (dev->fifo_size) { /* Note: setup required fifo size - 1. RTRSH and XTRSH */ buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR | (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR; omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); } /* Take the I2C module out of reset: */ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); dev->errata = 0; if (cpu_is_omap2430() || cpu_is_omap34xx()) dev->errata |= I2C_OMAP_ERRATA_I207; if (cpu_is_omap34xx() || cpu_is_omap44xx()) { dev->pscstate = psc; dev->scllstate = scll; dev->sclhstate = sclh; dev->bufstate = buf; } return 0; }
void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { int i; char *name; for (i = 0; i < nr_controllers; i++) { unsigned long base, size; unsigned int irq = 0; if (!mmc_data[i]) continue; omap2_mmc_mux(mmc_data[i], i); switch (i) { case 0: base = OMAP2_MMC1_BASE; irq = INT_24XX_MMC_IRQ; break; case 1: base = OMAP2_MMC2_BASE; irq = INT_24XX_MMC2_IRQ; break; case 2: if (!cpu_is_omap44xx() && !cpu_is_omap34xx()) return; base = OMAP3_MMC3_BASE; irq = INT_34XX_MMC3_IRQ; break; case 3: if (!cpu_is_omap44xx()) return; base = OMAP4_MMC4_BASE; irq = OMAP44XX_IRQ_MMC4; break; case 4: if (!cpu_is_omap44xx()) return; base = OMAP4_MMC5_BASE; irq = OMAP44XX_IRQ_MMC5; break; default: continue; } if (cpu_is_omap2420()) { size = OMAP2420_MMC_SIZE; name = "mmci-omap"; } else if (cpu_is_omap44xx()) { if (i < 3) irq += OMAP44XX_IRQ_GIC_START; size = OMAP4_HSMMC_SIZE; name = "mmci-omap-hs"; } else { size = OMAP3_HSMMC_SIZE; name = "mmci-omap-hs"; } omap_mmc_add(name, i, base, size, irq, mmc_data[i]); }; }
void __init usbhs_init(const struct usbhs_omap_board_data *pdata) { struct omap_hwmod *uhh_hwm, *tll_hwm; struct platform_device *pdev; int bus_id = -1; int i; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { usbhs_data.port_mode[i] = pdata->port_mode[i]; usbtll_data.port_mode[i] = pdata->port_mode[i]; ohci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i]; ehci_data.regulator[i] = pdata->regulator[i]; } ehci_data.phy_reset = pdata->phy_reset; ehci_data.phy_clk = pdata->phy_clk; ohci_data.es2_compatibility = pdata->es2_compatibility; ehci_data.usbhs_update_sar = &usbhs_update_sar; ohci_data.usbhs_update_sar = &usbhs_update_sar; usbhs_data.ehci_data = &ehci_data; usbhs_data.ohci_data = &ohci_data; uhh_hwm = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); if (!uhh_hwm) { pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); return; } tll_hwm = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); if (!tll_hwm) { pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); return; } l3init_clkdm = clkdm_lookup("l3_init_clkdm"); if (!l3init_clkdm) { pr_err("Failed to get l3_init_clkdm\n"); } pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm, (void *)&usbtll_data, sizeof(usbtll_data), omap_uhhtll_latency, ARRAY_SIZE(omap_uhhtll_latency), false); if (IS_ERR(pdev)) { pr_err("Could not build hwmod device %s\n", USBHS_TLL_HWMODNAME); return; } pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm, (void *)&usbhs_data, sizeof(usbhs_data), omap_uhhtll_latency, ARRAY_SIZE(omap_uhhtll_latency), false); if (IS_ERR(pdev)) { pr_err("Could not build hwmod devices %s\n", USBHS_UHH_HWMODNAME); return; } pdev_usbhs = pdev; if (cpu_is_omap34xx()) { setup_ehci_io_mux(pdata->port_mode); setup_ohci_io_mux(pdata->port_mode); } else if (cpu_is_omap44xx() || cpu_is_omap54xx()) uhh_hwm->mux = setup_4430_usbhs_io_mux(pdev, pdata->port_mode); }
void __init usbhs_init(const struct usbhs_omap_board_data *pdata) { struct omap_hwmod *oh[4]; struct omap_device *od; int bus_id = -1; int i; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { usbhs_data.port_mode[i] = pdata->port_mode[i]; ohci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i]; ehci_data.regulator[i] = pdata->regulator[i]; ehci_data.transceiver_clk[i] = pdata->transceiver_clk[i]; } ehci_data.phy_reset = pdata->phy_reset; ehci_data.ehci_phy_vbus_not_used = pdata->ehci_phy_vbus_not_used; ohci_data.es2_compatibility = pdata->es2_compatibility; ohci_data.ohci_phy_suspend = pdata->ohci_phy_suspend; usbhs_data.ehci_data = &ehci_data; usbhs_data.ohci_data = &ohci_data; oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); if (!oh[0]) { pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); return; } oh[1] = omap_hwmod_lookup(USBHS_OHCI_HWMODNAME); if (!oh[1]) { pr_err("Could not look up %s\n", USBHS_OHCI_HWMODNAME); return; } oh[2] = omap_hwmod_lookup(USBHS_EHCI_HWMODNAME); if (!oh[2]) { pr_err("Could not look up %s\n", USBHS_EHCI_HWMODNAME); return; } oh[3] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); if (!oh[3]) { pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); return; } if (cpu_is_omap34xx()) { setup_ehci_io_mux(pdata->port_mode); setup_ohci_io_mux(pdata->port_mode); } else if (cpu_is_omap44xx()) { oh[2]->mux = setup_4430ehci_io_mux(pdata->port_mode); if (oh[2]->mux) omap_hwmod_mux(oh[2]->mux, _HWMOD_STATE_ENABLED); oh[1]->mux = setup_4430ohci_io_mux(pdata->port_mode); if (oh[1]->mux) omap_hwmod_mux(oh[1]->mux, _HWMOD_STATE_ENABLED); } if (cpu_is_omap44xx()) { setup_4430ehci_drvstrength(pdata->port_mode); /* TODO - implement for OHCI*/ } od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 4, (void *)&usbhs_data, sizeof(usbhs_data), omap_uhhtll_latency, ARRAY_SIZE(omap_uhhtll_latency), false); if (IS_ERR(od)) { pr_err("Could not build hwmod devices %s, %s\n", USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME); return; } usbhs_wake = kmalloc(sizeof(*usbhs_wake), GFP_KERNEL); if (!usbhs_wake) { pr_err("Could not allocate usbhs_wake\n"); return; } INIT_WORK(&usbhs_wake->wakeup_work, usbhs_resume_work); usbhs_wake->oh_ehci = oh[2]; usbhs_wake->oh_ohci = oh[1]; usbhs_wake->dev = &od->pdev.dev; }
static int __init hdcp_init(void) { HDCP_DBG("hdcp_init() %ums\n", jiffies_to_msecs(jiffies)); if (cpu_is_omap44xx()) { /* Map HDMI WP address */ hdcp.hdmi_wp_base_addr = ioremap(HDMI_WP, 0x1000); if (!hdcp.hdmi_wp_base_addr) { printk(KERN_ERR "HDCP: HDMI WP IOremap error\n"); return -EFAULT; } } else { hdcp.hdmi_wp_base_addr = NULL; } hdcp.hdcp_work = kzalloc(sizeof(struct hdcp_worker_data), GFP_KERNEL); if (!hdcp.hdcp_work) { HDCP_ERR("Could not allocate HDCP worker structure\n"); goto err_alloc_work; } hdcp.mdev = kzalloc(sizeof(struct miscdevice), GFP_KERNEL); if (!hdcp.mdev) { HDCP_ERR("Could not allocate misc device memory\n"); goto err_alloc_mdev; } /* Map DESHDCP in kernel address space */ hdcp.deshdcp_base_addr = ioremap(DSS_SS_FROM_L3__DESHDCP, 0x34); if (!hdcp.deshdcp_base_addr) { HDCP_ERR("DESHDCP IOremap error\n"); goto err_map_deshdcp; } mutex_init(&hdcp.lock); hdcp.mdev->minor = MISC_DYNAMIC_MINOR; hdcp.mdev->name = "hdcp"; hdcp.mdev->mode = 0666; hdcp.mdev->fops = &hdcp_fops; if (misc_register(hdcp.mdev)) { HDCP_ERR("Could not add character driver\n"); goto err_misc_register; } mutex_lock(&hdcp.lock); /* Variable init */ hdcp.en_ctrl = 0; hdcp.hdcp_state = HDCP_DISABLED; hdcp.pending_start = 0; hdcp.pending_wq_event = 0; hdcp.retry_cnt = 0; hdcp.auth_state = HDCP_STATE_DISABLED; hdcp.pending_disable = 0; hdcp.hdcp_up_event = 0; hdcp.hdcp_down_event = 0; hdcp_wait_re_entrance = 0; hdcp.hpd_low = 0; spin_lock_init(&hdcp.spinlock); init_completion(&hdcp_comp); hdcp.workqueue = create_singlethread_workqueue("hdcp"); if (hdcp.workqueue == NULL) { HDCP_ERR("Could not create HDCP workqueue\n"); goto err_add_driver; } INIT_DELAYED_WORK(&hdcp.hdcp_work->dwork, hdcp_work_queue); mutex_init(&hdcp.re_entrant_lock); if (hdmi_runtime_get()) { HDCP_ERR("%s Error enabling clocks\n", __func__); goto err_runtime; } /* Register HDCP callbacks to HDMI library */ if (cpu_is_omap44xx()) omapdss_hdmi_register_hdcp_callbacks(&omap4_hdcp_start_frame_cb, &omap4_hdcp_3des_cb, &omap4_hdcp_irq_cb); else omapdss_hdmi_register_hdcp_callbacks(&hdcp_start_frame_cb, &hdcp_3des_cb, &hdcp_irq_cb); hdmi_runtime_put(); mutex_unlock(&hdcp.lock); hdcp_load_keys(); return 0; err_runtime: mutex_destroy(&hdcp.re_entrant_lock); destroy_workqueue(hdcp.workqueue); err_add_driver: misc_deregister(hdcp.mdev); mutex_unlock(&hdcp.lock); err_misc_register: mutex_destroy(&hdcp.lock); iounmap(hdcp.deshdcp_base_addr); err_map_deshdcp: kfree(hdcp.mdev); err_alloc_mdev: kfree(hdcp.hdcp_work); err_alloc_work: if (cpu_is_omap44xx()) iounmap(hdcp.hdmi_wp_base_addr); return -EFAULT; }
static __devinit int omap_hdmi_probe(struct platform_device *pdev) { int ret; struct resource *hdmi_rsrc; struct omap_dss_device *dssdev = NULL; bool hdmi_dev_found = false; hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!hdmi_rsrc) { dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n"); return -ENODEV; } omap_hdmi_dai_dma_params.port_addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT; hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!hdmi_rsrc) { dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n"); return -ENODEV; } hdmi.oh = omap_hwmod_lookup("dss_hdmi"); if (!hdmi.oh) { dev_err(&pdev->dev, "can't find omap_hwmod for hdmi\n"); return -ENODEV; } omap_hdmi_dai_dma_params.dma_req = hdmi_rsrc->start; /* * Find an HDMI device. In the future, registers all the HDMI devices * it finds and create a PCM for each. */ for_each_dss_dev(dssdev) { omap_dss_get_device(dssdev); if (!dssdev->driver) { omap_dss_put_device(dssdev); continue; } if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { hdmi_dev_found = true; break; } } if (!hdmi_dev_found) { dev_err(&pdev->dev, "no driver for HDMI display found"); return -ENODEV; } hdmi.dssdev = dssdev; /* the supported rates and sample format depend on the cpu */ if (cpu_is_omap44xx()) { omap_hdmi_dai.playback.rates = OMAP4_HDMI_RATES; omap_hdmi_dai.playback.formats = OMAP4_HDMI_FORMATS; omap_hdmi_dai.playback.channels_max = 8; } else { /* OMAP5 */ omap_hdmi_dai.playback.rates = OMAP5_HDMI_RATES; omap_hdmi_dai.playback.formats = OMAP5_HDMI_FORMATS; #ifdef CONFIG_ARCH_OMAP5_ES1 omap_hdmi_dai.playback.channels_max = 2; #else omap_hdmi_dai.playback.channels_max = 8; #endif } ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai); hdmi.notifier.notifier_call = hdmi_audio_notifier_callback; blocking_notifier_chain_register(&hdmi.dssdev->state_notifiers, &hdmi.notifier); return ret; }
int __init musb_platform_init(struct musb *musb) { u32 l; struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; int status; /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ musb->xceiv = otg_get_transceiver(); if (!musb->xceiv) { pr_err("HS USB OTG: no transceiver configured\n"); return -ENODEV; } if (cpu_is_omap44xx()) { /* disable the optional 60M clock if enabled by romcode*/ l = omap_readl(0x4A009360); l &= ~0x00000100; omap_writel(l, 0x4A009360); omap_writel(0x1, 0x4A002300); } /* Fixme this can be enabled when load the gadget driver also*/ musb_platform_resume(musb); /*powerup the phy as romcode would have put the phy in some state * which is impacting the core retention if the gadget driver is not * loaded. */ l = musb_readl(musb->mregs, OTG_INTERFSEL); if (data->interface_type == MUSB_INTERFACE_UTMI) { /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */ l &= ~ULPI_12PIN; /* Disable ULPI */ l |= UTMI_8BIT; /* Enable UTMI */ } else { l |= ULPI_12PIN; } musb_writel(musb->mregs, OTG_INTERFSEL, l); pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, " "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n", musb_readl(musb->mregs, OTG_REVISION), musb_readl(musb->mregs, OTG_SYSCONFIG), musb_readl(musb->mregs, OTG_SYSSTATUS), musb_readl(musb->mregs, OTG_INTERFSEL), musb_readl(musb->mregs, OTG_SIMENABLE)); if (is_host_enabled(musb)) musb->board_set_vbus = omap_set_vbus; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); plat->is_usb_active = is_musb_active; if (cpu_is_omap44xx()) { wake_lock_init(&usb_lock, WAKE_LOCK_SUSPEND, "musb_wake_lock"); /* register for transciever notification*/ status = otg_register_notifier(musb->xceiv, &musb->nb); if (status) { DBG(1, "notification register failed\n"); wake_lock_destroy(&usb_lock); } } return 0; }