本文整理汇总了C++中DIV_ROUND_CLOSEST函数的典型用法代码示例。如果您正苦于以下问题:C++ DIV_ROUND_CLOSEST函数的具体用法?C++ DIV_ROUND_CLOSEST怎么用?C++ DIV_ROUND_CLOSEST使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了DIV_ROUND_CLOSEST函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: moxart_probe
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;
//.........这里部分代码省略.........
示例2: freq_to_clock_divider
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));
}
示例3: ns_to_lpf_count
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));
}
示例4: vt8500_serial_probe
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;
}
示例5: carrier_freq_to_clock_divider
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));
}
示例6: s3cfb_set_clock
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;
}
示例7: vlv_dsi_get_pclk
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;
}
示例8: iguanair_tx
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;
}
示例9: calc_divisor
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);
}
示例10: DS1621_TEMP_FROM_REG
static inline int DS1621_TEMP_FROM_REG(u16 reg)
{
return DIV_ROUND_CLOSEST(((s16)reg / 16) * 625, 10);
}
示例11: DS1621_TEMP_TO_REG
/*
* 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;
}
示例12: s3c_pwm_config
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);
//.........这里部分代码省略.........
示例13: mtk8250_set_termios
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 {
示例14: max310x_set_ref_clk
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;
}
示例15: vid_from_reg
/*
* 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;
}
}