Lines Matching +full:fan +full:-
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2014-2018 Nuvoton Technology corporation.
7 #include <linux/hwmon-sysfs.h>
79 /* NPCM7XX FAN Tacho registers */
140 /* FAN General Definition */
141 /* Define the maximum FAN channel number */
147 * Get Fan Tach Timeout (base on clock 214843.75Hz, 1 cnt = 4.654us)
149 * (The minimum FAN speed could to support ~640RPM/pulse 1,
150 * 320RPM/pulse 2, ...-- 10.6Hz)
154 #define NPCM7XX_FAN_TCPA (NPCM7XX_FAN_TCNT - NPCM7XX_FAN_TIMEOUT)
155 #define NPCM7XX_FAN_TCPB (NPCM7XX_FAN_TCNT - NPCM7XX_FAN_TIMEOUT)
165 /* Obtain the fan number */
166 #define NPCM7XX_FAN_INPUT(fan, cmp) (((fan) << 1) + (cmp)) argument
168 /* fan sample status */
224 mutex_lock(&data->pwm_lock[module]); in npcm7xx_pwm_config_set()
227 iowrite32(val, NPCM7XX_PWM_REG_CMRx(data->pwm_base, module, pwm_ch)); in npcm7xx_pwm_config_set()
228 tmp_buf = ioread32(NPCM7XX_PWM_REG_CR(data->pwm_base, module)); in npcm7xx_pwm_config_set()
248 mutex_unlock(&data->pwm_lock[module]); in npcm7xx_pwm_config_set()
249 return -ENODEV; in npcm7xx_pwm_config_set()
262 iowrite32(tmp_buf, NPCM7XX_PWM_REG_CR(data->pwm_base, module)); in npcm7xx_pwm_config_set()
263 mutex_unlock(&data->pwm_lock[module]); in npcm7xx_pwm_config_set()
269 u8 fan, u8 cmp) in npcm7xx_fan_start_capture() argument
276 fan_id = NPCM7XX_FAN_INPUT(fan, cmp); in npcm7xx_fan_start_capture()
278 /* to check whether any fan tach is enable */ in npcm7xx_fan_start_capture()
279 if (data->fan_dev[fan_id].fan_st_flg != FAN_DISABLE) { in npcm7xx_fan_start_capture()
281 spin_lock_irqsave(&data->fan_lock[fan], flags); in npcm7xx_fan_start_capture()
283 data->fan_dev[fan_id].fan_st_flg = FAN_INIT; in npcm7xx_fan_start_capture()
284 reg_int = ioread8(NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_fan_start_capture()
296 NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_fan_start_capture()
299 | ioread8(NPCM7XX_FAN_REG_TCKC(data->fan_base, in npcm7xx_fan_start_capture()
300 fan)); in npcm7xx_fan_start_capture()
303 iowrite8(reg_mode, NPCM7XX_FAN_REG_TCKC(data->fan_base, in npcm7xx_fan_start_capture()
304 fan)); in npcm7xx_fan_start_capture()
309 NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_fan_start_capture()
313 | ioread8(NPCM7XX_FAN_REG_TCKC(data->fan_base, in npcm7xx_fan_start_capture()
314 fan)); in npcm7xx_fan_start_capture()
318 NPCM7XX_FAN_REG_TCKC(data->fan_base, fan)); in npcm7xx_fan_start_capture()
321 spin_unlock_irqrestore(&data->fan_lock[fan], flags); in npcm7xx_fan_start_capture()
326 * Enable a background timer to poll fan tach value, (200ms * 4)
327 * to polling all fan
340 for (i = data->fan_select; i < NPCM7XX_FAN_MAX_MODULE; in npcm7xx_fan_polling()
344 NPCM7XX_FAN_REG_TICLR(data->fan_base, i)); in npcm7xx_fan_polling()
346 if (data->fan_present[i * 2]) { in npcm7xx_fan_polling()
348 NPCM7XX_FAN_REG_TCNT1(data->fan_base, i)); in npcm7xx_fan_polling()
351 if (data->fan_present[(i * 2) + 1]) { in npcm7xx_fan_polling()
353 NPCM7XX_FAN_REG_TCNT2(data->fan_base, i)); in npcm7xx_fan_polling()
358 data->fan_select++; in npcm7xx_fan_polling()
359 data->fan_select &= 0x3; in npcm7xx_fan_polling()
362 data->fan_timer.expires = jiffies + in npcm7xx_fan_polling()
364 add_timer(&data->fan_timer); in npcm7xx_fan_polling()
368 u8 fan, u8 cmp, u8 fan_id, u8 flag_int, in npcm7xx_fan_compute() argument
376 fan_cap = ioread16(NPCM7XX_FAN_REG_TCRA(data->fan_base, fan)); in npcm7xx_fan_compute()
378 fan_cap = ioread16(NPCM7XX_FAN_REG_TCRB(data->fan_base, fan)); in npcm7xx_fan_compute()
381 iowrite8(flag_clear, NPCM7XX_FAN_REG_TICLR(data->fan_base, fan)); in npcm7xx_fan_compute()
383 if (data->fan_dev[fan_id].fan_st_flg == FAN_INIT) { in npcm7xx_fan_compute()
385 data->fan_dev[fan_id].fan_st_flg = in npcm7xx_fan_compute()
389 data->fan_dev[fan_id].fan_cnt_tmp = 0; in npcm7xx_fan_compute()
390 } else if (data->fan_dev[fan_id].fan_st_flg < FAN_ENOUGH_SAMPLE) { in npcm7xx_fan_compute()
393 * (ex: 2 pulse fan need to get 2 sample) in npcm7xx_fan_compute()
395 data->fan_dev[fan_id].fan_cnt_tmp += in npcm7xx_fan_compute()
396 (NPCM7XX_FAN_TCNT - fan_cap); in npcm7xx_fan_compute()
398 data->fan_dev[fan_id].fan_st_flg++; in npcm7xx_fan_compute()
400 /* get enough sample or fan disable */ in npcm7xx_fan_compute()
401 if (data->fan_dev[fan_id].fan_st_flg == FAN_ENOUGH_SAMPLE) { in npcm7xx_fan_compute()
402 data->fan_dev[fan_id].fan_cnt_tmp += in npcm7xx_fan_compute()
403 (NPCM7XX_FAN_TCNT - fan_cap); in npcm7xx_fan_compute()
406 data->fan_dev[fan_id].fan_cnt = in npcm7xx_fan_compute()
407 data->fan_dev[fan_id].fan_cnt_tmp / in npcm7xx_fan_compute()
410 data->fan_dev[fan_id].fan_st_flg = FAN_INIT; in npcm7xx_fan_compute()
413 reg_int = ioread8(NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_fan_compute()
417 NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_fan_compute()
418 reg_mode = ioread8(NPCM7XX_FAN_REG_TCKC(data->fan_base, fan)); in npcm7xx_fan_compute()
422 NPCM7XX_FAN_REG_TCKC(data->fan_base, fan)); in npcm7xx_fan_compute()
427 u8 fan, u8 cmp, u8 flag) in npcm7xx_check_cmp() argument
438 fan_id = NPCM7XX_FAN_INPUT(fan, cmp); in npcm7xx_check_cmp()
455 reg_int = ioread8(NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_check_cmp()
459 NPCM7XX_FAN_REG_TIEN(data->fan_base, fan)); in npcm7xx_check_cmp()
463 NPCM7XX_FAN_REG_TICLR(data->fan_base, fan)); in npcm7xx_check_cmp()
465 reg_mode = ioread8(NPCM7XX_FAN_REG_TCKC(data->fan_base, fan)); in npcm7xx_check_cmp()
469 NPCM7XX_FAN_REG_TCKC(data->fan_base, fan)); in npcm7xx_check_cmp()
472 * If timeout occurs (NPCM7XX_FAN_TIMEOUT), the fan doesn't in npcm7xx_check_cmp()
476 data->fan_dev[fan_id].fan_cnt = 0; in npcm7xx_check_cmp()
480 npcm7xx_fan_compute(data, fan, cmp, fan_id, flag_int, in npcm7xx_check_cmp()
492 module = irq - data->fan_irq[0]; in npcm7xx_fan_isr()
493 spin_lock_irqsave(&data->fan_lock[module], flags); in npcm7xx_fan_isr()
495 flag = ioread8(NPCM7XX_FAN_REG_TICTRL(data->fan_base, module)); in npcm7xx_fan_isr()
499 spin_unlock_irqrestore(&data->fan_lock[module], flags); in npcm7xx_fan_isr()
503 spin_unlock_irqrestore(&data->fan_lock[module], flags); in npcm7xx_fan_isr()
518 (NPCM7XX_PWM_REG_CMRx(data->pwm_base, module, pmw_ch)); in npcm7xx_read_pwm()
521 return -EOPNOTSUPP; in npcm7xx_read_pwm()
534 return -EINVAL; in npcm7xx_write_pwm()
538 err = -EOPNOTSUPP; in npcm7xx_write_pwm()
549 if (!data->pwm_present[channel] || channel >= data->info->pwm_max_channel) in npcm7xx_pwm_is_visible()
568 if (data->fan_dev[channel].fan_cnt <= 0) in npcm7xx_read_fan()
569 return data->fan_dev[channel].fan_cnt; in npcm7xx_read_fan()
572 if (data->fan_dev[channel].fan_cnt > 0 && in npcm7xx_read_fan()
573 data->fan_dev[channel].fan_pls_per_rev > 0) in npcm7xx_read_fan()
574 *val = ((data->input_clk_freq * 60) / in npcm7xx_read_fan()
575 (data->fan_dev[channel].fan_cnt * in npcm7xx_read_fan()
576 data->fan_dev[channel].fan_pls_per_rev)); in npcm7xx_read_fan()
579 return -EOPNOTSUPP; in npcm7xx_read_fan()
587 if (!data->fan_present[channel]) in npcm7xx_fan_is_visible()
607 return -EOPNOTSUPP; in npcm7xx_read()
618 return -EOPNOTSUPP; in npcm7xx_write()
650 HWMON_CHANNEL_INFO(fan,
695 pwm_clk_freq = clk_get_rate(data->pwm_clk); in npcm7xx_pwm_init()
708 prescale_val--; in npcm7xx_pwm_init()
713 for (m = 0; m < data->pwm_modules; m++) { in npcm7xx_pwm_init()
714 iowrite32(prescale_val, NPCM7XX_PWM_REG_PR(data->pwm_base, m)); in npcm7xx_pwm_init()
716 NPCM7XX_PWM_REG_CSR(data->pwm_base, m)); in npcm7xx_pwm_init()
718 NPCM7XX_PWM_REG_CR(data->pwm_base, m)); in npcm7xx_pwm_init()
722 NPCM7XX_PWM_REG_CNRx(data->pwm_base, m, ch)); in npcm7xx_pwm_init()
739 NPCM7XX_FAN_REG_TCKC(data->fan_base, md)); in npcm7xx_fan_init()
742 iowrite8(0x00, NPCM7XX_FAN_REG_TIEN(data->fan_base, md)); in npcm7xx_fan_init()
746 NPCM7XX_FAN_REG_TICLR(data->fan_base, md)); in npcm7xx_fan_init()
750 NPCM7XX_FAN_REG_TPRSC(data->fan_base, md)); in npcm7xx_fan_init()
752 /* set FAN0~7 mode (high-to-low transition) */ in npcm7xx_fan_init()
755 NPCM7XX_FAN_REG_TMCTRL(data->fan_base, md)); in npcm7xx_fan_init()
759 NPCM7XX_FAN_REG_TCNT1(data->fan_base, md)); in npcm7xx_fan_init()
761 NPCM7XX_FAN_REG_TCNT2(data->fan_base, md)); in npcm7xx_fan_init()
765 NPCM7XX_FAN_REG_TCPCFG(data->fan_base, md)); in npcm7xx_fan_init()
769 NPCM7XX_FAN_REG_TCPA(data->fan_base, md)); in npcm7xx_fan_init()
771 NPCM7XX_FAN_REG_TCPB(data->fan_base, md)); in npcm7xx_fan_init()
773 /* set FAN0~7 fan input FANIN 0~15 */ in npcm7xx_fan_init()
775 NPCM7XX_FAN_REG_TINASEL(data->fan_base, md)); in npcm7xx_fan_init()
777 NPCM7XX_FAN_REG_TINBSEL(data->fan_base, md)); in npcm7xx_fan_init()
781 data->fan_dev[ch].fan_st_flg = FAN_DISABLE; in npcm7xx_fan_init()
782 data->fan_dev[ch].fan_pls_per_rev = in npcm7xx_fan_init()
784 data->fan_dev[ch].fan_cnt = 0; in npcm7xx_fan_init()
788 apb_clk_freq = clk_get_rate(data->fan_clk); in npcm7xx_fan_init()
790 /* Fan tach input clock = APB clock / prescalar, default is 255. */ in npcm7xx_fan_init()
791 data->input_clk_freq = apb_clk_freq / (NPCM7XX_FAN_CLK_PRESCALE + 1); in npcm7xx_fan_init()
798 struct npcm7xx_cooling_device *cdev = tcdev->devdata; in npcm7xx_pwm_cz_get_max_state()
800 *state = cdev->max_state; in npcm7xx_pwm_cz_get_max_state()
809 struct npcm7xx_cooling_device *cdev = tcdev->devdata; in npcm7xx_pwm_cz_get_cur_state()
811 *state = cdev->cur_state; in npcm7xx_pwm_cz_get_cur_state()
820 struct npcm7xx_cooling_device *cdev = tcdev->devdata; in npcm7xx_pwm_cz_set_cur_state()
823 if (state > cdev->max_state) in npcm7xx_pwm_cz_set_cur_state()
824 return -EINVAL; in npcm7xx_pwm_cz_set_cur_state()
826 cdev->cur_state = state; in npcm7xx_pwm_cz_set_cur_state()
827 ret = npcm7xx_pwm_config_set(cdev->data, cdev->pwm_port, in npcm7xx_pwm_cz_set_cur_state()
828 cdev->cooling_levels[cdev->cur_state]); in npcm7xx_pwm_cz_set_cur_state()
849 return -ENOMEM; in npcm7xx_create_pwm_cooling()
851 cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL); in npcm7xx_create_pwm_cooling()
852 if (!cdev->cooling_levels) in npcm7xx_create_pwm_cooling()
853 return -ENOMEM; in npcm7xx_create_pwm_cooling()
855 cdev->max_state = num_levels - 1; in npcm7xx_create_pwm_cooling()
856 ret = of_property_read_u8_array(child, "cooling-levels", in npcm7xx_create_pwm_cooling()
857 cdev->cooling_levels, in npcm7xx_create_pwm_cooling()
860 dev_err(dev, "Property 'cooling-levels' cannot be read.\n"); in npcm7xx_create_pwm_cooling()
863 snprintf(cdev->name, THERMAL_NAME_LENGTH, "%pOFn%d", child, in npcm7xx_create_pwm_cooling()
866 cdev->tcdev = devm_thermal_of_cooling_device_register(dev, child, in npcm7xx_create_pwm_cooling()
867 cdev->name, cdev, &npcm7xx_pwm_cool_ops); in npcm7xx_create_pwm_cooling()
868 if (IS_ERR(cdev->tcdev)) in npcm7xx_create_pwm_cooling()
869 return PTR_ERR(cdev->tcdev); in npcm7xx_create_pwm_cooling()
871 cdev->data = data; in npcm7xx_create_pwm_cooling()
872 cdev->pwm_port = pwm_port; in npcm7xx_create_pwm_cooling()
874 data->cdev[pwm_port] = cdev; in npcm7xx_create_pwm_cooling()
892 data->pwm_present[pwm_port] = true; in npcm7xx_en_pwm_fan()
898 ret = of_property_count_u8_elems(child, "cooling-levels"); in npcm7xx_en_pwm_fan()
906 fan_cnt = of_property_count_u8_elems(child, "fan-tach-ch"); in npcm7xx_en_pwm_fan()
908 return -EINVAL; in npcm7xx_en_pwm_fan()
912 return -ENOMEM; in npcm7xx_en_pwm_fan()
914 ret = of_property_read_u8_array(child, "fan-tach-ch", fan_ch, fan_cnt); in npcm7xx_en_pwm_fan()
920 data->fan_present[index] = true; in npcm7xx_en_pwm_fan()
921 data->fan_dev[index].fan_st_flg = FAN_INIT; in npcm7xx_en_pwm_fan()
929 struct device *dev = &pdev->dev; in npcm7xx_pwm_fan_probe()
939 np = dev->of_node; in npcm7xx_pwm_fan_probe()
943 return -ENOMEM; in npcm7xx_pwm_fan_probe()
945 data->info = device_get_match_data(dev); in npcm7xx_pwm_fan_probe()
946 if (!data->info) in npcm7xx_pwm_fan_probe()
947 return -EINVAL; in npcm7xx_pwm_fan_probe()
949 data->pwm_modules = data->info->pwm_max_channel / NPCM7XX_PWM_MAX_CHN_NUM_IN_A_MODULE; in npcm7xx_pwm_fan_probe()
954 return -ENODEV; in npcm7xx_pwm_fan_probe()
957 data->pwm_base = devm_ioremap_resource(dev, res); in npcm7xx_pwm_fan_probe()
959 if (IS_ERR(data->pwm_base)) in npcm7xx_pwm_fan_probe()
960 return PTR_ERR(data->pwm_base); in npcm7xx_pwm_fan_probe()
962 data->pwm_clk = devm_clk_get(dev, "pwm"); in npcm7xx_pwm_fan_probe()
963 if (IS_ERR(data->pwm_clk)) { in npcm7xx_pwm_fan_probe()
965 return PTR_ERR(data->pwm_clk); in npcm7xx_pwm_fan_probe()
968 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fan"); in npcm7xx_pwm_fan_probe()
970 dev_err(dev, "fan resource not found\n"); in npcm7xx_pwm_fan_probe()
971 return -ENODEV; in npcm7xx_pwm_fan_probe()
974 data->fan_base = devm_ioremap_resource(dev, res); in npcm7xx_pwm_fan_probe()
975 dev_dbg(dev, "fan base resource is %pR\n", res); in npcm7xx_pwm_fan_probe()
976 if (IS_ERR(data->fan_base)) in npcm7xx_pwm_fan_probe()
977 return PTR_ERR(data->fan_base); in npcm7xx_pwm_fan_probe()
979 data->fan_clk = devm_clk_get(dev, "fan"); in npcm7xx_pwm_fan_probe()
980 if (IS_ERR(data->fan_clk)) { in npcm7xx_pwm_fan_probe()
981 dev_err(dev, "couldn't get fan clock\n"); in npcm7xx_pwm_fan_probe()
982 return PTR_ERR(data->fan_clk); in npcm7xx_pwm_fan_probe()
988 for (cnt = 0; cnt < data->pwm_modules; cnt++) in npcm7xx_pwm_fan_probe()
989 mutex_init(&data->pwm_lock[cnt]); in npcm7xx_pwm_fan_probe()
992 spin_lock_init(&data->fan_lock[i]); in npcm7xx_pwm_fan_probe()
994 data->fan_irq[i] = platform_get_irq(pdev, i); in npcm7xx_pwm_fan_probe()
995 if (data->fan_irq[i] < 0) in npcm7xx_pwm_fan_probe()
996 return data->fan_irq[i]; in npcm7xx_pwm_fan_probe()
998 sprintf(name, "NPCM7XX-FAN-MD%d", i); in npcm7xx_pwm_fan_probe()
999 ret = devm_request_irq(dev, data->fan_irq[i], npcm7xx_fan_isr, in npcm7xx_pwm_fan_probe()
1002 dev_err(dev, "register IRQ fan%d failed\n", i); in npcm7xx_pwm_fan_probe()
1010 dev_err(dev, "enable pwm and fan failed\n"); in npcm7xx_pwm_fan_probe()
1024 if (data->fan_present[i]) { in npcm7xx_pwm_fan_probe()
1025 /* fan timer initialization */ in npcm7xx_pwm_fan_probe()
1026 data->fan_timer.expires = jiffies + in npcm7xx_pwm_fan_probe()
1028 timer_setup(&data->fan_timer, in npcm7xx_pwm_fan_probe()
1030 add_timer(&data->fan_timer); in npcm7xx_pwm_fan_probe()
1035 pr_info("NPCM7XX PWM-FAN Driver probed, output Freq %dHz[PWM], input Freq %dHz[FAN]\n", in npcm7xx_pwm_fan_probe()
1036 output_freq, data->input_clk_freq); in npcm7xx_pwm_fan_probe()
1042 { .compatible = "nuvoton,npcm750-pwm-fan", .data = &npxm7xx_hwmon_info},
1043 { .compatible = "nuvoton,npcm845-pwm-fan", .data = &npxm8xx_hwmon_info},
1058 MODULE_DESCRIPTION("Nuvoton NPCM7XX PWM and Fan Tacho driver");