static int moxart_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *node = dev->of_node; struct resource res_mmc; struct mmc_host *mmc; struct moxart_host *host = NULL; struct dma_slave_config cfg; struct clk *clk; void __iomem *reg_mmc; int irq, ret; u32 i; mmc = mmc_alloc_host(sizeof(struct moxart_host), dev); if (!mmc) { dev_err(dev, "mmc_alloc_host failed\n"); ret = -ENOMEM; goto out; } ret = of_address_to_resource(node, 0, &res_mmc); if (ret) { dev_err(dev, "of_address_to_resource failed\n"); goto out; } irq = irq_of_parse_and_map(node, 0); if (irq <= 0) { dev_err(dev, "irq_of_parse_and_map failed\n"); ret = -EINVAL; goto out; } clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { ret = PTR_ERR(clk); goto out; } reg_mmc = devm_ioremap_resource(dev, &res_mmc); if (IS_ERR(reg_mmc)) { ret = PTR_ERR(reg_mmc); goto out; } ret = mmc_of_parse(mmc); if (ret) goto out; host = mmc_priv(mmc); host->mmc = mmc; host->base = reg_mmc; host->reg_phys = res_mmc.start; host->timeout = msecs_to_jiffies(1000); host->sysclk = clk_get_rate(clk); host->fifo_width = readl(host->base + REG_FEATURE) << 2; host->dma_chan_tx = dma_request_slave_channel_reason(dev, "tx"); host->dma_chan_rx = dma_request_slave_channel_reason(dev, "rx"); spin_lock_init(&host->lock); mmc->ops = &moxart_ops; mmc->f_max = DIV_ROUND_CLOSEST(host->sysclk, 2); mmc->f_min = DIV_ROUND_CLOSEST(host->sysclk, CLK_DIV_MASK * 2); mmc->ocr_avail = 0xffff00; /* Support 2.0v - 3.6v power. */ if (IS_ERR(host->dma_chan_tx) || IS_ERR(host->dma_chan_rx)) { if (PTR_ERR(host->dma_chan_tx) == -EPROBE_DEFER || PTR_ERR(host->dma_chan_rx) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto out; } dev_dbg(dev, "PIO mode transfer enabled\n"); host->have_dma = false; } else { dev_dbg(dev, "DMA channels found (%p,%p)\n", host->dma_chan_tx, host->dma_chan_rx); host->have_dma = true; cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.direction = DMA_MEM_TO_DEV; cfg.src_addr = 0; cfg.dst_addr = host->reg_phys + REG_DATA_WINDOW; dmaengine_slave_config(host->dma_chan_tx, &cfg); cfg.direction = DMA_DEV_TO_MEM; cfg.src_addr = host->reg_phys + REG_DATA_WINDOW; cfg.dst_addr = 0; dmaengine_slave_config(host->dma_chan_rx, &cfg); } switch ((readl(host->base + REG_BUS_WIDTH) >> 3) & 3) { case 1: mmc->caps |= MMC_CAP_4_BIT_DATA; break; case 2: mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; break; default: break; } writel(0, host->base + REG_INTERRUPT_MASK); writel(CMD_SDC_RESET, host->base + REG_COMMAND); for (i = 0; i < MAX_RETRIES; i++) { if (!(readl(host->base + REG_COMMAND) & CMD_SDC_RESET)) break; udelay(5); } ret = devm_request_irq(dev, irq, moxart_irq, 0, "moxart-mmc", host); if (ret) goto out; dev_set_drvdata(dev, mmc); mmc_add_host(mmc); dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width); return 0; out: if (mmc) mmc_free_host(mmc); return ret; }
static inline u16 freq_to_clock_divider(unsigned int freq, unsigned int rollovers) { return count_to_clock_divider( DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * rollovers)); }
static inline u16 ns_to_lpf_count(unsigned int ns) { return count_to_lpf_count( DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000)); }
static int vt8500_serial_probe(struct platform_device *pdev) { struct vt8500_port *vt8500_port; struct resource *mmres, *irqres; struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; const unsigned int *flags; int ret; int port; match = of_match_device(wmt_dt_ids, &pdev->dev); if (!match) return -EINVAL; flags = match->data; mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!mmres || !irqres) return -ENODEV; if (np) { port = of_alias_get_id(np, "serial"); if (port >= VT8500_MAX_PORTS) port = -1; } else { port = -1; } if (port < 0) { /* calculate the port id */ port = find_first_zero_bit(&vt8500_ports_in_use, sizeof(vt8500_ports_in_use)); } if (port >= VT8500_MAX_PORTS) return -ENODEV; /* reserve the port id */ if (test_and_set_bit(port, &vt8500_ports_in_use)) { /* port already in use - shouldn't really happen */ return -EBUSY; } vt8500_port = devm_kzalloc(&pdev->dev, sizeof(struct vt8500_port), GFP_KERNEL); if (!vt8500_port) return -ENOMEM; vt8500_port->uart.membase = devm_ioremap_resource(&pdev->dev, mmres); if (IS_ERR(vt8500_port->uart.membase)) return PTR_ERR(vt8500_port->uart.membase); vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); if (IS_ERR(vt8500_port->clk)) { dev_err(&pdev->dev, "failed to get clock\n"); return -EINVAL; } ret = clk_prepare_enable(vt8500_port->clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); return ret; } vt8500_port->vt8500_uart_flags = *flags; vt8500_port->clk_predivisor = DIV_ROUND_CLOSEST( clk_get_rate(vt8500_port->clk), VT8500_RECOMMENDED_CLK ); vt8500_port->uart.type = PORT_VT8500; vt8500_port->uart.iotype = UPIO_MEM; vt8500_port->uart.mapbase = mmres->start; vt8500_port->uart.irq = irqres->start; vt8500_port->uart.fifosize = 16; vt8500_port->uart.ops = &vt8500_uart_pops; vt8500_port->uart.line = port; vt8500_port->uart.dev = &pdev->dev; vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; /* Serial core uses the magic "16" everywhere - adjust for it */ vt8500_port->uart.uartclk = 16 * clk_get_rate(vt8500_port->clk) / vt8500_port->clk_predivisor / VT8500_OVERSAMPLING_DIVISOR; snprintf(vt8500_port->name, sizeof(vt8500_port->name), "VT8500 UART%d", pdev->id); vt8500_uart_ports[port] = vt8500_port; uart_add_one_port(&vt8500_uart_driver, &vt8500_port->uart); platform_set_drvdata(pdev, vt8500_port); return 0; }
static inline u16 carrier_freq_to_clock_divider(unsigned int freq) { return count_to_clock_divider( DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * 16)); }
int s3cfb_set_clock(struct s3cfb_global *ctrl) { struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); u32 cfg, maxclk, src_clk, vclk, div; /* spec is under 100MHz */ maxclk = 100 * 1000000; cfg = readl(ctrl->regs + S3C_VIDCON0); if (pdata->hw_ver == 0x70) { cfg &= ~(S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_VCLKEN_MASK); cfg |= (S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_FREERUN); src_clk = clk_get_rate(ctrl->clock); printk(KERN_DEBUG "FIMD src sclk = %d\n", src_clk); } else { cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | S3C_VIDCON0_VCLKEN_MASK | S3C_VIDCON0_CLKDIR_MASK); cfg |= (S3C_VIDCON0_CLKVALUP_ALWAYS | S3C_VIDCON0_VCLKEN_NORMAL | S3C_VIDCON0_CLKDIR_DIVIDED); if (strcmp(pdata->clk_name, "sclk_fimd") == 0) { cfg |= S3C_VIDCON0_CLKSEL_SCLK; src_clk = clk_get_rate(ctrl->clock); printk(KERN_DEBUG "FIMD src sclk = %d\n", src_clk); } else { cfg |= S3C_VIDCON0_CLKSEL_HCLK; src_clk = ctrl->clock->parent->rate; printk(KERN_DEBUG "FIMD src hclk = %d\n", src_clk); } } vclk = PICOS2KHZ(ctrl->fb[pdata->default_win]->var.pixclock) * 1000; if (vclk > maxclk) { dev_info(ctrl->dev, "vclk(%d) should be smaller than %d\n", vclk, maxclk); /* vclk = maxclk; */ } div = DIV_ROUND_CLOSEST(src_clk, vclk); if (div == 0) { dev_err(ctrl->dev, "div(%d) should be non-zero\n", div); div = 1; } if ((src_clk/div) > maxclk) dev_info(ctrl->dev, "vclk(%d) should be smaller than %d Hz\n", src_clk/div, maxclk); cfg &= ~S3C_VIDCON0_CLKVAL_F(0xff); cfg |= S3C_VIDCON0_CLKVAL_F(div - 1); writel(cfg, ctrl->regs + S3C_VIDCON0); dev_info(ctrl->dev, "parent clock: %d, vclk: %d, vclk div: %d\n", src_clk, vclk, div); return 0; }
u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp, struct intel_crtc_state *config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); u32 dsi_clock, pclk; u32 pll_ctl, pll_div; u32 m = 0, p = 0, n; int refclk = IS_CHERRYVIEW(dev_priv) ? 100000 : 25000; int i; DRM_DEBUG_KMS("\n"); mutex_lock(&dev_priv->sb_lock); pll_ctl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER); mutex_unlock(&dev_priv->sb_lock); config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK; config->dsi_pll.div = pll_div; /* mask out other bits and extract the P1 divisor */ pll_ctl &= DSI_PLL_P1_POST_DIV_MASK; pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2); /* N1 divisor */ n = (pll_div & DSI_PLL_N1_DIV_MASK) >> DSI_PLL_N1_DIV_SHIFT; n = 1 << n; /* register has log2(N1) */ /* mask out the other bits and extract the M1 divisor */ pll_div &= DSI_PLL_M1_DIV_MASK; pll_div = pll_div >> DSI_PLL_M1_DIV_SHIFT; while (pll_ctl) { pll_ctl = pll_ctl >> 1; p++; } p--; if (!p) { DRM_ERROR("wrong P1 divisor\n"); return 0; } for (i = 0; i < ARRAY_SIZE(lfsr_converts); i++) { if (lfsr_converts[i] == pll_div) break; } if (i == ARRAY_SIZE(lfsr_converts)) { DRM_ERROR("wrong m_seed programmed\n"); return 0; } m = i + 62; dsi_clock = (m * refclk) / (p * n); /* pixel_format and pipe_bpp should agree */ assert_bpp_mismatch(intel_dsi->pixel_format, pipe_bpp); pclk = DIV_ROUND_CLOSEST(dsi_clock * intel_dsi->lane_count, pipe_bpp); return pclk; }
static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count) { struct iguanair *ir = dev->priv; uint8_t space, *payload; unsigned i, size, rc; struct send_packet *packet; mutex_lock(&ir->lock); /* convert from us to carrier periods */ for (i = size = 0; i < count; i++) { txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000); size += (txbuf[i] + 126) / 127; } packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL); if (!packet) { rc = -ENOMEM; goto out; } if (size > ir->bufsize) { rc = -E2BIG; goto out; } packet->header.start = 0; packet->header.direction = DIR_OUT; packet->header.cmd = CMD_SEND; packet->length = size; packet->channels = ir->channels << 4; packet->busy7 = ir->busy7; packet->busy4 = ir->busy4; space = 0; payload = packet->payload; for (i = 0; i < count; i++) { unsigned periods = txbuf[i]; while (periods > 127) { *payload++ = 127 | space; periods -= 127; } *payload++ = periods | space; space ^= 0x80; } if (ir->receiver_on) { rc = iguanair_receiver(ir, false); if (rc) { dev_warn(ir->dev, "disable receiver before transmit failed\n"); goto out; } } ir->tx_overflow = false; INIT_COMPLETION(ir->completion); rc = iguanair_send(ir, packet, size + 8, NULL, NULL); if (rc == 0) { wait_for_completion_timeout(&ir->completion, TIMEOUT); if (ir->tx_overflow) rc = -EOVERFLOW; } ir->tx_overflow = false; if (ir->receiver_on) { if (iguanair_receiver(ir, true)) dev_warn(ir->dev, "re-enable receiver after transmit failed\n"); } out: mutex_unlock(&ir->lock); kfree(packet); return rc; }
static inline int calc_divisor(NS16550_t port, int clock, int baudrate) { const unsigned int mode_x_div = 16; return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); }
static inline int DS1621_TEMP_FROM_REG(u16 reg) { return DIV_ROUND_CLOSEST(((s16)reg / 16) * 625, 10); }
/* * TEMP: 0.001C/bit (-55C to +125C) * REG: * - 1621, 1625: 0.5C/bit, 7 zero-bits * - 1631, 1721, 1731: 0.0625C/bit, 4 zero-bits */ static inline u16 DS1621_TEMP_TO_REG(long temp, u8 zbits) { temp = clamp_val(temp, DS1621_TEMP_MIN, DS1621_TEMP_MAX); temp = DIV_ROUND_CLOSEST(temp * (1 << (8 - zbits)), 1000) << zbits; return temp; }
static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns) { struct s3c_chip *s3c = to_s3c_chip(chip); struct s3c_pwm_device *s3c_pwm = pwm_get_chip_data(pwm); void __iomem *reg_base = s3c->reg_base; unsigned long tin_rate; unsigned long tin_ns; unsigned long period; unsigned long flags; unsigned long tcon; unsigned long tcnt; long tcmp; enum duty_cycle duty_cycle; unsigned int id = pwm->pwm; /* We currently avoid using 64bit arithmetic by using the * fact that anything faster than 1Hz is easily representable * by 32bits. */ if (period_ns > NS_IN_HZ || duty_ns > NS_IN_HZ) return -ERANGE; if (duty_ns > period_ns) return -EINVAL; if (period_ns == s3c_pwm->period_ns && duty_ns == s3c_pwm->duty_ns) return 0; period = NS_IN_HZ / period_ns; /* Check to see if we are changing the clock rate of the PWM */ if (s3c_pwm->period_ns != period_ns && pwm_is_tdiv(s3c_pwm)) { tin_rate = pwm_calc_tin(pwm, period); clk_set_rate(s3c_pwm->clk_div, tin_rate); tin_rate = clk_get_rate(s3c_pwm->clk_div); s3c_pwm->period_ns = period_ns; pwm_dbg(s3c, "tin_rate=%lu\n", tin_rate); } else { tin_rate = clk_get_rate(s3c_pwm->clk_tin); } if(!tin_rate) return -EFAULT; /* Note, counters count down */ tin_ns = NS_IN_HZ / tin_rate; tcnt = DIV_ROUND_CLOSEST(period_ns, tin_ns); tcmp = DIV_ROUND_CLOSEST(duty_ns, tin_ns); if (tcnt <= 1) { /* Too small to generate a pulse */ return -ERANGE; } pwm_dbg(s3c, "duty_ns=%d, period_ns=%d (%lu)\n", duty_ns, period_ns, period); if (tcmp == 0) duty_cycle = DUTY_CYCLE_ZERO; else if (tcmp == tcnt) duty_cycle = DUTY_CYCLE_FULL; else duty_cycle = DUTY_CYCLE_PULSE; tcmp = tcnt - tcmp; /* the pwm hw only checks the compare register after a decrement, so the pin never toggles if tcmp = tcnt */ if (tcmp == tcnt) tcmp--; /* * PWM counts 1 hidden tick at the end of each period on S3C64XX and * EXYNOS series, so tcmp and tcnt should be subtracted 1. */ if (!pwm_is_s3c24xx(s3c)) { tcnt--; /* * tcmp can be -1. It appears 100% duty cycle and PWM never * toggles when TCMPB is set to 0xFFFFFFFF (-1). */ tcmp--; } pwm_dbg(s3c, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); /* Update the PWM register block. */ spin_lock_irqsave(&pwm_spinlock, flags); __raw_writel(tcmp, reg_base + REG_TCMPB(id)); __raw_writel(tcnt, reg_base + REG_TCNTB(id)); if (pwm_is_s3c24xx(s3c)) { tcon = __raw_readl(reg_base + REG_TCON); tcon |= pwm_tcon_manulupdate(s3c_pwm); tcon |= pwm_tcon_autoreload(s3c_pwm); __raw_writel(tcon, reg_base + REG_TCON); tcon &= ~pwm_tcon_manulupdate(s3c_pwm); __raw_writel(tcon, reg_base + REG_TCON); } else { tcon = __raw_readl(reg_base + REG_TCON); if (s3c_pwm->running == 1 && tcon & pwm_tcon_start(s3c_pwm) && s3c_pwm->duty_cycle != duty_cycle) { if (duty_cycle == DUTY_CYCLE_ZERO) { tcon |= pwm_tcon_manulupdate(s3c_pwm); __raw_writel(tcon, reg_base + REG_TCON); tcon &= ~pwm_tcon_manulupdate(s3c_pwm); tcon &= ~pwm_tcon_autoreload(s3c_pwm); } else { tcon |= pwm_tcon_autoreload(s3c_pwm); } __raw_writel(tcon, reg_base + REG_TCON); } } s3c_pwm->duty_ns = duty_ns; s3c_pwm->period_ns = period_ns; s3c_pwm->duty_cycle = duty_cycle; spin_unlock_irqrestore(&pwm_spinlock, flags); return 0; }
int get_divider(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; struct clksrc_clk *sclk; struct clk *clk; u32 rate, reg, i; u8 fimd_div; sclk = container_of(fbdev->clock, struct clksrc_clk, clk); clk = clk_get_parent(clk_get_parent(fbdev->clock)); rate = clk_get_rate(clk); lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv = DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_NORMAL].vclk); lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv = DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_LIMIT].vclk); fimd_div = gcd(lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv, lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv); if ((!fimd_div) || (fimd_div > 16)) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv /= fimd_div; lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv /= fimd_div; dev_info(fb->dev, "%s rate is %d, fimd divider=%d\n", clk->name, rate, fimd_div); fimd_div--; for (i = 0; i < LCDFREQ_LEVEL_END; i++) { if (lcdfreq->table[i].cmu_clkdiv > 16) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } dev_info(fb->dev, "%dhz div is %d\n", lcdfreq->table[i].hz, lcdfreq->table[i].cmu_clkdiv); lcdfreq->table[i].cmu_clkdiv--; } reg = (readl(fbdev->regs + S3C_VIDCON0) & (S3C_VIDCON0_CLKVAL_F(0xff))) >> 6; if (fimd_div != reg) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } reg = (readl(sclk->reg_div.reg)) >> sclk->reg_div.shift; reg &= 0xf; if (lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv != reg) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } return 0; err: return -EINVAL; }
static void mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); unsigned long flags; unsigned int baud, quot; #ifdef CONFIG_SERIAL_8250_DMA if (up->dma) { if (uart_console(port)) { devm_kfree(up->port.dev, up->dma); up->dma = NULL; } else { mtk8250_dma_enable(up); } } #endif serial8250_do_set_termios(port, termios, old); /* * Mediatek UARTs use an extra highspeed register (UART_MTK_HIGHS) * * We need to recalcualte the quot register, as the claculation depends * on the vaule in the highspeed register. * * Some baudrates are not supported by the chip, so we use the next * lower rate supported and update termios c_flag. * * If highspeed register is set to 3, we need to specify sample count * and sample point to increase accuracy. If not, we reset the * registers to their default values. */ baud = uart_get_baud_rate(port, termios, old, port->uartclk / 16 / UART_DIV_MAX, port->uartclk); if (baud <= 115200) { serial_port_out(port, UART_MTK_HIGHS, 0x0); quot = uart_get_divisor(port, baud); } else if (baud <= 576000) { serial_port_out(port, UART_MTK_HIGHS, 0x2); /* Set to next lower baudrate supported */ if ((baud == 500000) || (baud == 576000)) baud = 460800; quot = DIV_ROUND_UP(port->uartclk, 4 * baud); } else { serial_port_out(port, UART_MTK_HIGHS, 0x3); quot = DIV_ROUND_UP(port->uartclk, 256 * baud); } /* * Ok, we're now changing the port state. Do it with * interrupts disabled. */ spin_lock_irqsave(&port->lock, flags); /* set DLAB we have cval saved in up->lcr from the call to the core */ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); serial_dl_write(up, quot); /* reset DLAB */ serial_port_out(port, UART_LCR, up->lcr); if (baud > 460800) { unsigned int tmp; tmp = DIV_ROUND_CLOSEST(port->uartclk, quot * baud); serial_port_out(port, UART_MTK_SAMPLE_COUNT, tmp - 1); serial_port_out(port, UART_MTK_SAMPLE_POINT, (tmp - 2) >> 1); } else {
static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq, bool xtal) { unsigned int div, clksrc, pllcfg = 0; long besterr = -1; unsigned long fdiv, fmul, bestfreq = freq; /* First, update error without PLL */ max310x_update_best_err(freq, &besterr); /* Try all possible PLL dividers */ for (div = 1; (div <= 63) && besterr; div++) { fdiv = DIV_ROUND_CLOSEST(freq, div); /* Try multiplier 6 */ fmul = fdiv * 6; if ((fdiv >= 500000) && (fdiv <= 800000)) if (!max310x_update_best_err(fmul, &besterr)) { pllcfg = (0 << 6) | div; bestfreq = fmul; } /* Try multiplier 48 */ fmul = fdiv * 48; if ((fdiv >= 850000) && (fdiv <= 1200000)) if (!max310x_update_best_err(fmul, &besterr)) { pllcfg = (1 << 6) | div; bestfreq = fmul; } /* Try multiplier 96 */ fmul = fdiv * 96; if ((fdiv >= 425000) && (fdiv <= 1000000)) if (!max310x_update_best_err(fmul, &besterr)) { pllcfg = (2 << 6) | div; bestfreq = fmul; } /* Try multiplier 144 */ fmul = fdiv * 144; if ((fdiv >= 390000) && (fdiv <= 667000)) if (!max310x_update_best_err(fmul, &besterr)) { pllcfg = (3 << 6) | div; bestfreq = fmul; } } /* Configure clock source */ clksrc = xtal ? MAX310X_CLKSRC_CRYST_BIT : MAX310X_CLKSRC_EXTCLK_BIT; /* Configure PLL */ if (pllcfg) { clksrc |= MAX310X_CLKSRC_PLL_BIT; regmap_write(s->regmap, MAX310X_PLLCFG_REG, pllcfg); } else clksrc |= MAX310X_CLKSRC_PLLBYP_BIT; regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc); /* Wait for crystal */ if (pllcfg && xtal) msleep(10); return (int)bestfreq; }
/* * vrm is the VRM/VRD document version multiplied by 10. * val is the 4-bit or more VID code. * Returned value is in mV to avoid floating point in the kernel. * Some VID have some bits in uV scale, this is rounded to mV. */ int vid_from_reg(int val, u8 vrm) { int vid; switch (vrm) { case 100: /* VRD 10.0 */ /* compute in uV, round to mV */ val &= 0x3f; if ((val & 0x1f) == 0x1f) return 0; if ((val & 0x1f) <= 0x09 || val == 0x0a) vid = 1087500 - (val & 0x1f) * 25000; else vid = 1862500 - (val & 0x1f) * 25000; if (val & 0x20) vid -= 12500; return (vid + 500) / 1000; case 110: /* Intel Conroe */ /* compute in uV, round to mV */ val &= 0xff; if (val < 0x02 || val > 0xb2) return 0; return (1600000 - (val - 2) * 6250 + 500) / 1000; case 24: /* Athlon64 & Opteron */ val &= 0x1f; if (val == 0x1f) return 0; /* fall through */ case 25: /* AMD NPT 0Fh */ val &= 0x3f; return (val < 32) ? 1550 - 25 * val : 775 - (25 * (val - 31)) / 2; case 26: /* AMD family 10h to 15h, serial VID */ val &= 0x7f; if (val >= 0x7c) return 0; return DIV_ROUND_CLOSEST(15500 - 125 * val, 10); case 91: /* VRM 9.1 */ case 90: /* VRM 9.0 */ val &= 0x1f; return val == 0x1f ? 0 : 1850 - val * 25; case 85: /* VRM 8.5 */ val &= 0x1f; return (val & 0x10 ? 25 : 0) + ((val & 0x0f) > 0x04 ? 2050 : 1250) - ((val & 0x0f) * 50); case 84: /* VRM 8.4 */ val &= 0x0f; /* fall through */ case 82: /* VRM 8.2 */ val &= 0x1f; return val == 0x1f ? 0 : val & 0x10 ? 5100 - (val) * 100 : 2050 - (val) * 50; case 17: /* Intel IMVP-II */ val &= 0x1f; return val & 0x10 ? 975 - (val & 0xF) * 25 : 1750 - val * 50; case 13: case 131: val &= 0x3f; /* Exception for Eden ULV 500 MHz */ if (vrm == 131 && val == 0x3f) val++; return 1708 - val * 16; case 14: /* Intel Core */ /* compute in uV, round to mV */ val &= 0x7f; return val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000; default: /* report 0 for unknown */ if (vrm) pr_warn("Requested unsupported VRM version (%u)\n", (unsigned int)vrm); return 0; } }
unsigned int uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, struct ktermios *old, unsigned int min, unsigned int max) { unsigned int try, baud, altbaud = 38400; int hung_up = 0; upf_t flags = port->flags & UPF_SPD_MASK; if (flags == UPF_SPD_HI) altbaud = 57600; else if (flags == UPF_SPD_VHI) altbaud = 115200; else if (flags == UPF_SPD_SHI) altbaud = 230400; else if (flags == UPF_SPD_WARP) altbaud = 460800; for (try = 0; try < 2; try++) { baud = tty_termios_baud_rate(termios); if (baud == 38400) baud = altbaud; if (baud == 0) { hung_up = 1; baud = 9600; } if (baud >= min && baud <= max) return baud; termios->c_cflag &= ~CBAUD; if (old) { baud = tty_termios_baud_rate(old); if (!hung_up) tty_termios_encode_baud_rate(termios, baud, baud); old = NULL; continue; } if (!hung_up) { if (baud <= min) tty_termios_encode_baud_rate(termios, min + 1, min + 1); else tty_termios_encode_baud_rate(termios, max - 1, max - 1); } } WARN_ON(1); return 0; } EXPORT_SYMBOL(uart_get_baud_rate); unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud) { unsigned int quot; if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) quot = port->custom_divisor; else quot = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud); return quot; }
/** * ti_abb_init_timings() - setup ABB clock timing for the current platform * @dev: device * @abb: pointer to the abb instance * * Return: 0 if timing is updated, else returns error result. */ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb) { u32 clock_cycles; u32 clk_rate, sr2_wt_cnt_val, cycle_rate; const struct ti_abb_reg *regs = abb->regs; int ret; char *pname = "ti,settling-time"; /* read device tree properties */ ret = of_property_read_u32(dev->of_node, pname, &abb->settling_time); if (ret) { dev_err(dev, "Unable to get property '%s'(%d)\n", pname, ret); return ret; } /* ABB LDO cannot be settle in 0 time */ if (!abb->settling_time) { dev_err(dev, "Invalid property:'%s' set as 0!\n", pname); return -EINVAL; } pname = "ti,clock-cycles"; ret = of_property_read_u32(dev->of_node, pname, &clock_cycles); if (ret) { dev_err(dev, "Unable to get property '%s'(%d)\n", pname, ret); return ret; } /* ABB LDO cannot be settle in 0 clock cycles */ if (!clock_cycles) { dev_err(dev, "Invalid property:'%s' set as 0!\n", pname); return -EINVAL; } abb->clk = devm_clk_get(dev, NULL); if (IS_ERR(abb->clk)) { ret = PTR_ERR(abb->clk); dev_err(dev, "%s: Unable to get clk(%d)\n", __func__, ret); return ret; } /* * SR2_WTCNT_VALUE is the settling time for the ABB ldo after a * transition and must be programmed with the correct time at boot. * The value programmed into the register is the number of SYS_CLK * clock cycles that match a given wall time profiled for the ldo. * This value depends on: * settling time of ldo in micro-seconds (varies per OMAP family) * # of clock cycles per SYS_CLK period (varies per OMAP family) * the SYS_CLK frequency in MHz (varies per board) * The formula is: * * ldo settling time (in micro-seconds) * SR2_WTCNT_VALUE = ------------------------------------------ * (# system clock cycles) * (sys_clk period) * * Put another way: * * SR2_WTCNT_VALUE = settling time / (# SYS_CLK cycles / SYS_CLK rate)) * * To avoid dividing by zero multiply both "# clock cycles" and * "settling time" by 10 such that the final result is the one we want. */ /* Convert SYS_CLK rate to MHz & prevent divide by zero */ clk_rate = DIV_ROUND_CLOSEST(clk_get_rate(abb->clk), 1000000); /* Calculate cycle rate */ cycle_rate = DIV_ROUND_CLOSEST(clock_cycles * 10, clk_rate); /* Calulate SR2_WTCNT_VALUE */ sr2_wt_cnt_val = DIV_ROUND_CLOSEST(abb->settling_time * 10, cycle_rate); dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__, clk_get_rate(abb->clk), sr2_wt_cnt_val); ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, abb->setup_reg); return 0; }
static inline u16 ns_to_clock_divider(unsigned int ns) { return count_to_clock_divider( DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000)); }
static int current_to_voltage(struct bcl_context *bcl, int ua) { return DIV_ROUND_CLOSEST(ua * bcl->btm_uv_to_ua_denominator, bcl->btm_uv_to_ua_numerator); }
static int gt_clockevent_set_periodic(struct clock_event_device *evt) { gt_compare_set(DIV_ROUND_CLOSEST(gt_clk_rate, HZ), 1); return 0; }
static int voltage_to_current(struct bcl_context *bcl, int uv) { return DIV_ROUND_CLOSEST(uv * bcl->btm_uv_to_ua_numerator, bcl->btm_uv_to_ua_denominator); }
static inline unsigned int clock_divider_to_ns(unsigned int divider) { /* Period of the Rx or Tx clock in ns */ return DIV_ROUND_CLOSEST((divider + 1) * 1000, CX25840_IR_REFCLK_FREQ / 1000000); }
static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) { const struct pmbus_driver_info *info = pmbus_get_driver_info(client); const struct lm25066_data *data = to_lm25066_data(info); int ret; if (page > 1) return -ENXIO; /* Map READ_VAUX into READ_VOUT register on page 1 */ if (page == 1) { switch (reg) { case PMBUS_READ_VOUT: ret = pmbus_read_word_data(client, 0, LM25066_READ_VAUX); if (ret < 0) break; /* Adjust returned value to match VOUT coefficients */ switch (data->id) { case lm25066: /* VOUT: 4.54 mV VAUX: 283.2 uV LSB */ ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); break; case lm5064: /* VOUT: 4.53 mV VAUX: 700 uV LSB */ ret = DIV_ROUND_CLOSEST(ret * 70, 453); break; case lm5066: /* VOUT: 2.18 mV VAUX: 725 uV LSB */ ret = DIV_ROUND_CLOSEST(ret * 725, 2180); break; } break; default: /* No other valid registers on page 1 */ ret = -ENXIO; break; } goto done; } switch (reg) { case PMBUS_READ_IIN: ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN); break; case PMBUS_READ_PIN: ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN); break; case PMBUS_IIN_OC_WARN_LIMIT: ret = pmbus_read_word_data(client, 0, LM25066_MFR_IIN_OC_WARN_LIMIT); break; case PMBUS_PIN_OP_WARN_LIMIT: ret = pmbus_read_word_data(client, 0, LM25066_MFR_PIN_OP_WARN_LIMIT); break; case PMBUS_VIRT_READ_VIN_AVG: ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN); break; case PMBUS_VIRT_READ_VOUT_AVG: ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT); break; case PMBUS_VIRT_READ_IIN_AVG: ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN); break; case PMBUS_VIRT_READ_PIN_AVG: ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN); break; case PMBUS_VIRT_READ_PIN_MAX: ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK); break; case PMBUS_VIRT_RESET_PIN_HISTORY: ret = 0; break; default: ret = -ENODATA; break; } done: return ret; }
static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider) { return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * 16); }
static int m88ds3103_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct m88ds3103_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i, itmp; unsigned int utmp; u8 buf[3]; *status = 0; if (!dev->warm) { ret = -EAGAIN; goto err; } switch (c->delivery_system) { case SYS_DVBS: ret = regmap_read(dev->regmap, 0xd1, &utmp); if (ret) goto err; if ((utmp & 0x07) == 0x07) *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; break; case SYS_DVBS2: ret = regmap_read(dev->regmap, 0x0d, &utmp); if (ret) goto err; if ((utmp & 0x8f) == 0x8f) *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; break; default: dev_dbg(&client->dev, "invalid delivery_system\n"); ret = -EINVAL; goto err; } dev->fe_status = *status; dev_dbg(&client->dev, "lock=%02x status=%02x\n", utmp, *status); /* CNR */ if (dev->fe_status & FE_HAS_VITERBI) { unsigned int cnr, noise, signal, noise_tot, signal_tot; cnr = 0; /* more iterations for more accurate estimation */ #define M88DS3103_SNR_ITERATIONS 3 switch (c->delivery_system) { case SYS_DVBS: itmp = 0; for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { ret = regmap_read(dev->regmap, 0xff, &utmp); if (ret) goto err; itmp += utmp; } /* use of single register limits max value to 15 dB */ /* SNR(X) dB = 10 * ln(X) / ln(10) dB */ itmp = DIV_ROUND_CLOSEST(itmp, 8 * M88DS3103_SNR_ITERATIONS); if (itmp) cnr = div_u64((u64) 10000 * intlog2(itmp), intlog2(10)); break; case SYS_DVBS2: noise_tot = 0; signal_tot = 0; for (i = 0; i < M88DS3103_SNR_ITERATIONS; i++) { ret = regmap_bulk_read(dev->regmap, 0x8c, buf, 3); if (ret) goto err; noise = buf[1] << 6; /* [13:6] */ noise |= buf[0] & 0x3f; /* [5:0] */ noise >>= 2; signal = buf[2] * buf[2]; signal >>= 1; noise_tot += noise; signal_tot += signal; } noise = noise_tot / M88DS3103_SNR_ITERATIONS; signal = signal_tot / M88DS3103_SNR_ITERATIONS; /* SNR(X) dB = 10 * log10(X) dB */ if (signal > noise) { itmp = signal / noise; cnr = div_u64((u64) 10000 * intlog10(itmp), (1 << 24)); } break; default: dev_dbg(&client->dev, "invalid delivery_system\n"); ret = -EINVAL; goto err; } if (cnr) { c->cnr.stat[0].scale = FE_SCALE_DECIBEL; c->cnr.stat[0].svalue = cnr; } else { c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; } } else {
static inline unsigned int clock_divider_to_freq(unsigned int divider, unsigned int rollovers) { return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * rollovers); }
static unsigned int get_clk_rate(struct platform_device *pdev, struct clk *sclk) { struct s3c_platform_fb *pdata = pdev->dev.platform_data; struct s3cfb_lcd *lcd = (struct s3cfb_lcd *)pdata->lcd; struct s3cfb_lcd_timing *timing = &lcd->timing; u32 src_clk, vclk, div, rate; u32 vclk_limit, div_limit, fimd_div; src_clk = clk_get_rate(sclk); vclk = (lcd->freq * (timing->h_bp + timing->h_fp + timing->h_sw + lcd->width) * (timing->v_bp + timing->v_fp + timing->v_sw + lcd->height)); #ifdef CONFIG_FB_S5P_I80_LCD vclk *= 2; #endif if (!vclk) vclk = src_clk; div = DIV_ROUND_CLOSEST(src_clk, vclk); if (lcd->freq_limit) { vclk_limit = (lcd->freq_limit * (timing->h_bp + timing->h_fp + timing->h_sw + lcd->width) * (timing->v_bp + timing->v_fp + timing->v_sw + lcd->height)); div_limit = DIV_ROUND_CLOSEST(src_clk, vclk_limit); fimd_div = gcd(div, div_limit); if (div/fimd_div <= 16) div /= fimd_div; } if (!div) { dev_err(&pdev->dev, "div(%d) should be non-zero\n", div); div = 1; } else if (div > 16) { for (fimd_div = 2; fimd_div <= div; fimd_div++) { if ((div%fimd_div == 0) && (div/fimd_div <= 16)) break; } div /= fimd_div; } div = (div > 16) ? 16 : div; rate = src_clk / div; if ((src_clk % rate) && (div != 1)) { div--; rate = src_clk / div; if (!(src_clk % rate)) rate--; } dev_info(&pdev->dev, "src_clk=%d, vclk=%d, div=%d(%d), rate=%d\n", src_clk, vclk, DIV_ROUND_CLOSEST(src_clk, vclk), div, rate); return rate; }
static inline unsigned int lpf_count_to_us(unsigned int count) { /* Duration of the Low Pass Filter rejection window in us */ return DIV_ROUND_CLOSEST(count, CX25840_IR_REFCLK_FREQ / 1000000); }
static char * minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) { const struct mcs_group *mg; unsigned int j, tp_max, tp_avg, eprob, tx_time; char htmode = '2'; char gimode = 'L'; u32 gflags; if (!mi->supported[i]) return p; mg = &minstrel_mcs_groups[i]; gflags = mg->flags; if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) htmode = '4'; else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH) htmode = '8'; if (gflags & IEEE80211_TX_RC_SHORT_GI) gimode = 'S'; for (j = 0; j < MCS_GROUP_RATES; j++) { struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; static const int bitrates[4] = { 10, 20, 55, 110 }; int idx = i * MCS_GROUP_RATES + j; unsigned int duration; if (!(mi->supported[i] & BIT(j))) continue; if (gflags & IEEE80211_TX_RC_MCS) { p += sprintf(p, "HT%c0 ", htmode); p += sprintf(p, "%cGI ", gimode); p += sprintf(p, "%d ", mg->streams); } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { p += sprintf(p, "VHT%c0 ", htmode); p += sprintf(p, "%cGI ", gimode); p += sprintf(p, "%d ", mg->streams); } else { p += sprintf(p, "CCK "); p += sprintf(p, "%cP ", j < 4 ? 'L' : 'S'); p += sprintf(p, "1 "); } *(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' '; *(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' '; *(p++) = (idx == mi->max_tp_rate[2]) ? 'C' : ' '; *(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' '; *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; if (gflags & IEEE80211_TX_RC_MCS) { p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j); } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { p += sprintf(p, " MCS%-1u/%1u", j, mg->streams); } else { int r = bitrates[j % 4]; p += sprintf(p, " %2u.%1uM", r / 10, r % 10); } p += sprintf(p, " %3u ", idx); /* tx_time[rate(i)] in usec */ duration = mg->duration[j]; duration <<= mg->shift; tx_time = DIV_ROUND_CLOSEST(duration, 1000); p += sprintf(p, "%6u ", tx_time); tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u" " %3u %3u %-3u " "%9llu %-9llu\n", tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, mrs->retry_count, mrs->last_success, mrs->last_attempts, (unsigned long long)mrs->succ_hist, (unsigned long long)mrs->att_hist); } return p; }