12d7a548aSJaghathiswari Rankappagounder Natarajan /* 22d7a548aSJaghathiswari Rankappagounder Natarajan * Copyright (c) 2016 Google, Inc 32d7a548aSJaghathiswari Rankappagounder Natarajan * 42d7a548aSJaghathiswari Rankappagounder Natarajan * This program is free software; you can redistribute it and/or modify 52d7a548aSJaghathiswari Rankappagounder Natarajan * it under the terms of the GNU General Public License version 2 or later as 62d7a548aSJaghathiswari Rankappagounder Natarajan * published by the Free Software Foundation. 72d7a548aSJaghathiswari Rankappagounder Natarajan */ 82d7a548aSJaghathiswari Rankappagounder Natarajan 92d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/clk.h> 1054b943e6SJoel #include <linux/delay.h> 117ed1c5e5SPatrick Venture #include <linux/errno.h> 122d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/gpio/consumer.h> 132d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/hwmon.h> 142d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/hwmon-sysfs.h> 152d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/io.h> 162d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/kernel.h> 172d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/module.h> 182d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/of_device.h> 1954b943e6SJoel #include <linux/of_platform.h> 202d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/platform_device.h> 212d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/regmap.h> 2218c514ccSJoel #include <linux/reset.h> 2354b943e6SJoel #include <linux/sysfs.h> 24f198907dSMykola Kostenok #include <linux/thermal.h> 252d7a548aSJaghathiswari Rankappagounder Natarajan 262d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED PWM & FAN Tach Register Definition */ 272d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL 0x00 282d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL 0x04 292d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY0_CTRL 0x08 302d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY1_CTRL 0x0c 312d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEM_CTRL 0x10 322d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEM_CTRL1 0x14 332d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEN_CTRL 0x18 342d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEN_CTRL1 0x1c 352d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TACH_SOURCE 0x20 362d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TRIGGER 0x28 372d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_RESULT 0x2c 382d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_INTR_CTRL 0x30 392d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_INTR_STS 0x34 402d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEM_LIMIT 0x38 412d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEN_LIMIT 0x3C 422d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_EXT 0x40 432d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_EXT 0x44 442d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY2_CTRL 0x48 452d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY3_CTRL 0x4c 462d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEO_CTRL 0x50 472d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEO_CTRL1 0x54 482d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TACH_SOURCE_EXT 0x60 492d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEO_LIMIT 0x78 502d7a548aSJaghathiswari Rankappagounder Natarajan 512d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CTRL : 0x00 - General Control Register */ 522d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1 15 532d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2 6 542d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK (BIT(7) | BIT(15)) 552d7a548aSJaghathiswari Rankappagounder Natarajan 562d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1 14 572d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2 5 582d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK (BIT(6) | BIT(14)) 592d7a548aSJaghathiswari Rankappagounder Natarajan 602d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1 13 612d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2 4 622d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK (BIT(5) | BIT(13)) 632d7a548aSJaghathiswari Rankappagounder Natarajan 642d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1 12 652d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2 3 662d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK (BIT(4) | BIT(12)) 672d7a548aSJaghathiswari Rankappagounder Natarajan 682d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_FAN_NUM_EN(x) BIT(16 + (x)) 692d7a548aSJaghathiswari Rankappagounder Natarajan 702d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMD_EN BIT(11) 712d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMC_EN BIT(10) 722d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMB_EN BIT(9) 732d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMA_EN BIT(8) 742d7a548aSJaghathiswari Rankappagounder Natarajan 752d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_CLK_SRC BIT(1) 762d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_CLK_EN BIT(0) 772d7a548aSJaghathiswari Rankappagounder Natarajan 782d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CLK_CTRL : 0x04 - Clock Control Register */ 792d7a548aSJaghathiswari Rankappagounder Natarajan /* TYPE N */ 802d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_MASK GENMASK(31, 16) 812d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT 24 822d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_H 20 832d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_L 16 842d7a548aSJaghathiswari Rankappagounder Natarajan /* TYPE M */ 852d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_MASK GENMASK(15, 0) 862d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT 8 872d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_H 4 882d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_L 0 892d7a548aSJaghathiswari Rankappagounder Natarajan 902d7a548aSJaghathiswari Rankappagounder Natarajan /* 912d7a548aSJaghathiswari Rankappagounder Natarajan * ASPEED_PTCR_DUTY_CTRL/1/2/3 : 0x08/0x0C/0x48/0x4C - PWM-FAN duty control 922d7a548aSJaghathiswari Rankappagounder Natarajan * 0/1/2/3 register 932d7a548aSJaghathiswari Rankappagounder Natarajan */ 942d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM2_FALL_POINT 24 952d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM2_RISE_POINT 16 962d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM2_RISE_FALL_MASK GENMASK(31, 16) 972d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM1_FALL_POINT 8 982d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM1_RISE_POINT 0 992d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM1_RISE_FALL_MASK GENMASK(15, 0) 1002d7a548aSJaghathiswari Rankappagounder Natarajan 1012d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_TYPEM_CTRL : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register */ 1022d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_MASK (GENMASK(5, 1) | GENMASK(31, 16)) 1032d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN1_MASK GENMASK(31, 0) 1042d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_PERIOD 16 1052d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_MODE 4 1062d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_DIVISION 1 1072d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_TYPE_EN 1 1082d7a548aSJaghathiswari Rankappagounder Natarajan 1092d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register */ 1102d7a548aSJaghathiswari Rankappagounder Natarajan /* bit [0,1] at 0x20, bit [2] at 0x60 */ 1112d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_BIT01(x) ((x) * 2) 1122d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_BIT2(x) ((x) * 2) 1132d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3 << ((x) * 2)) 1142d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_MASK_BIT2(x) BIT((x) * 2) 1152d7a548aSJaghathiswari Rankappagounder Natarajan 1162d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_RESULT : 0x2c - Result Register */ 1172d7a548aSJaghathiswari Rankappagounder Natarajan #define RESULT_STATUS_MASK BIT(31) 1182d7a548aSJaghathiswari Rankappagounder Natarajan #define RESULT_VALUE_MASK 0xfffff 1192d7a548aSJaghathiswari Rankappagounder Natarajan 1202d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */ 1212d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1 15 1222d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2 6 1232d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK (BIT(7) | BIT(15)) 1242d7a548aSJaghathiswari Rankappagounder Natarajan 1252d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1 14 1262d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2 5 1272d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK (BIT(6) | BIT(14)) 1282d7a548aSJaghathiswari Rankappagounder Natarajan 1292d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1 13 1302d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2 4 1312d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK (BIT(5) | BIT(13)) 1322d7a548aSJaghathiswari Rankappagounder Natarajan 1332d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1 12 1342d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2 3 1352d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK (BIT(4) | BIT(12)) 1362d7a548aSJaghathiswari Rankappagounder Natarajan 1372d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMH_EN BIT(11) 1382d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMG_EN BIT(10) 1392d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMF_EN BIT(9) 1402d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWME_EN BIT(8) 1412d7a548aSJaghathiswari Rankappagounder Natarajan 1422d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */ 1432d7a548aSJaghathiswari Rankappagounder Natarajan /* TYPE O */ 1442d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0) 1452d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8 1462d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4 1472d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0 1482d7a548aSJaghathiswari Rankappagounder Natarajan 1492d7a548aSJaghathiswari Rankappagounder Natarajan #define PWM_MAX 255 1502d7a548aSJaghathiswari Rankappagounder Natarajan 1511e276292SPatrick Venture #define BOTH_EDGES 0x02 /* 10b */ 1521e276292SPatrick Venture 1532d7a548aSJaghathiswari Rankappagounder Natarajan #define M_PWM_DIV_H 0x00 1542d7a548aSJaghathiswari Rankappagounder Natarajan #define M_PWM_DIV_L 0x05 1552d7a548aSJaghathiswari Rankappagounder Natarajan #define M_PWM_PERIOD 0x5F 1562d7a548aSJaghathiswari Rankappagounder Natarajan #define M_TACH_CLK_DIV 0x00 1571e276292SPatrick Venture /* 1581e276292SPatrick Venture * 5:4 Type N fan tach mode selection bit: 1591e276292SPatrick Venture * 00: falling 1601e276292SPatrick Venture * 01: rising 1611e276292SPatrick Venture * 10: both 1621e276292SPatrick Venture * 11: reserved. 1631e276292SPatrick Venture */ 1641e276292SPatrick Venture #define M_TACH_MODE 0x02 /* 10b */ 165762b1e88SPatrick Venture #define M_TACH_UNIT 0x0210 1662d7a548aSJaghathiswari Rankappagounder Natarajan #define INIT_FAN_CTRL 0xFF 1672d7a548aSJaghathiswari Rankappagounder Natarajan 16844b41366SPatrick Venture /* How long we sleep in us while waiting for an RPM result. */ 16944b41366SPatrick Venture #define ASPEED_RPM_STATUS_SLEEP_USEC 500 17044b41366SPatrick Venture 171f198907dSMykola Kostenok #define MAX_CDEV_NAME_LEN 16 172f198907dSMykola Kostenok 173f198907dSMykola Kostenok struct aspeed_cooling_device { 174f198907dSMykola Kostenok char name[16]; 175f198907dSMykola Kostenok struct aspeed_pwm_tacho_data *priv; 176f198907dSMykola Kostenok struct thermal_cooling_device *tcdev; 177f198907dSMykola Kostenok int pwm_port; 178f198907dSMykola Kostenok u8 *cooling_levels; 179f198907dSMykola Kostenok u8 max_state; 180f198907dSMykola Kostenok u8 cur_state; 181f198907dSMykola Kostenok }; 182f198907dSMykola Kostenok 1832d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data { 1842d7a548aSJaghathiswari Rankappagounder Natarajan struct regmap *regmap; 18518c514ccSJoel struct reset_control *rst; 1862d7a548aSJaghathiswari Rankappagounder Natarajan unsigned long clk_freq; 1872d7a548aSJaghathiswari Rankappagounder Natarajan bool pwm_present[8]; 1882d7a548aSJaghathiswari Rankappagounder Natarajan bool fan_tach_present[16]; 1892d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_pwm_clock_unit[3]; 1902d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_pwm_clock_division_h[3]; 1912d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_pwm_clock_division_l[3]; 1922d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_fan_tach_clock_division[3]; 1931e276292SPatrick Venture u8 type_fan_tach_mode[3]; 1942d7a548aSJaghathiswari Rankappagounder Natarajan u16 type_fan_tach_unit[3]; 1952d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port_type[8]; 1962d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port_fan_ctrl[8]; 1972d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch_source[16]; 198f198907dSMykola Kostenok struct aspeed_cooling_device *cdev[8]; 1992d7a548aSJaghathiswari Rankappagounder Natarajan const struct attribute_group *groups[3]; 2002d7a548aSJaghathiswari Rankappagounder Natarajan }; 2012d7a548aSJaghathiswari Rankappagounder Natarajan 2022d7a548aSJaghathiswari Rankappagounder Natarajan enum type { TYPEM, TYPEN, TYPEO }; 2032d7a548aSJaghathiswari Rankappagounder Natarajan 2042d7a548aSJaghathiswari Rankappagounder Natarajan struct type_params { 2052d7a548aSJaghathiswari Rankappagounder Natarajan u32 l_value; 2062d7a548aSJaghathiswari Rankappagounder Natarajan u32 h_value; 2072d7a548aSJaghathiswari Rankappagounder Natarajan u32 unit_value; 2082d7a548aSJaghathiswari Rankappagounder Natarajan u32 clk_ctrl_mask; 2092d7a548aSJaghathiswari Rankappagounder Natarajan u32 clk_ctrl_reg; 2102d7a548aSJaghathiswari Rankappagounder Natarajan u32 ctrl_reg; 2112d7a548aSJaghathiswari Rankappagounder Natarajan u32 ctrl_reg1; 2122d7a548aSJaghathiswari Rankappagounder Natarajan }; 2132d7a548aSJaghathiswari Rankappagounder Natarajan 2142d7a548aSJaghathiswari Rankappagounder Natarajan static const struct type_params type_params[] = { 2152d7a548aSJaghathiswari Rankappagounder Natarajan [TYPEM] = { 2162d7a548aSJaghathiswari Rankappagounder Natarajan .l_value = ASPEED_PTCR_CLK_CTRL_TYPEM_L, 2172d7a548aSJaghathiswari Rankappagounder Natarajan .h_value = ASPEED_PTCR_CLK_CTRL_TYPEM_H, 2182d7a548aSJaghathiswari Rankappagounder Natarajan .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT, 2192d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEM_MASK, 2202d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL, 2212d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_TYPEM_CTRL, 2222d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg1 = ASPEED_PTCR_TYPEM_CTRL1, 2232d7a548aSJaghathiswari Rankappagounder Natarajan }, 2242d7a548aSJaghathiswari Rankappagounder Natarajan [TYPEN] = { 2252d7a548aSJaghathiswari Rankappagounder Natarajan .l_value = ASPEED_PTCR_CLK_CTRL_TYPEN_L, 2262d7a548aSJaghathiswari Rankappagounder Natarajan .h_value = ASPEED_PTCR_CLK_CTRL_TYPEN_H, 2272d7a548aSJaghathiswari Rankappagounder Natarajan .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT, 2282d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEN_MASK, 2292d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL, 2302d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_TYPEN_CTRL, 2312d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg1 = ASPEED_PTCR_TYPEN_CTRL1, 2322d7a548aSJaghathiswari Rankappagounder Natarajan }, 2332d7a548aSJaghathiswari Rankappagounder Natarajan [TYPEO] = { 2342d7a548aSJaghathiswari Rankappagounder Natarajan .l_value = ASPEED_PTCR_CLK_CTRL_TYPEO_L, 2352d7a548aSJaghathiswari Rankappagounder Natarajan .h_value = ASPEED_PTCR_CLK_CTRL_TYPEO_H, 2362d7a548aSJaghathiswari Rankappagounder Natarajan .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT, 2372d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEO_MASK, 2382d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL_EXT, 2392d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_TYPEO_CTRL, 2402d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg1 = ASPEED_PTCR_TYPEO_CTRL1, 2412d7a548aSJaghathiswari Rankappagounder Natarajan } 2422d7a548aSJaghathiswari Rankappagounder Natarajan }; 2432d7a548aSJaghathiswari Rankappagounder Natarajan 2442d7a548aSJaghathiswari Rankappagounder Natarajan enum pwm_port { PWMA, PWMB, PWMC, PWMD, PWME, PWMF, PWMG, PWMH }; 2452d7a548aSJaghathiswari Rankappagounder Natarajan 2462d7a548aSJaghathiswari Rankappagounder Natarajan struct pwm_port_params { 2472d7a548aSJaghathiswari Rankappagounder Natarajan u32 pwm_en; 2482d7a548aSJaghathiswari Rankappagounder Natarajan u32 ctrl_reg; 2492d7a548aSJaghathiswari Rankappagounder Natarajan u32 type_part1; 2502d7a548aSJaghathiswari Rankappagounder Natarajan u32 type_part2; 2512d7a548aSJaghathiswari Rankappagounder Natarajan u32 type_mask; 2522d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_rise_point; 2532d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_fall_point; 2542d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_reg; 2552d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_rise_fall_mask; 2562d7a548aSJaghathiswari Rankappagounder Natarajan }; 2572d7a548aSJaghathiswari Rankappagounder Natarajan 2582d7a548aSJaghathiswari Rankappagounder Natarajan static const struct pwm_port_params pwm_port_params[] = { 2592d7a548aSJaghathiswari Rankappagounder Natarajan [PWMA] = { 2602d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMA_EN, 2612d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 2622d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1, 2632d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2, 2642d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK, 2652d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 2662d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 2672d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL, 2682d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 2692d7a548aSJaghathiswari Rankappagounder Natarajan }, 2702d7a548aSJaghathiswari Rankappagounder Natarajan [PWMB] = { 2712d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMB_EN, 2722d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 2732d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1, 2742d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2, 2752d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK, 2762d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 2772d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 2782d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL, 2792d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 2802d7a548aSJaghathiswari Rankappagounder Natarajan }, 2812d7a548aSJaghathiswari Rankappagounder Natarajan [PWMC] = { 2822d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMC_EN, 2832d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 2842d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1, 2852d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2, 2862d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK, 2872d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 2882d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 2892d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL, 2902d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 2912d7a548aSJaghathiswari Rankappagounder Natarajan }, 2922d7a548aSJaghathiswari Rankappagounder Natarajan [PWMD] = { 2932d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMD_EN, 2942d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 2952d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1, 2962d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2, 2972d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK, 2982d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 2992d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 3002d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL, 3012d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 3022d7a548aSJaghathiswari Rankappagounder Natarajan }, 3032d7a548aSJaghathiswari Rankappagounder Natarajan [PWME] = { 3042d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWME_EN, 3052d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 3062d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1, 3072d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2, 3082d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK, 3092d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 3102d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 3112d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL, 3122d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 3132d7a548aSJaghathiswari Rankappagounder Natarajan }, 3142d7a548aSJaghathiswari Rankappagounder Natarajan [PWMF] = { 3152d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMF_EN, 3162d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 3172d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1, 3182d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2, 3192d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK, 3202d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 3212d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 3222d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL, 3232d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 3242d7a548aSJaghathiswari Rankappagounder Natarajan }, 3252d7a548aSJaghathiswari Rankappagounder Natarajan [PWMG] = { 3262d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMG_EN, 3272d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 3282d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1, 3292d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2, 3302d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK, 3312d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 3322d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 3332d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL, 3342d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 3352d7a548aSJaghathiswari Rankappagounder Natarajan }, 3362d7a548aSJaghathiswari Rankappagounder Natarajan [PWMH] = { 3372d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMH_EN, 3382d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 3392d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1, 3402d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2, 3412d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK, 3422d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 3432d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 3442d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL, 3452d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 3462d7a548aSJaghathiswari Rankappagounder Natarajan } 3472d7a548aSJaghathiswari Rankappagounder Natarajan }; 3482d7a548aSJaghathiswari Rankappagounder Natarajan 3492d7a548aSJaghathiswari Rankappagounder Natarajan static int regmap_aspeed_pwm_tacho_reg_write(void *context, unsigned int reg, 3502d7a548aSJaghathiswari Rankappagounder Natarajan unsigned int val) 3512d7a548aSJaghathiswari Rankappagounder Natarajan { 3522d7a548aSJaghathiswari Rankappagounder Natarajan void __iomem *regs = (void __iomem *)context; 3532d7a548aSJaghathiswari Rankappagounder Natarajan 3542d7a548aSJaghathiswari Rankappagounder Natarajan writel(val, regs + reg); 3552d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 3562d7a548aSJaghathiswari Rankappagounder Natarajan } 3572d7a548aSJaghathiswari Rankappagounder Natarajan 3582d7a548aSJaghathiswari Rankappagounder Natarajan static int regmap_aspeed_pwm_tacho_reg_read(void *context, unsigned int reg, 3592d7a548aSJaghathiswari Rankappagounder Natarajan unsigned int *val) 3602d7a548aSJaghathiswari Rankappagounder Natarajan { 3612d7a548aSJaghathiswari Rankappagounder Natarajan void __iomem *regs = (void __iomem *)context; 3622d7a548aSJaghathiswari Rankappagounder Natarajan 3632d7a548aSJaghathiswari Rankappagounder Natarajan *val = readl(regs + reg); 3642d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 3652d7a548aSJaghathiswari Rankappagounder Natarajan } 3662d7a548aSJaghathiswari Rankappagounder Natarajan 3672d7a548aSJaghathiswari Rankappagounder Natarajan static const struct regmap_config aspeed_pwm_tacho_regmap_config = { 3682d7a548aSJaghathiswari Rankappagounder Natarajan .reg_bits = 32, 3692d7a548aSJaghathiswari Rankappagounder Natarajan .val_bits = 32, 3702d7a548aSJaghathiswari Rankappagounder Natarajan .reg_stride = 4, 3712d7a548aSJaghathiswari Rankappagounder Natarajan .max_register = ASPEED_PTCR_TYPEO_LIMIT, 3722d7a548aSJaghathiswari Rankappagounder Natarajan .reg_write = regmap_aspeed_pwm_tacho_reg_write, 3732d7a548aSJaghathiswari Rankappagounder Natarajan .reg_read = regmap_aspeed_pwm_tacho_reg_read, 3742d7a548aSJaghathiswari Rankappagounder Natarajan .fast_io = true, 3752d7a548aSJaghathiswari Rankappagounder Natarajan }; 3762d7a548aSJaghathiswari Rankappagounder Natarajan 3772d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_clock_enable(struct regmap *regmap, bool val) 3782d7a548aSJaghathiswari Rankappagounder Natarajan { 3792d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_CTRL, 3802d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_CLK_EN, 3812d7a548aSJaghathiswari Rankappagounder Natarajan val ? ASPEED_PTCR_CTRL_CLK_EN : 0); 3822d7a548aSJaghathiswari Rankappagounder Natarajan } 3832d7a548aSJaghathiswari Rankappagounder Natarajan 3842d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_clock_source(struct regmap *regmap, int val) 3852d7a548aSJaghathiswari Rankappagounder Natarajan { 3862d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_CTRL, 3872d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_CLK_SRC, 3882d7a548aSJaghathiswari Rankappagounder Natarajan val ? ASPEED_PTCR_CTRL_CLK_SRC : 0); 3892d7a548aSJaghathiswari Rankappagounder Natarajan } 3902d7a548aSJaghathiswari Rankappagounder Natarajan 3912d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_clock_values(struct regmap *regmap, u8 type, 3922d7a548aSJaghathiswari Rankappagounder Natarajan u8 div_high, u8 div_low, u8 unit) 3932d7a548aSJaghathiswari Rankappagounder Natarajan { 3942d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = ((div_high << type_params[type].h_value) | 3952d7a548aSJaghathiswari Rankappagounder Natarajan (div_low << type_params[type].l_value) | 3962d7a548aSJaghathiswari Rankappagounder Natarajan (unit << type_params[type].unit_value)); 3972d7a548aSJaghathiswari Rankappagounder Natarajan 3982d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].clk_ctrl_reg, 3992d7a548aSJaghathiswari Rankappagounder Natarajan type_params[type].clk_ctrl_mask, reg_value); 4002d7a548aSJaghathiswari Rankappagounder Natarajan } 4012d7a548aSJaghathiswari Rankappagounder Natarajan 4022d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_enable(struct regmap *regmap, u8 pwm_port, 4032d7a548aSJaghathiswari Rankappagounder Natarajan bool enable) 4042d7a548aSJaghathiswari Rankappagounder Natarajan { 4052d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg, 4062d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].pwm_en, 4072d7a548aSJaghathiswari Rankappagounder Natarajan enable ? pwm_port_params[pwm_port].pwm_en : 0); 4082d7a548aSJaghathiswari Rankappagounder Natarajan } 4092d7a548aSJaghathiswari Rankappagounder Natarajan 4102d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_type(struct regmap *regmap, 4112d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port, u8 type) 4122d7a548aSJaghathiswari Rankappagounder Natarajan { 4132d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = (type & 0x1) << pwm_port_params[pwm_port].type_part1; 4142d7a548aSJaghathiswari Rankappagounder Natarajan 4152d7a548aSJaghathiswari Rankappagounder Natarajan reg_value |= (type & 0x2) << pwm_port_params[pwm_port].type_part2; 4162d7a548aSJaghathiswari Rankappagounder Natarajan 4172d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg, 4182d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].type_mask, reg_value); 4192d7a548aSJaghathiswari Rankappagounder Natarajan } 4202d7a548aSJaghathiswari Rankappagounder Natarajan 4212d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_duty_rising_falling(struct regmap *regmap, 4222d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port, u8 rising, 4232d7a548aSJaghathiswari Rankappagounder Natarajan u8 falling) 4242d7a548aSJaghathiswari Rankappagounder Natarajan { 4252d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = (rising << 4262d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].duty_ctrl_rise_point); 4272d7a548aSJaghathiswari Rankappagounder Natarajan reg_value |= (falling << 4282d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].duty_ctrl_fall_point); 4292d7a548aSJaghathiswari Rankappagounder Natarajan 4302d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, pwm_port_params[pwm_port].duty_ctrl_reg, 4312d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].duty_ctrl_rise_fall_mask, 4322d7a548aSJaghathiswari Rankappagounder Natarajan reg_value); 4332d7a548aSJaghathiswari Rankappagounder Natarajan } 4342d7a548aSJaghathiswari Rankappagounder Natarajan 4352d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_tacho_type_enable(struct regmap *regmap, u8 type, 4362d7a548aSJaghathiswari Rankappagounder Natarajan bool enable) 4372d7a548aSJaghathiswari Rankappagounder Natarajan { 4382d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].ctrl_reg, 4392d7a548aSJaghathiswari Rankappagounder Natarajan TYPE_CTRL_FAN_TYPE_EN, 4402d7a548aSJaghathiswari Rankappagounder Natarajan enable ? TYPE_CTRL_FAN_TYPE_EN : 0); 4412d7a548aSJaghathiswari Rankappagounder Natarajan } 4422d7a548aSJaghathiswari Rankappagounder Natarajan 4432d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_tacho_type_values(struct regmap *regmap, u8 type, 4442d7a548aSJaghathiswari Rankappagounder Natarajan u8 mode, u16 unit, u8 division) 4452d7a548aSJaghathiswari Rankappagounder Natarajan { 4462d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = ((mode << TYPE_CTRL_FAN_MODE) | 4472d7a548aSJaghathiswari Rankappagounder Natarajan (unit << TYPE_CTRL_FAN_PERIOD) | 4482d7a548aSJaghathiswari Rankappagounder Natarajan (division << TYPE_CTRL_FAN_DIVISION)); 4492d7a548aSJaghathiswari Rankappagounder Natarajan 4502d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].ctrl_reg, 4512d7a548aSJaghathiswari Rankappagounder Natarajan TYPE_CTRL_FAN_MASK, reg_value); 4522d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].ctrl_reg1, 4532d7a548aSJaghathiswari Rankappagounder Natarajan TYPE_CTRL_FAN1_MASK, unit << 16); 4542d7a548aSJaghathiswari Rankappagounder Natarajan } 4552d7a548aSJaghathiswari Rankappagounder Natarajan 4562d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_fan_tach_ch_enable(struct regmap *regmap, u8 fan_tach_ch, 4572d7a548aSJaghathiswari Rankappagounder Natarajan bool enable) 4582d7a548aSJaghathiswari Rankappagounder Natarajan { 4592d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_CTRL, 4602d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch), 4612d7a548aSJaghathiswari Rankappagounder Natarajan enable ? 4622d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch) : 0); 4632d7a548aSJaghathiswari Rankappagounder Natarajan } 4642d7a548aSJaghathiswari Rankappagounder Natarajan 4652d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_fan_tach_ch_source(struct regmap *regmap, u8 fan_tach_ch, 4662d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch_source) 4672d7a548aSJaghathiswari Rankappagounder Natarajan { 4682d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value1 = ((fan_tach_ch_source & 0x3) << 4692d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_BIT01(fan_tach_ch)); 4702d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value2 = (((fan_tach_ch_source & 0x4) >> 2) << 4712d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_BIT2(fan_tach_ch)); 4722d7a548aSJaghathiswari Rankappagounder Natarajan 4732d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE, 4742d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_MASK_BIT01(fan_tach_ch), 4752d7a548aSJaghathiswari Rankappagounder Natarajan reg_value1); 4762d7a548aSJaghathiswari Rankappagounder Natarajan 4772d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 4782d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_MASK_BIT2(fan_tach_ch), 4792d7a548aSJaghathiswari Rankappagounder Natarajan reg_value2); 4802d7a548aSJaghathiswari Rankappagounder Natarajan } 4812d7a548aSJaghathiswari Rankappagounder Natarajan 4822d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_fan_ctrl(struct aspeed_pwm_tacho_data *priv, 4832d7a548aSJaghathiswari Rankappagounder Natarajan u8 index, u8 fan_ctrl) 4842d7a548aSJaghathiswari Rankappagounder Natarajan { 4852d7a548aSJaghathiswari Rankappagounder Natarajan u16 period, dc_time_on; 4862d7a548aSJaghathiswari Rankappagounder Natarajan 4872d7a548aSJaghathiswari Rankappagounder Natarajan period = priv->type_pwm_clock_unit[priv->pwm_port_type[index]]; 4882d7a548aSJaghathiswari Rankappagounder Natarajan period += 1; 4892d7a548aSJaghathiswari Rankappagounder Natarajan dc_time_on = (fan_ctrl * period) / PWM_MAX; 4902d7a548aSJaghathiswari Rankappagounder Natarajan 4912d7a548aSJaghathiswari Rankappagounder Natarajan if (dc_time_on == 0) { 4922d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_enable(priv->regmap, index, false); 4932d7a548aSJaghathiswari Rankappagounder Natarajan } else { 4942d7a548aSJaghathiswari Rankappagounder Natarajan if (dc_time_on == period) 4952d7a548aSJaghathiswari Rankappagounder Natarajan dc_time_on = 0; 4962d7a548aSJaghathiswari Rankappagounder Natarajan 4972d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_duty_rising_falling(priv->regmap, index, 0, 4982d7a548aSJaghathiswari Rankappagounder Natarajan dc_time_on); 4992d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_enable(priv->regmap, index, true); 5002d7a548aSJaghathiswari Rankappagounder Natarajan } 5012d7a548aSJaghathiswari Rankappagounder Natarajan } 5022d7a548aSJaghathiswari Rankappagounder Natarajan 5032d7a548aSJaghathiswari Rankappagounder Natarajan static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data 5042d7a548aSJaghathiswari Rankappagounder Natarajan *priv, u8 type) 5052d7a548aSJaghathiswari Rankappagounder Natarajan { 5062d7a548aSJaghathiswari Rankappagounder Natarajan u32 clk; 5072d7a548aSJaghathiswari Rankappagounder Natarajan u16 tacho_unit; 5082d7a548aSJaghathiswari Rankappagounder Natarajan u8 clk_unit, div_h, div_l, tacho_div; 5092d7a548aSJaghathiswari Rankappagounder Natarajan 5102d7a548aSJaghathiswari Rankappagounder Natarajan clk = priv->clk_freq; 5112d7a548aSJaghathiswari Rankappagounder Natarajan clk_unit = priv->type_pwm_clock_unit[type]; 5122d7a548aSJaghathiswari Rankappagounder Natarajan div_h = priv->type_pwm_clock_division_h[type]; 5132d7a548aSJaghathiswari Rankappagounder Natarajan div_h = 0x1 << div_h; 5142d7a548aSJaghathiswari Rankappagounder Natarajan div_l = priv->type_pwm_clock_division_l[type]; 5152d7a548aSJaghathiswari Rankappagounder Natarajan if (div_l == 0) 5162d7a548aSJaghathiswari Rankappagounder Natarajan div_l = 1; 5172d7a548aSJaghathiswari Rankappagounder Natarajan else 5182d7a548aSJaghathiswari Rankappagounder Natarajan div_l = div_l * 2; 5192d7a548aSJaghathiswari Rankappagounder Natarajan 5202d7a548aSJaghathiswari Rankappagounder Natarajan tacho_unit = priv->type_fan_tach_unit[type]; 5212d7a548aSJaghathiswari Rankappagounder Natarajan tacho_div = priv->type_fan_tach_clock_division[type]; 5222d7a548aSJaghathiswari Rankappagounder Natarajan 5232d7a548aSJaghathiswari Rankappagounder Natarajan tacho_div = 0x4 << (tacho_div * 2); 5242d7a548aSJaghathiswari Rankappagounder Natarajan return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit); 5252d7a548aSJaghathiswari Rankappagounder Natarajan } 5262d7a548aSJaghathiswari Rankappagounder Natarajan 5277ed1c5e5SPatrick Venture static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, 5282d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch) 5292d7a548aSJaghathiswari Rankappagounder Natarajan { 53044b41366SPatrick Venture u32 raw_data, tach_div, clk_source, msec, usec, val; 5311e276292SPatrick Venture u8 fan_tach_ch_source, type, mode, both; 53244b41366SPatrick Venture int ret; 5332d7a548aSJaghathiswari Rankappagounder Natarajan 5342d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); 5352d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); 5362d7a548aSJaghathiswari Rankappagounder Natarajan 5372d7a548aSJaghathiswari Rankappagounder Natarajan fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch]; 5382d7a548aSJaghathiswari Rankappagounder Natarajan type = priv->pwm_port_type[fan_tach_ch_source]; 5392d7a548aSJaghathiswari Rankappagounder Natarajan 54044b41366SPatrick Venture msec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type)); 54144b41366SPatrick Venture usec = msec * 1000; 5422d7a548aSJaghathiswari Rankappagounder Natarajan 54344b41366SPatrick Venture ret = regmap_read_poll_timeout( 54444b41366SPatrick Venture priv->regmap, 54544b41366SPatrick Venture ASPEED_PTCR_RESULT, 54644b41366SPatrick Venture val, 54744b41366SPatrick Venture (val & RESULT_STATUS_MASK), 54844b41366SPatrick Venture ASPEED_RPM_STATUS_SLEEP_USEC, 54944b41366SPatrick Venture usec); 55044b41366SPatrick Venture 55144b41366SPatrick Venture /* return -ETIMEDOUT if we didn't get an answer. */ 55244b41366SPatrick Venture if (ret) 55344b41366SPatrick Venture return ret; 5547ed1c5e5SPatrick Venture 5552d7a548aSJaghathiswari Rankappagounder Natarajan raw_data = val & RESULT_VALUE_MASK; 5562d7a548aSJaghathiswari Rankappagounder Natarajan tach_div = priv->type_fan_tach_clock_division[type]; 5571e276292SPatrick Venture /* 5581e276292SPatrick Venture * We need the mode to determine if the raw_data is double (from 5591e276292SPatrick Venture * counting both edges). 5601e276292SPatrick Venture */ 5611e276292SPatrick Venture mode = priv->type_fan_tach_mode[type]; 5621e276292SPatrick Venture both = (mode & BOTH_EDGES) ? 1 : 0; 5631e276292SPatrick Venture 5641e276292SPatrick Venture tach_div = (0x4 << both) << (tach_div * 2); 5652d7a548aSJaghathiswari Rankappagounder Natarajan clk_source = priv->clk_freq; 5662d7a548aSJaghathiswari Rankappagounder Natarajan 5672d7a548aSJaghathiswari Rankappagounder Natarajan if (raw_data == 0) 5682d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 5692d7a548aSJaghathiswari Rankappagounder Natarajan 5702d7a548aSJaghathiswari Rankappagounder Natarajan return (clk_source * 60) / (2 * raw_data * tach_div); 5712d7a548aSJaghathiswari Rankappagounder Natarajan } 5722d7a548aSJaghathiswari Rankappagounder Natarajan 5732d7a548aSJaghathiswari Rankappagounder Natarajan static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, 5742d7a548aSJaghathiswari Rankappagounder Natarajan const char *buf, size_t count) 5752d7a548aSJaghathiswari Rankappagounder Natarajan { 5762d7a548aSJaghathiswari Rankappagounder Natarajan struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 5772d7a548aSJaghathiswari Rankappagounder Natarajan int index = sensor_attr->index; 5782d7a548aSJaghathiswari Rankappagounder Natarajan int ret; 5792d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 5802d7a548aSJaghathiswari Rankappagounder Natarajan long fan_ctrl; 5812d7a548aSJaghathiswari Rankappagounder Natarajan 5822d7a548aSJaghathiswari Rankappagounder Natarajan ret = kstrtol(buf, 10, &fan_ctrl); 5832d7a548aSJaghathiswari Rankappagounder Natarajan if (ret != 0) 5842d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 5852d7a548aSJaghathiswari Rankappagounder Natarajan 5862d7a548aSJaghathiswari Rankappagounder Natarajan if (fan_ctrl < 0 || fan_ctrl > PWM_MAX) 5872d7a548aSJaghathiswari Rankappagounder Natarajan return -EINVAL; 5882d7a548aSJaghathiswari Rankappagounder Natarajan 5892d7a548aSJaghathiswari Rankappagounder Natarajan if (priv->pwm_port_fan_ctrl[index] == fan_ctrl) 5902d7a548aSJaghathiswari Rankappagounder Natarajan return count; 5912d7a548aSJaghathiswari Rankappagounder Natarajan 5922d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_port_fan_ctrl[index] = fan_ctrl; 5932d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_fan_ctrl(priv, index, fan_ctrl); 5942d7a548aSJaghathiswari Rankappagounder Natarajan 5952d7a548aSJaghathiswari Rankappagounder Natarajan return count; 5962d7a548aSJaghathiswari Rankappagounder Natarajan } 5972d7a548aSJaghathiswari Rankappagounder Natarajan 5982d7a548aSJaghathiswari Rankappagounder Natarajan static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, 5992d7a548aSJaghathiswari Rankappagounder Natarajan char *buf) 6002d7a548aSJaghathiswari Rankappagounder Natarajan { 6012d7a548aSJaghathiswari Rankappagounder Natarajan struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 6022d7a548aSJaghathiswari Rankappagounder Natarajan int index = sensor_attr->index; 6032d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 6042d7a548aSJaghathiswari Rankappagounder Natarajan 6052d7a548aSJaghathiswari Rankappagounder Natarajan return sprintf(buf, "%u\n", priv->pwm_port_fan_ctrl[index]); 6062d7a548aSJaghathiswari Rankappagounder Natarajan } 6072d7a548aSJaghathiswari Rankappagounder Natarajan 6082d7a548aSJaghathiswari Rankappagounder Natarajan static ssize_t show_rpm(struct device *dev, struct device_attribute *attr, 6092d7a548aSJaghathiswari Rankappagounder Natarajan char *buf) 6102d7a548aSJaghathiswari Rankappagounder Natarajan { 6112d7a548aSJaghathiswari Rankappagounder Natarajan struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 6122d7a548aSJaghathiswari Rankappagounder Natarajan int index = sensor_attr->index; 6137ed1c5e5SPatrick Venture int rpm; 6142d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 6152d7a548aSJaghathiswari Rankappagounder Natarajan 6162d7a548aSJaghathiswari Rankappagounder Natarajan rpm = aspeed_get_fan_tach_ch_rpm(priv, index); 6177ed1c5e5SPatrick Venture if (rpm < 0) 6187ed1c5e5SPatrick Venture return rpm; 6192d7a548aSJaghathiswari Rankappagounder Natarajan 6207ed1c5e5SPatrick Venture return sprintf(buf, "%d\n", rpm); 6212d7a548aSJaghathiswari Rankappagounder Natarajan } 6222d7a548aSJaghathiswari Rankappagounder Natarajan 6232d7a548aSJaghathiswari Rankappagounder Natarajan static umode_t pwm_is_visible(struct kobject *kobj, 6242d7a548aSJaghathiswari Rankappagounder Natarajan struct attribute *a, int index) 6252d7a548aSJaghathiswari Rankappagounder Natarajan { 6262d7a548aSJaghathiswari Rankappagounder Natarajan struct device *dev = container_of(kobj, struct device, kobj); 6272d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 6282d7a548aSJaghathiswari Rankappagounder Natarajan 6292d7a548aSJaghathiswari Rankappagounder Natarajan if (!priv->pwm_present[index]) 6302d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 6312d7a548aSJaghathiswari Rankappagounder Natarajan return a->mode; 6322d7a548aSJaghathiswari Rankappagounder Natarajan } 6332d7a548aSJaghathiswari Rankappagounder Natarajan 6342d7a548aSJaghathiswari Rankappagounder Natarajan static umode_t fan_dev_is_visible(struct kobject *kobj, 6352d7a548aSJaghathiswari Rankappagounder Natarajan struct attribute *a, int index) 6362d7a548aSJaghathiswari Rankappagounder Natarajan { 6372d7a548aSJaghathiswari Rankappagounder Natarajan struct device *dev = container_of(kobj, struct device, kobj); 6382d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 6392d7a548aSJaghathiswari Rankappagounder Natarajan 6402d7a548aSJaghathiswari Rankappagounder Natarajan if (!priv->fan_tach_present[index]) 6412d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 6422d7a548aSJaghathiswari Rankappagounder Natarajan return a->mode; 6432d7a548aSJaghathiswari Rankappagounder Natarajan } 6442d7a548aSJaghathiswari Rankappagounder Natarajan 6452d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm1, 0644, 6465f348fa3SStefan Schaeckeler show_pwm, set_pwm, 0); 6472d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm2, 0644, 6485f348fa3SStefan Schaeckeler show_pwm, set_pwm, 1); 6492d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm3, 0644, 6505f348fa3SStefan Schaeckeler show_pwm, set_pwm, 2); 6512d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm4, 0644, 6525f348fa3SStefan Schaeckeler show_pwm, set_pwm, 3); 6532d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm5, 0644, 6545f348fa3SStefan Schaeckeler show_pwm, set_pwm, 4); 6552d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm6, 0644, 6565f348fa3SStefan Schaeckeler show_pwm, set_pwm, 5); 6572d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm7, 0644, 6585f348fa3SStefan Schaeckeler show_pwm, set_pwm, 6); 6595f348fa3SStefan Schaeckeler static SENSOR_DEVICE_ATTR(pwm8, 0644, 6602d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 7); 6612d7a548aSJaghathiswari Rankappagounder Natarajan static struct attribute *pwm_dev_attrs[] = { 6622d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm1.dev_attr.attr, 6632d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm2.dev_attr.attr, 6642d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm3.dev_attr.attr, 6652d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm4.dev_attr.attr, 6662d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm5.dev_attr.attr, 6672d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm6.dev_attr.attr, 6682d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm7.dev_attr.attr, 6695f348fa3SStefan Schaeckeler &sensor_dev_attr_pwm8.dev_attr.attr, 6702d7a548aSJaghathiswari Rankappagounder Natarajan NULL, 6712d7a548aSJaghathiswari Rankappagounder Natarajan }; 6722d7a548aSJaghathiswari Rankappagounder Natarajan 6732d7a548aSJaghathiswari Rankappagounder Natarajan static const struct attribute_group pwm_dev_group = { 6742d7a548aSJaghathiswari Rankappagounder Natarajan .attrs = pwm_dev_attrs, 6752d7a548aSJaghathiswari Rankappagounder Natarajan .is_visible = pwm_is_visible, 6762d7a548aSJaghathiswari Rankappagounder Natarajan }; 6772d7a548aSJaghathiswari Rankappagounder Natarajan 6782d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan1_input, 0444, 6795f348fa3SStefan Schaeckeler show_rpm, NULL, 0); 6802d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan2_input, 0444, 6815f348fa3SStefan Schaeckeler show_rpm, NULL, 1); 6822d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan3_input, 0444, 6835f348fa3SStefan Schaeckeler show_rpm, NULL, 2); 6842d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan4_input, 0444, 6855f348fa3SStefan Schaeckeler show_rpm, NULL, 3); 6862d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan5_input, 0444, 6875f348fa3SStefan Schaeckeler show_rpm, NULL, 4); 6882d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan6_input, 0444, 6895f348fa3SStefan Schaeckeler show_rpm, NULL, 5); 6902d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan7_input, 0444, 6915f348fa3SStefan Schaeckeler show_rpm, NULL, 6); 6922d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan8_input, 0444, 6935f348fa3SStefan Schaeckeler show_rpm, NULL, 7); 6942d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan9_input, 0444, 6955f348fa3SStefan Schaeckeler show_rpm, NULL, 8); 6962d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan10_input, 0444, 6975f348fa3SStefan Schaeckeler show_rpm, NULL, 9); 6982d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan11_input, 0444, 6995f348fa3SStefan Schaeckeler show_rpm, NULL, 10); 7002d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan12_input, 0444, 7015f348fa3SStefan Schaeckeler show_rpm, NULL, 11); 7022d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan13_input, 0444, 7035f348fa3SStefan Schaeckeler show_rpm, NULL, 12); 7042d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan14_input, 0444, 7055f348fa3SStefan Schaeckeler show_rpm, NULL, 13); 7062d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan15_input, 0444, 7075f348fa3SStefan Schaeckeler show_rpm, NULL, 14); 7085f348fa3SStefan Schaeckeler static SENSOR_DEVICE_ATTR(fan16_input, 0444, 7092d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 15); 7102d7a548aSJaghathiswari Rankappagounder Natarajan static struct attribute *fan_dev_attrs[] = { 7112d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan1_input.dev_attr.attr, 7122d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan2_input.dev_attr.attr, 7132d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan3_input.dev_attr.attr, 7142d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan4_input.dev_attr.attr, 7152d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan5_input.dev_attr.attr, 7162d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan6_input.dev_attr.attr, 7172d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan7_input.dev_attr.attr, 7182d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan8_input.dev_attr.attr, 7192d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan9_input.dev_attr.attr, 7202d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan10_input.dev_attr.attr, 7212d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan11_input.dev_attr.attr, 7222d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan12_input.dev_attr.attr, 7232d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan13_input.dev_attr.attr, 7242d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan14_input.dev_attr.attr, 7252d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan15_input.dev_attr.attr, 7265f348fa3SStefan Schaeckeler &sensor_dev_attr_fan16_input.dev_attr.attr, 7272d7a548aSJaghathiswari Rankappagounder Natarajan NULL 7282d7a548aSJaghathiswari Rankappagounder Natarajan }; 7292d7a548aSJaghathiswari Rankappagounder Natarajan 7302d7a548aSJaghathiswari Rankappagounder Natarajan static const struct attribute_group fan_dev_group = { 7312d7a548aSJaghathiswari Rankappagounder Natarajan .attrs = fan_dev_attrs, 7322d7a548aSJaghathiswari Rankappagounder Natarajan .is_visible = fan_dev_is_visible, 7332d7a548aSJaghathiswari Rankappagounder Natarajan }; 7342d7a548aSJaghathiswari Rankappagounder Natarajan 7352d7a548aSJaghathiswari Rankappagounder Natarajan /* 7362d7a548aSJaghathiswari Rankappagounder Natarajan * The clock type is type M : 7372d7a548aSJaghathiswari Rankappagounder Natarajan * The PWM frequency = 24MHz / (type M clock division L bit * 7382d7a548aSJaghathiswari Rankappagounder Natarajan * type M clock division H bit * (type M PWM period bit + 1)) 7392d7a548aSJaghathiswari Rankappagounder Natarajan */ 7402d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv) 7412d7a548aSJaghathiswari Rankappagounder Natarajan { 7422d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H; 7432d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L; 7442d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD; 7452d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H, 7462d7a548aSJaghathiswari Rankappagounder Natarajan M_PWM_DIV_L, M_PWM_PERIOD); 7472d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true); 7482d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV; 7492d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT; 7501e276292SPatrick Venture priv->type_fan_tach_mode[TYPEM] = M_TACH_MODE; 7512d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE, 7522d7a548aSJaghathiswari Rankappagounder Natarajan M_TACH_UNIT, M_TACH_CLK_DIV); 7532d7a548aSJaghathiswari Rankappagounder Natarajan } 7542d7a548aSJaghathiswari Rankappagounder Natarajan 7552d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv, 7562d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port) 7572d7a548aSJaghathiswari Rankappagounder Natarajan { 7582d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true); 7592d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_present[pwm_port] = true; 7602d7a548aSJaghathiswari Rankappagounder Natarajan 7612d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_port_type[pwm_port] = TYPEM; 7622d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_type(priv->regmap, pwm_port, TYPEM); 7632d7a548aSJaghathiswari Rankappagounder Natarajan 7642d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_port_fan_ctrl[pwm_port] = INIT_FAN_CTRL; 7652d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_fan_ctrl(priv, pwm_port, INIT_FAN_CTRL); 7662d7a548aSJaghathiswari Rankappagounder Natarajan } 7672d7a548aSJaghathiswari Rankappagounder Natarajan 7682d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv, 7692d7a548aSJaghathiswari Rankappagounder Natarajan u8 *fan_tach_ch, 7702d7a548aSJaghathiswari Rankappagounder Natarajan int count, 7712d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_source) 7722d7a548aSJaghathiswari Rankappagounder Natarajan { 7732d7a548aSJaghathiswari Rankappagounder Natarajan u8 val, index; 7742d7a548aSJaghathiswari Rankappagounder Natarajan 7752d7a548aSJaghathiswari Rankappagounder Natarajan for (val = 0; val < count; val++) { 7762d7a548aSJaghathiswari Rankappagounder Natarajan index = fan_tach_ch[val]; 7772d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_fan_tach_ch_enable(priv->regmap, index, true); 7782d7a548aSJaghathiswari Rankappagounder Natarajan priv->fan_tach_present[index] = true; 7792d7a548aSJaghathiswari Rankappagounder Natarajan priv->fan_tach_ch_source[index] = pwm_source; 7802d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_fan_tach_ch_source(priv->regmap, index, pwm_source); 7812d7a548aSJaghathiswari Rankappagounder Natarajan } 7822d7a548aSJaghathiswari Rankappagounder Natarajan } 7832d7a548aSJaghathiswari Rankappagounder Natarajan 784f198907dSMykola Kostenok static int 785f198907dSMykola Kostenok aspeed_pwm_cz_get_max_state(struct thermal_cooling_device *tcdev, 786f198907dSMykola Kostenok unsigned long *state) 787f198907dSMykola Kostenok { 788f198907dSMykola Kostenok struct aspeed_cooling_device *cdev = tcdev->devdata; 789f198907dSMykola Kostenok 790f198907dSMykola Kostenok *state = cdev->max_state; 791f198907dSMykola Kostenok 792f198907dSMykola Kostenok return 0; 793f198907dSMykola Kostenok } 794f198907dSMykola Kostenok 795f198907dSMykola Kostenok static int 796f198907dSMykola Kostenok aspeed_pwm_cz_get_cur_state(struct thermal_cooling_device *tcdev, 797f198907dSMykola Kostenok unsigned long *state) 798f198907dSMykola Kostenok { 799f198907dSMykola Kostenok struct aspeed_cooling_device *cdev = tcdev->devdata; 800f198907dSMykola Kostenok 801f198907dSMykola Kostenok *state = cdev->cur_state; 802f198907dSMykola Kostenok 803f198907dSMykola Kostenok return 0; 804f198907dSMykola Kostenok } 805f198907dSMykola Kostenok 806f198907dSMykola Kostenok static int 807f198907dSMykola Kostenok aspeed_pwm_cz_set_cur_state(struct thermal_cooling_device *tcdev, 808f198907dSMykola Kostenok unsigned long state) 809f198907dSMykola Kostenok { 810f198907dSMykola Kostenok struct aspeed_cooling_device *cdev = tcdev->devdata; 811f198907dSMykola Kostenok 812f198907dSMykola Kostenok if (state > cdev->max_state) 813f198907dSMykola Kostenok return -EINVAL; 814f198907dSMykola Kostenok 815f198907dSMykola Kostenok cdev->cur_state = state; 816f198907dSMykola Kostenok cdev->priv->pwm_port_fan_ctrl[cdev->pwm_port] = 817f198907dSMykola Kostenok cdev->cooling_levels[cdev->cur_state]; 818f198907dSMykola Kostenok aspeed_set_pwm_port_fan_ctrl(cdev->priv, cdev->pwm_port, 819f198907dSMykola Kostenok cdev->cooling_levels[cdev->cur_state]); 820f198907dSMykola Kostenok 821f198907dSMykola Kostenok return 0; 822f198907dSMykola Kostenok } 823f198907dSMykola Kostenok 824f198907dSMykola Kostenok static const struct thermal_cooling_device_ops aspeed_pwm_cool_ops = { 825f198907dSMykola Kostenok .get_max_state = aspeed_pwm_cz_get_max_state, 826f198907dSMykola Kostenok .get_cur_state = aspeed_pwm_cz_get_cur_state, 827f198907dSMykola Kostenok .set_cur_state = aspeed_pwm_cz_set_cur_state, 828f198907dSMykola Kostenok }; 829f198907dSMykola Kostenok 830f198907dSMykola Kostenok static int aspeed_create_pwm_cooling(struct device *dev, 831f198907dSMykola Kostenok struct device_node *child, 832f198907dSMykola Kostenok struct aspeed_pwm_tacho_data *priv, 833f198907dSMykola Kostenok u32 pwm_port, u8 num_levels) 834f198907dSMykola Kostenok { 835f198907dSMykola Kostenok int ret; 836f198907dSMykola Kostenok struct aspeed_cooling_device *cdev; 837f198907dSMykola Kostenok 838f198907dSMykola Kostenok cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); 839f198907dSMykola Kostenok 840f198907dSMykola Kostenok if (!cdev) 841f198907dSMykola Kostenok return -ENOMEM; 842f198907dSMykola Kostenok 843f198907dSMykola Kostenok cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL); 844f198907dSMykola Kostenok if (!cdev->cooling_levels) 845f198907dSMykola Kostenok return -ENOMEM; 846f198907dSMykola Kostenok 847f198907dSMykola Kostenok cdev->max_state = num_levels - 1; 848f198907dSMykola Kostenok ret = of_property_read_u8_array(child, "cooling-levels", 849f198907dSMykola Kostenok cdev->cooling_levels, 850f198907dSMykola Kostenok num_levels); 851f198907dSMykola Kostenok if (ret) { 852f198907dSMykola Kostenok dev_err(dev, "Property 'cooling-levels' cannot be read.\n"); 853f198907dSMykola Kostenok return ret; 854f198907dSMykola Kostenok } 855f198907dSMykola Kostenok snprintf(cdev->name, MAX_CDEV_NAME_LEN, "%s%d", child->name, pwm_port); 856f198907dSMykola Kostenok 857f198907dSMykola Kostenok cdev->tcdev = thermal_of_cooling_device_register(child, 858f198907dSMykola Kostenok cdev->name, 859f198907dSMykola Kostenok cdev, 860f198907dSMykola Kostenok &aspeed_pwm_cool_ops); 861f198907dSMykola Kostenok if (IS_ERR(cdev->tcdev)) 862f198907dSMykola Kostenok return PTR_ERR(cdev->tcdev); 863f198907dSMykola Kostenok 864f198907dSMykola Kostenok cdev->priv = priv; 865f198907dSMykola Kostenok cdev->pwm_port = pwm_port; 866f198907dSMykola Kostenok 867f198907dSMykola Kostenok priv->cdev[pwm_port] = cdev; 868f198907dSMykola Kostenok 869f198907dSMykola Kostenok return 0; 870f198907dSMykola Kostenok } 871f198907dSMykola Kostenok 8722d7a548aSJaghathiswari Rankappagounder Natarajan static int aspeed_create_fan(struct device *dev, 8732d7a548aSJaghathiswari Rankappagounder Natarajan struct device_node *child, 8742d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv) 8752d7a548aSJaghathiswari Rankappagounder Natarajan { 8762d7a548aSJaghathiswari Rankappagounder Natarajan u8 *fan_tach_ch; 8772d7a548aSJaghathiswari Rankappagounder Natarajan u32 pwm_port; 8782d7a548aSJaghathiswari Rankappagounder Natarajan int ret, count; 8792d7a548aSJaghathiswari Rankappagounder Natarajan 8802d7a548aSJaghathiswari Rankappagounder Natarajan ret = of_property_read_u32(child, "reg", &pwm_port); 8812d7a548aSJaghathiswari Rankappagounder Natarajan if (ret) 8822d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 8832d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_create_pwm_port(priv, (u8)pwm_port); 8842d7a548aSJaghathiswari Rankappagounder Natarajan 885f198907dSMykola Kostenok ret = of_property_count_u8_elems(child, "cooling-levels"); 886f198907dSMykola Kostenok 887f198907dSMykola Kostenok if (ret > 0) { 888f198907dSMykola Kostenok ret = aspeed_create_pwm_cooling(dev, child, priv, pwm_port, 889f198907dSMykola Kostenok ret); 890f198907dSMykola Kostenok if (ret) 891f198907dSMykola Kostenok return ret; 892f198907dSMykola Kostenok } 893f198907dSMykola Kostenok 8942d7a548aSJaghathiswari Rankappagounder Natarajan count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); 8952d7a548aSJaghathiswari Rankappagounder Natarajan if (count < 1) 8962d7a548aSJaghathiswari Rankappagounder Natarajan return -EINVAL; 897*a86854d0SKees Cook fan_tach_ch = devm_kcalloc(dev, count, sizeof(*fan_tach_ch), 8982d7a548aSJaghathiswari Rankappagounder Natarajan GFP_KERNEL); 8992d7a548aSJaghathiswari Rankappagounder Natarajan if (!fan_tach_ch) 9002d7a548aSJaghathiswari Rankappagounder Natarajan return -ENOMEM; 9012d7a548aSJaghathiswari Rankappagounder Natarajan ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch", 9022d7a548aSJaghathiswari Rankappagounder Natarajan fan_tach_ch, count); 9032d7a548aSJaghathiswari Rankappagounder Natarajan if (ret) 9042d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 9052d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, pwm_port); 9062d7a548aSJaghathiswari Rankappagounder Natarajan 9072d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 9082d7a548aSJaghathiswari Rankappagounder Natarajan } 9092d7a548aSJaghathiswari Rankappagounder Natarajan 91018c514ccSJoel static void aspeed_pwm_tacho_remove(void *data) 91118c514ccSJoel { 91218c514ccSJoel struct aspeed_pwm_tacho_data *priv = data; 91318c514ccSJoel 91418c514ccSJoel reset_control_assert(priv->rst); 91518c514ccSJoel } 91618c514ccSJoel 9172d7a548aSJaghathiswari Rankappagounder Natarajan static int aspeed_pwm_tacho_probe(struct platform_device *pdev) 9182d7a548aSJaghathiswari Rankappagounder Natarajan { 9192d7a548aSJaghathiswari Rankappagounder Natarajan struct device *dev = &pdev->dev; 9202d7a548aSJaghathiswari Rankappagounder Natarajan struct device_node *np, *child; 9212d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv; 9222d7a548aSJaghathiswari Rankappagounder Natarajan void __iomem *regs; 9232d7a548aSJaghathiswari Rankappagounder Natarajan struct resource *res; 9242d7a548aSJaghathiswari Rankappagounder Natarajan struct device *hwmon; 9252d7a548aSJaghathiswari Rankappagounder Natarajan struct clk *clk; 9262d7a548aSJaghathiswari Rankappagounder Natarajan int ret; 9272d7a548aSJaghathiswari Rankappagounder Natarajan 9282d7a548aSJaghathiswari Rankappagounder Natarajan np = dev->of_node; 9292d7a548aSJaghathiswari Rankappagounder Natarajan 9302d7a548aSJaghathiswari Rankappagounder Natarajan res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 9312d7a548aSJaghathiswari Rankappagounder Natarajan if (!res) 9322d7a548aSJaghathiswari Rankappagounder Natarajan return -ENOENT; 9332d7a548aSJaghathiswari Rankappagounder Natarajan regs = devm_ioremap_resource(dev, res); 9342d7a548aSJaghathiswari Rankappagounder Natarajan if (IS_ERR(regs)) 9352d7a548aSJaghathiswari Rankappagounder Natarajan return PTR_ERR(regs); 9362d7a548aSJaghathiswari Rankappagounder Natarajan priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 9372d7a548aSJaghathiswari Rankappagounder Natarajan if (!priv) 9382d7a548aSJaghathiswari Rankappagounder Natarajan return -ENOMEM; 9392d7a548aSJaghathiswari Rankappagounder Natarajan priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, 9402d7a548aSJaghathiswari Rankappagounder Natarajan &aspeed_pwm_tacho_regmap_config); 9412d7a548aSJaghathiswari Rankappagounder Natarajan if (IS_ERR(priv->regmap)) 9422d7a548aSJaghathiswari Rankappagounder Natarajan return PTR_ERR(priv->regmap); 94318c514ccSJoel 94418c514ccSJoel priv->rst = devm_reset_control_get_exclusive(dev, NULL); 94518c514ccSJoel if (IS_ERR(priv->rst)) { 94618c514ccSJoel dev_err(dev, 94718c514ccSJoel "missing or invalid reset controller device tree entry"); 94818c514ccSJoel return PTR_ERR(priv->rst); 94918c514ccSJoel } 95018c514ccSJoel reset_control_deassert(priv->rst); 95118c514ccSJoel 95218c514ccSJoel ret = devm_add_action_or_reset(dev, aspeed_pwm_tacho_remove, priv); 95318c514ccSJoel if (ret) 95418c514ccSJoel return ret; 95518c514ccSJoel 9562d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE, 0); 9572d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 0); 9582d7a548aSJaghathiswari Rankappagounder Natarajan 9592d7a548aSJaghathiswari Rankappagounder Natarajan clk = devm_clk_get(dev, NULL); 9602d7a548aSJaghathiswari Rankappagounder Natarajan if (IS_ERR(clk)) 9612d7a548aSJaghathiswari Rankappagounder Natarajan return -ENODEV; 9622d7a548aSJaghathiswari Rankappagounder Natarajan priv->clk_freq = clk_get_rate(clk); 9632d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_clock_enable(priv->regmap, true); 9642d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_clock_source(priv->regmap, 0); 9652d7a548aSJaghathiswari Rankappagounder Natarajan 9662d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_create_type(priv); 9672d7a548aSJaghathiswari Rankappagounder Natarajan 9682d7a548aSJaghathiswari Rankappagounder Natarajan for_each_child_of_node(np, child) { 9692d7a548aSJaghathiswari Rankappagounder Natarajan ret = aspeed_create_fan(dev, child, priv); 970f198907dSMykola Kostenok if (ret) { 9712d7a548aSJaghathiswari Rankappagounder Natarajan of_node_put(child); 9722d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 9732d7a548aSJaghathiswari Rankappagounder Natarajan } 974f198907dSMykola Kostenok } 9752d7a548aSJaghathiswari Rankappagounder Natarajan 9762d7a548aSJaghathiswari Rankappagounder Natarajan priv->groups[0] = &pwm_dev_group; 9772d7a548aSJaghathiswari Rankappagounder Natarajan priv->groups[1] = &fan_dev_group; 9782d7a548aSJaghathiswari Rankappagounder Natarajan priv->groups[2] = NULL; 9792d7a548aSJaghathiswari Rankappagounder Natarajan hwmon = devm_hwmon_device_register_with_groups(dev, 9802d7a548aSJaghathiswari Rankappagounder Natarajan "aspeed_pwm_tacho", 9812d7a548aSJaghathiswari Rankappagounder Natarajan priv, priv->groups); 9822d7a548aSJaghathiswari Rankappagounder Natarajan return PTR_ERR_OR_ZERO(hwmon); 9832d7a548aSJaghathiswari Rankappagounder Natarajan } 9842d7a548aSJaghathiswari Rankappagounder Natarajan 9852d7a548aSJaghathiswari Rankappagounder Natarajan static const struct of_device_id of_pwm_tacho_match_table[] = { 9862d7a548aSJaghathiswari Rankappagounder Natarajan { .compatible = "aspeed,ast2400-pwm-tacho", }, 9872d7a548aSJaghathiswari Rankappagounder Natarajan { .compatible = "aspeed,ast2500-pwm-tacho", }, 9882d7a548aSJaghathiswari Rankappagounder Natarajan {}, 9892d7a548aSJaghathiswari Rankappagounder Natarajan }; 9902d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_DEVICE_TABLE(of, of_pwm_tacho_match_table); 9912d7a548aSJaghathiswari Rankappagounder Natarajan 9922d7a548aSJaghathiswari Rankappagounder Natarajan static struct platform_driver aspeed_pwm_tacho_driver = { 9932d7a548aSJaghathiswari Rankappagounder Natarajan .probe = aspeed_pwm_tacho_probe, 9942d7a548aSJaghathiswari Rankappagounder Natarajan .driver = { 9952d7a548aSJaghathiswari Rankappagounder Natarajan .name = "aspeed_pwm_tacho", 9962d7a548aSJaghathiswari Rankappagounder Natarajan .of_match_table = of_pwm_tacho_match_table, 9972d7a548aSJaghathiswari Rankappagounder Natarajan }, 9982d7a548aSJaghathiswari Rankappagounder Natarajan }; 9992d7a548aSJaghathiswari Rankappagounder Natarajan 10002d7a548aSJaghathiswari Rankappagounder Natarajan module_platform_driver(aspeed_pwm_tacho_driver); 10012d7a548aSJaghathiswari Rankappagounder Natarajan 10022d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>"); 10032d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_DESCRIPTION("ASPEED PWM and Fan Tacho device driver"); 10042d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_LICENSE("GPL"); 1005