aspeed-pwm-tacho.c (95c4629d92d15d10e5f7c55bfb72583f96a91374) aspeed-pwm-tacho.c (1e276292bf25d288b645d3026f6c026ac9347061)
1/*
2 * Copyright (c) 2016 Google, Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 or later as
6 * published by the Free Software Foundation.
7 */
8

--- 132 unchanged lines hidden (view full) ---

141/* TYPE O */
142#define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0)
143#define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8
144#define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4
145#define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0
146
147#define PWM_MAX 255
148
1/*
2 * Copyright (c) 2016 Google, Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 or later as
6 * published by the Free Software Foundation.
7 */
8

--- 132 unchanged lines hidden (view full) ---

141/* TYPE O */
142#define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0)
143#define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8
144#define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4
145#define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0
146
147#define PWM_MAX 255
148
149#define BOTH_EDGES 0x02 /* 10b */
150
149#define M_PWM_DIV_H 0x00
150#define M_PWM_DIV_L 0x05
151#define M_PWM_PERIOD 0x5F
152#define M_TACH_CLK_DIV 0x00
151#define M_PWM_DIV_H 0x00
152#define M_PWM_DIV_L 0x05
153#define M_PWM_PERIOD 0x5F
154#define M_TACH_CLK_DIV 0x00
153#define M_TACH_MODE 0x00
155/*
156 * 5:4 Type N fan tach mode selection bit:
157 * 00: falling
158 * 01: rising
159 * 10: both
160 * 11: reserved.
161 */
162#define M_TACH_MODE 0x02 /* 10b */
154#define M_TACH_UNIT 0x1000
155#define INIT_FAN_CTRL 0xFF
156
157struct aspeed_pwm_tacho_data {
158 struct regmap *regmap;
159 unsigned long clk_freq;
160 bool pwm_present[8];
161 bool fan_tach_present[16];
162 u8 type_pwm_clock_unit[3];
163 u8 type_pwm_clock_division_h[3];
164 u8 type_pwm_clock_division_l[3];
165 u8 type_fan_tach_clock_division[3];
163#define M_TACH_UNIT 0x1000
164#define INIT_FAN_CTRL 0xFF
165
166struct aspeed_pwm_tacho_data {
167 struct regmap *regmap;
168 unsigned long clk_freq;
169 bool pwm_present[8];
170 bool fan_tach_present[16];
171 u8 type_pwm_clock_unit[3];
172 u8 type_pwm_clock_division_h[3];
173 u8 type_pwm_clock_division_l[3];
174 u8 type_fan_tach_clock_division[3];
175 u8 type_fan_tach_mode[3];
166 u16 type_fan_tach_unit[3];
167 u8 pwm_port_type[8];
168 u8 pwm_port_fan_ctrl[8];
169 u8 fan_tach_ch_source[16];
170 const struct attribute_group *groups[3];
171};
172
173enum type { TYPEM, TYPEN, TYPEO };

--- 320 unchanged lines hidden (view full) ---

494 tacho_div = 0x4 << (tacho_div * 2);
495 return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
496}
497
498static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
499 u8 fan_tach_ch)
500{
501 u32 raw_data, tach_div, clk_source, sec, val;
176 u16 type_fan_tach_unit[3];
177 u8 pwm_port_type[8];
178 u8 pwm_port_fan_ctrl[8];
179 u8 fan_tach_ch_source[16];
180 const struct attribute_group *groups[3];
181};
182
183enum type { TYPEM, TYPEN, TYPEO };

--- 320 unchanged lines hidden (view full) ---

504 tacho_div = 0x4 << (tacho_div * 2);
505 return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
506}
507
508static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
509 u8 fan_tach_ch)
510{
511 u32 raw_data, tach_div, clk_source, sec, val;
502 u8 fan_tach_ch_source, type;
512 u8 fan_tach_ch_source, type, mode, both;
503
504 regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
505 regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
506
507 fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch];
508 type = priv->pwm_port_type[fan_tach_ch_source];
509
510 sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type));
511 msleep(sec);
512
513 regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
514 if (!(val & RESULT_STATUS_MASK))
515 return -ETIMEDOUT;
516
517 raw_data = val & RESULT_VALUE_MASK;
518 tach_div = priv->type_fan_tach_clock_division[type];
513
514 regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
515 regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
516
517 fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch];
518 type = priv->pwm_port_type[fan_tach_ch_source];
519
520 sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type));
521 msleep(sec);
522
523 regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
524 if (!(val & RESULT_STATUS_MASK))
525 return -ETIMEDOUT;
526
527 raw_data = val & RESULT_VALUE_MASK;
528 tach_div = priv->type_fan_tach_clock_division[type];
519 tach_div = 0x4 << (tach_div * 2);
529 /*
530 * We need the mode to determine if the raw_data is double (from
531 * counting both edges).
532 */
533 mode = priv->type_fan_tach_mode[type];
534 both = (mode & BOTH_EDGES) ? 1 : 0;
535
536 tach_div = (0x4 << both) << (tach_div * 2);
520 clk_source = priv->clk_freq;
521
522 if (raw_data == 0)
523 return 0;
524
525 return (clk_source * 60) / (2 * raw_data * tach_div);
526}
527

--- 169 unchanged lines hidden (view full) ---

697 priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H;
698 priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L;
699 priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD;
700 aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H,
701 M_PWM_DIV_L, M_PWM_PERIOD);
702 aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true);
703 priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV;
704 priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT;
537 clk_source = priv->clk_freq;
538
539 if (raw_data == 0)
540 return 0;
541
542 return (clk_source * 60) / (2 * raw_data * tach_div);
543}
544

--- 169 unchanged lines hidden (view full) ---

714 priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H;
715 priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L;
716 priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD;
717 aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H,
718 M_PWM_DIV_L, M_PWM_PERIOD);
719 aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true);
720 priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV;
721 priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT;
722 priv->type_fan_tach_mode[TYPEM] = M_TACH_MODE;
705 aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE,
706 M_TACH_UNIT, M_TACH_CLK_DIV);
707}
708
709static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv,
710 u8 pwm_port)
711{
712 aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true);

--- 128 unchanged lines hidden ---
723 aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE,
724 M_TACH_UNIT, M_TACH_CLK_DIV);
725}
726
727static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv,
728 u8 pwm_port)
729{
730 aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true);

--- 128 unchanged lines hidden ---