Lines Matching +full:tach +full:- +full:ch

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * PWM/TACH controller driver for Aspeed ast2600 SoCs.
9 * Q := (DIV_L + 1) << DIV_H / input-clk
31 * - Enabled changing when the duty_cycle bigger than 0% and less than 100%.
32 * - Polarity changing when the duty_cycle bigger than 0% and less than 100%.
35 * - When changing both duty cycle and period, we cannot prevent in
38 * - Disabling the PWM doesn't complete the current period.
41 * - When only changing one of duty cycle or period, our pwm controller will not
65 #define PWM_ASPEED_CTRL(ch) ((ch) * 0x10 + 0x00) argument
78 #define PWM_ASPEED_DUTY_CYCLE(ch) ((ch) * 0x10 + 0x04) argument
87 /* The channel number of Aspeed tach controller */
89 /* TACH Control Register */
90 #define TACH_ASPEED_CTRL(ch) (((ch) * 0x10) + 0x08) argument
116 /* TACH Status Register */
117 #define TACH_ASPEED_STS(ch) (((ch) * 0x10) + 0x0C) argument
153 u32 hwpwm = pwm->hwpwm; in aspeed_pwm_get_state()
158 val = readl(priv->base + PWM_ASPEED_CTRL(hwpwm)); in aspeed_pwm_get_state()
164 val = readl(priv->base + PWM_ASPEED_DUTY_CYCLE(hwpwm)); in aspeed_pwm_get_state()
173 state->period = DIV_ROUND_UP_ULL(dividend, priv->clk_rate); in aspeed_pwm_get_state()
178 state->duty_cycle = DIV_ROUND_UP_ULL(dividend, priv->clk_rate); in aspeed_pwm_get_state()
180 state->duty_cycle = clk_en ? state->period : 0; in aspeed_pwm_get_state()
182 state->polarity = polarity ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL; in aspeed_pwm_get_state()
183 state->enabled = pin_en; in aspeed_pwm_get_state()
191 u32 hwpwm = pwm->hwpwm, duty_pt, val; in aspeed_pwm_apply()
195 expect_period = div64_u64(ULLONG_MAX, (u64)priv->clk_rate); in aspeed_pwm_apply()
196 expect_period = min(expect_period, state->period); in aspeed_pwm_apply()
198 expect_period, state->duty_cycle); in aspeed_pwm_apply()
205 div_h = order_base_2(DIV64_U64_ROUND_UP(priv->clk_rate * expect_period, divisor)); in aspeed_pwm_apply()
210 div_l = div64_u64(priv->clk_rate * expect_period, divisor); in aspeed_pwm_apply()
213 return -ERANGE; in aspeed_pwm_apply()
215 div_l -= 1; in aspeed_pwm_apply()
221 priv->clk_rate, div_h, div_l); in aspeed_pwm_apply()
223 duty_pt = div64_u64(state->duty_cycle * priv->clk_rate, in aspeed_pwm_apply()
226 state->duty_cycle, duty_pt); in aspeed_pwm_apply()
230 * fine-grained resolution for duty_cycle at the expense of a in aspeed_pwm_apply()
233 val = readl(priv->base + PWM_ASPEED_DUTY_CYCLE(hwpwm)); in aspeed_pwm_apply()
237 writel(val, priv->base + PWM_ASPEED_DUTY_CYCLE(hwpwm)); in aspeed_pwm_apply()
246 val = readl(priv->base + PWM_ASPEED_DUTY_CYCLE(hwpwm)); in aspeed_pwm_apply()
250 writel(val, priv->base + PWM_ASPEED_DUTY_CYCLE(hwpwm)); in aspeed_pwm_apply()
253 val = readl(priv->base + PWM_ASPEED_CTRL(hwpwm)); in aspeed_pwm_apply()
259 FIELD_PREP(PWM_ASPEED_CTRL_PIN_ENABLE, state->enabled) | in aspeed_pwm_apply()
261 FIELD_PREP(PWM_ASPEED_CTRL_INVERSE, state->polarity); in aspeed_pwm_apply()
262 writel(val, priv->base + PWM_ASPEED_CTRL(hwpwm)); in aspeed_pwm_apply()
276 writel(readl(priv->base + TACH_ASPEED_CTRL(tach_ch)) | in aspeed_tach_ch_enable()
278 priv->base + TACH_ASPEED_CTRL(tach_ch)); in aspeed_tach_ch_enable()
280 writel(readl(priv->base + TACH_ASPEED_CTRL(tach_ch)) & in aspeed_tach_ch_enable()
282 priv->base + TACH_ASPEED_CTRL(tach_ch)); in aspeed_tach_ch_enable()
290 tach_div = tach_val * priv->tach_divisor * DEFAULT_FAN_PULSE_PR; in aspeed_tach_val_to_rpm()
292 dev_dbg(priv->dev, "clk %ld, tach_val %d , tach_div %d\n", in aspeed_tach_val_to_rpm()
293 priv->clk_rate, tach_val, tach_div); in aspeed_tach_val_to_rpm()
295 rpm = (u64)priv->clk_rate * 60; in aspeed_tach_val_to_rpm()
306 val = readl(priv->base + TACH_ASPEED_STS(fan_tach_ch)); in aspeed_get_fan_tach_ch_rpm()
326 reg_val = readl(priv->base + TACH_ASPEED_CTRL(channel)); in aspeed_tach_hwmon_read()
331 return -EOPNOTSUPP; in aspeed_tach_hwmon_read()
347 return -EINVAL; in aspeed_tach_hwmon_write()
348 priv->tach_divisor = val; in aspeed_tach_hwmon_write()
349 reg_val = readl(priv->base + TACH_ASPEED_CTRL(channel)); in aspeed_tach_hwmon_write()
352 DIV_TO_REG(priv->tach_divisor)); in aspeed_tach_hwmon_write()
353 writel(reg_val, priv->base + TACH_ASPEED_CTRL(channel)); in aspeed_tach_hwmon_write()
356 return -EOPNOTSUPP; in aspeed_tach_hwmon_write()
368 if (!priv->tach_present[channel]) in aspeed_tach_dev_is_visible()
404 u8 ch, index; in aspeed_present_fan_tach() local
408 ch = tach_ch[index]; in aspeed_present_fan_tach()
409 priv->tach_present[ch] = true; in aspeed_present_fan_tach()
410 priv->tach_divisor = DEFAULT_TACH_DIV; in aspeed_present_fan_tach()
412 val = readl(priv->base + TACH_ASPEED_CTRL(ch)); in aspeed_present_fan_tach()
419 DIV_TO_REG(priv->tach_divisor)); in aspeed_present_fan_tach()
420 writel(val, priv->base + TACH_ASPEED_CTRL(ch)); in aspeed_present_fan_tach()
422 aspeed_tach_ch_enable(priv, ch, true); in aspeed_present_fan_tach()
433 count = of_property_count_u8_elems(child, "tach-ch"); in aspeed_create_fan_monitor()
435 return -EINVAL; in aspeed_create_fan_monitor()
438 return -ENOMEM; in aspeed_create_fan_monitor()
439 ret = of_property_read_u8_array(child, "tach-ch", tach_ch, count); in aspeed_create_fan_monitor()
457 struct device *dev = &pdev->dev, *hwmon; in aspeed_pwm_tach_probe()
464 return -ENOMEM; in aspeed_pwm_tach_probe()
465 priv->dev = dev; in aspeed_pwm_tach_probe()
466 priv->base = devm_platform_ioremap_resource(pdev, 0); in aspeed_pwm_tach_probe()
467 if (IS_ERR(priv->base)) in aspeed_pwm_tach_probe()
468 return PTR_ERR(priv->base); in aspeed_pwm_tach_probe()
470 priv->clk = devm_clk_get_enabled(dev, NULL); in aspeed_pwm_tach_probe()
471 if (IS_ERR(priv->clk)) in aspeed_pwm_tach_probe()
472 return dev_err_probe(dev, PTR_ERR(priv->clk), in aspeed_pwm_tach_probe()
474 priv->clk_rate = clk_get_rate(priv->clk); in aspeed_pwm_tach_probe()
475 priv->reset = devm_reset_control_get_exclusive(dev, NULL); in aspeed_pwm_tach_probe()
476 if (IS_ERR(priv->reset)) in aspeed_pwm_tach_probe()
477 return dev_err_probe(dev, PTR_ERR(priv->reset), in aspeed_pwm_tach_probe()
480 ret = reset_control_deassert(priv->reset); in aspeed_pwm_tach_probe()
485 priv->reset); in aspeed_pwm_tach_probe()
494 chip->ops = &aspeed_pwm_ops; in aspeed_pwm_tach_probe()
500 for_each_child_of_node_scoped(dev->of_node, child) { in aspeed_pwm_tach_probe()
515 of_platform_populate(dev->of_node, NULL, NULL, dev); in aspeed_pwm_tach_probe()
524 reset_control_assert(priv->reset); in aspeed_pwm_tach_remove()
529 .compatible = "aspeed,ast2600-pwm-tach",
539 .name = "aspeed-g6-pwm-tach",
547 MODULE_DESCRIPTION("Aspeed ast2600 PWM and Fan Tach device driver");