1*2d7a548aSJaghathiswari Rankappagounder Natarajan /* 2*2d7a548aSJaghathiswari Rankappagounder Natarajan * Copyright (c) 2016 Google, Inc 3*2d7a548aSJaghathiswari Rankappagounder Natarajan * 4*2d7a548aSJaghathiswari Rankappagounder Natarajan * This program is free software; you can redistribute it and/or modify 5*2d7a548aSJaghathiswari Rankappagounder Natarajan * it under the terms of the GNU General Public License version 2 or later as 6*2d7a548aSJaghathiswari Rankappagounder Natarajan * published by the Free Software Foundation. 7*2d7a548aSJaghathiswari Rankappagounder Natarajan */ 8*2d7a548aSJaghathiswari Rankappagounder Natarajan 9*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/clk.h> 10*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/gpio/consumer.h> 11*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/delay.h> 12*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/hwmon.h> 13*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/hwmon-sysfs.h> 14*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/io.h> 15*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/kernel.h> 16*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/module.h> 17*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/of_platform.h> 18*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/of_device.h> 19*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/platform_device.h> 20*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/sysfs.h> 21*2d7a548aSJaghathiswari Rankappagounder Natarajan #include <linux/regmap.h> 22*2d7a548aSJaghathiswari Rankappagounder Natarajan 23*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED PWM & FAN Tach Register Definition */ 24*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL 0x00 25*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL 0x04 26*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY0_CTRL 0x08 27*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY1_CTRL 0x0c 28*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEM_CTRL 0x10 29*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEM_CTRL1 0x14 30*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEN_CTRL 0x18 31*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEN_CTRL1 0x1c 32*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TACH_SOURCE 0x20 33*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TRIGGER 0x28 34*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_RESULT 0x2c 35*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_INTR_CTRL 0x30 36*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_INTR_STS 0x34 37*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEM_LIMIT 0x38 38*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEN_LIMIT 0x3C 39*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_EXT 0x40 40*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_EXT 0x44 41*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY2_CTRL 0x48 42*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_DUTY3_CTRL 0x4c 43*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEO_CTRL 0x50 44*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEO_CTRL1 0x54 45*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TACH_SOURCE_EXT 0x60 46*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_TYPEO_LIMIT 0x78 47*2d7a548aSJaghathiswari Rankappagounder Natarajan 48*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CTRL : 0x00 - General Control Register */ 49*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1 15 50*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2 6 51*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK (BIT(7) | BIT(15)) 52*2d7a548aSJaghathiswari Rankappagounder Natarajan 53*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1 14 54*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2 5 55*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK (BIT(6) | BIT(14)) 56*2d7a548aSJaghathiswari Rankappagounder Natarajan 57*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1 13 58*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2 4 59*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK (BIT(5) | BIT(13)) 60*2d7a548aSJaghathiswari Rankappagounder Natarajan 61*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1 12 62*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2 3 63*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK (BIT(4) | BIT(12)) 64*2d7a548aSJaghathiswari Rankappagounder Natarajan 65*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_FAN_NUM_EN(x) BIT(16 + (x)) 66*2d7a548aSJaghathiswari Rankappagounder Natarajan 67*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMD_EN BIT(11) 68*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMC_EN BIT(10) 69*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMB_EN BIT(9) 70*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMA_EN BIT(8) 71*2d7a548aSJaghathiswari Rankappagounder Natarajan 72*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_CLK_SRC BIT(1) 73*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_CLK_EN BIT(0) 74*2d7a548aSJaghathiswari Rankappagounder Natarajan 75*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CLK_CTRL : 0x04 - Clock Control Register */ 76*2d7a548aSJaghathiswari Rankappagounder Natarajan /* TYPE N */ 77*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_MASK GENMASK(31, 16) 78*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT 24 79*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_H 20 80*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEN_L 16 81*2d7a548aSJaghathiswari Rankappagounder Natarajan /* TYPE M */ 82*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_MASK GENMASK(15, 0) 83*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT 8 84*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_H 4 85*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEM_L 0 86*2d7a548aSJaghathiswari Rankappagounder Natarajan 87*2d7a548aSJaghathiswari Rankappagounder Natarajan /* 88*2d7a548aSJaghathiswari Rankappagounder Natarajan * ASPEED_PTCR_DUTY_CTRL/1/2/3 : 0x08/0x0C/0x48/0x4C - PWM-FAN duty control 89*2d7a548aSJaghathiswari Rankappagounder Natarajan * 0/1/2/3 register 90*2d7a548aSJaghathiswari Rankappagounder Natarajan */ 91*2d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM2_FALL_POINT 24 92*2d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM2_RISE_POINT 16 93*2d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM2_RISE_FALL_MASK GENMASK(31, 16) 94*2d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM1_FALL_POINT 8 95*2d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM1_RISE_POINT 0 96*2d7a548aSJaghathiswari Rankappagounder Natarajan #define DUTY_CTRL_PWM1_RISE_FALL_MASK GENMASK(15, 0) 97*2d7a548aSJaghathiswari Rankappagounder Natarajan 98*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_TYPEM_CTRL : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register */ 99*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_MASK (GENMASK(5, 1) | GENMASK(31, 16)) 100*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN1_MASK GENMASK(31, 0) 101*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_PERIOD 16 102*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_MODE 4 103*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_DIVISION 1 104*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TYPE_CTRL_FAN_TYPE_EN 1 105*2d7a548aSJaghathiswari Rankappagounder Natarajan 106*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register */ 107*2d7a548aSJaghathiswari Rankappagounder Natarajan /* bit [0,1] at 0x20, bit [2] at 0x60 */ 108*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_BIT01(x) ((x) * 2) 109*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_BIT2(x) ((x) * 2) 110*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3 << ((x) * 2)) 111*2d7a548aSJaghathiswari Rankappagounder Natarajan #define TACH_PWM_SOURCE_MASK_BIT2(x) BIT((x) * 2) 112*2d7a548aSJaghathiswari Rankappagounder Natarajan 113*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_RESULT : 0x2c - Result Register */ 114*2d7a548aSJaghathiswari Rankappagounder Natarajan #define RESULT_STATUS_MASK BIT(31) 115*2d7a548aSJaghathiswari Rankappagounder Natarajan #define RESULT_VALUE_MASK 0xfffff 116*2d7a548aSJaghathiswari Rankappagounder Natarajan 117*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */ 118*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1 15 119*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2 6 120*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK (BIT(7) | BIT(15)) 121*2d7a548aSJaghathiswari Rankappagounder Natarajan 122*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1 14 123*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2 5 124*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK (BIT(6) | BIT(14)) 125*2d7a548aSJaghathiswari Rankappagounder Natarajan 126*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1 13 127*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2 4 128*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK (BIT(5) | BIT(13)) 129*2d7a548aSJaghathiswari Rankappagounder Natarajan 130*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1 12 131*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2 3 132*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK (BIT(4) | BIT(12)) 133*2d7a548aSJaghathiswari Rankappagounder Natarajan 134*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMH_EN BIT(11) 135*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMG_EN BIT(10) 136*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWMF_EN BIT(9) 137*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CTRL_PWME_EN BIT(8) 138*2d7a548aSJaghathiswari Rankappagounder Natarajan 139*2d7a548aSJaghathiswari Rankappagounder Natarajan /* ASPEED_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */ 140*2d7a548aSJaghathiswari Rankappagounder Natarajan /* TYPE O */ 141*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0) 142*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8 143*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4 144*2d7a548aSJaghathiswari Rankappagounder Natarajan #define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0 145*2d7a548aSJaghathiswari Rankappagounder Natarajan 146*2d7a548aSJaghathiswari Rankappagounder Natarajan #define PWM_MAX 255 147*2d7a548aSJaghathiswari Rankappagounder Natarajan 148*2d7a548aSJaghathiswari Rankappagounder Natarajan #define M_PWM_DIV_H 0x00 149*2d7a548aSJaghathiswari Rankappagounder Natarajan #define M_PWM_DIV_L 0x05 150*2d7a548aSJaghathiswari Rankappagounder Natarajan #define M_PWM_PERIOD 0x5F 151*2d7a548aSJaghathiswari Rankappagounder Natarajan #define M_TACH_CLK_DIV 0x00 152*2d7a548aSJaghathiswari Rankappagounder Natarajan #define M_TACH_MODE 0x00 153*2d7a548aSJaghathiswari Rankappagounder Natarajan #define M_TACH_UNIT 0x1000 154*2d7a548aSJaghathiswari Rankappagounder Natarajan #define INIT_FAN_CTRL 0xFF 155*2d7a548aSJaghathiswari Rankappagounder Natarajan 156*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data { 157*2d7a548aSJaghathiswari Rankappagounder Natarajan struct regmap *regmap; 158*2d7a548aSJaghathiswari Rankappagounder Natarajan unsigned long clk_freq; 159*2d7a548aSJaghathiswari Rankappagounder Natarajan bool pwm_present[8]; 160*2d7a548aSJaghathiswari Rankappagounder Natarajan bool fan_tach_present[16]; 161*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_pwm_clock_unit[3]; 162*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_pwm_clock_division_h[3]; 163*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_pwm_clock_division_l[3]; 164*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 type_fan_tach_clock_division[3]; 165*2d7a548aSJaghathiswari Rankappagounder Natarajan u16 type_fan_tach_unit[3]; 166*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port_type[8]; 167*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port_fan_ctrl[8]; 168*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch_source[16]; 169*2d7a548aSJaghathiswari Rankappagounder Natarajan const struct attribute_group *groups[3]; 170*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 171*2d7a548aSJaghathiswari Rankappagounder Natarajan 172*2d7a548aSJaghathiswari Rankappagounder Natarajan enum type { TYPEM, TYPEN, TYPEO }; 173*2d7a548aSJaghathiswari Rankappagounder Natarajan 174*2d7a548aSJaghathiswari Rankappagounder Natarajan struct type_params { 175*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 l_value; 176*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 h_value; 177*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 unit_value; 178*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 clk_ctrl_mask; 179*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 clk_ctrl_reg; 180*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 ctrl_reg; 181*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 ctrl_reg1; 182*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 183*2d7a548aSJaghathiswari Rankappagounder Natarajan 184*2d7a548aSJaghathiswari Rankappagounder Natarajan static const struct type_params type_params[] = { 185*2d7a548aSJaghathiswari Rankappagounder Natarajan [TYPEM] = { 186*2d7a548aSJaghathiswari Rankappagounder Natarajan .l_value = ASPEED_PTCR_CLK_CTRL_TYPEM_L, 187*2d7a548aSJaghathiswari Rankappagounder Natarajan .h_value = ASPEED_PTCR_CLK_CTRL_TYPEM_H, 188*2d7a548aSJaghathiswari Rankappagounder Natarajan .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT, 189*2d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEM_MASK, 190*2d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL, 191*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_TYPEM_CTRL, 192*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg1 = ASPEED_PTCR_TYPEM_CTRL1, 193*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 194*2d7a548aSJaghathiswari Rankappagounder Natarajan [TYPEN] = { 195*2d7a548aSJaghathiswari Rankappagounder Natarajan .l_value = ASPEED_PTCR_CLK_CTRL_TYPEN_L, 196*2d7a548aSJaghathiswari Rankappagounder Natarajan .h_value = ASPEED_PTCR_CLK_CTRL_TYPEN_H, 197*2d7a548aSJaghathiswari Rankappagounder Natarajan .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT, 198*2d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEN_MASK, 199*2d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL, 200*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_TYPEN_CTRL, 201*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg1 = ASPEED_PTCR_TYPEN_CTRL1, 202*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 203*2d7a548aSJaghathiswari Rankappagounder Natarajan [TYPEO] = { 204*2d7a548aSJaghathiswari Rankappagounder Natarajan .l_value = ASPEED_PTCR_CLK_CTRL_TYPEO_L, 205*2d7a548aSJaghathiswari Rankappagounder Natarajan .h_value = ASPEED_PTCR_CLK_CTRL_TYPEO_H, 206*2d7a548aSJaghathiswari Rankappagounder Natarajan .unit_value = ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT, 207*2d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEO_MASK, 208*2d7a548aSJaghathiswari Rankappagounder Natarajan .clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL_EXT, 209*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_TYPEO_CTRL, 210*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg1 = ASPEED_PTCR_TYPEO_CTRL1, 211*2d7a548aSJaghathiswari Rankappagounder Natarajan } 212*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 213*2d7a548aSJaghathiswari Rankappagounder Natarajan 214*2d7a548aSJaghathiswari Rankappagounder Natarajan enum pwm_port { PWMA, PWMB, PWMC, PWMD, PWME, PWMF, PWMG, PWMH }; 215*2d7a548aSJaghathiswari Rankappagounder Natarajan 216*2d7a548aSJaghathiswari Rankappagounder Natarajan struct pwm_port_params { 217*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 pwm_en; 218*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 ctrl_reg; 219*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 type_part1; 220*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 type_part2; 221*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 type_mask; 222*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_rise_point; 223*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_fall_point; 224*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_reg; 225*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 duty_ctrl_rise_fall_mask; 226*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 227*2d7a548aSJaghathiswari Rankappagounder Natarajan 228*2d7a548aSJaghathiswari Rankappagounder Natarajan static const struct pwm_port_params pwm_port_params[] = { 229*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMA] = { 230*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMA_EN, 231*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 232*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1, 233*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2, 234*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK, 235*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 236*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 237*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL, 238*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 239*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 240*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMB] = { 241*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMB_EN, 242*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 243*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1, 244*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2, 245*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK, 246*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 247*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 248*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL, 249*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 250*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 251*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMC] = { 252*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMC_EN, 253*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 254*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1, 255*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2, 256*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK, 257*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 258*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 259*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL, 260*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 261*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 262*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMD] = { 263*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMD_EN, 264*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL, 265*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1, 266*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2, 267*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK, 268*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 269*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 270*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL, 271*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 272*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 273*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWME] = { 274*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWME_EN, 275*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 276*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1, 277*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2, 278*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK, 279*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 280*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 281*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL, 282*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 283*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 284*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMF] = { 285*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMF_EN, 286*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 287*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1, 288*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2, 289*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK, 290*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 291*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 292*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL, 293*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 294*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 295*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMG] = { 296*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMG_EN, 297*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 298*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1, 299*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2, 300*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK, 301*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT, 302*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT, 303*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL, 304*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK, 305*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 306*2d7a548aSJaghathiswari Rankappagounder Natarajan [PWMH] = { 307*2d7a548aSJaghathiswari Rankappagounder Natarajan .pwm_en = ASPEED_PTCR_CTRL_PWMH_EN, 308*2d7a548aSJaghathiswari Rankappagounder Natarajan .ctrl_reg = ASPEED_PTCR_CTRL_EXT, 309*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part1 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1, 310*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_part2 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2, 311*2d7a548aSJaghathiswari Rankappagounder Natarajan .type_mask = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK, 312*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT, 313*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT, 314*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL, 315*2d7a548aSJaghathiswari Rankappagounder Natarajan .duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK, 316*2d7a548aSJaghathiswari Rankappagounder Natarajan } 317*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 318*2d7a548aSJaghathiswari Rankappagounder Natarajan 319*2d7a548aSJaghathiswari Rankappagounder Natarajan static int regmap_aspeed_pwm_tacho_reg_write(void *context, unsigned int reg, 320*2d7a548aSJaghathiswari Rankappagounder Natarajan unsigned int val) 321*2d7a548aSJaghathiswari Rankappagounder Natarajan { 322*2d7a548aSJaghathiswari Rankappagounder Natarajan void __iomem *regs = (void __iomem *)context; 323*2d7a548aSJaghathiswari Rankappagounder Natarajan 324*2d7a548aSJaghathiswari Rankappagounder Natarajan writel(val, regs + reg); 325*2d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 326*2d7a548aSJaghathiswari Rankappagounder Natarajan } 327*2d7a548aSJaghathiswari Rankappagounder Natarajan 328*2d7a548aSJaghathiswari Rankappagounder Natarajan static int regmap_aspeed_pwm_tacho_reg_read(void *context, unsigned int reg, 329*2d7a548aSJaghathiswari Rankappagounder Natarajan unsigned int *val) 330*2d7a548aSJaghathiswari Rankappagounder Natarajan { 331*2d7a548aSJaghathiswari Rankappagounder Natarajan void __iomem *regs = (void __iomem *)context; 332*2d7a548aSJaghathiswari Rankappagounder Natarajan 333*2d7a548aSJaghathiswari Rankappagounder Natarajan *val = readl(regs + reg); 334*2d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 335*2d7a548aSJaghathiswari Rankappagounder Natarajan } 336*2d7a548aSJaghathiswari Rankappagounder Natarajan 337*2d7a548aSJaghathiswari Rankappagounder Natarajan static const struct regmap_config aspeed_pwm_tacho_regmap_config = { 338*2d7a548aSJaghathiswari Rankappagounder Natarajan .reg_bits = 32, 339*2d7a548aSJaghathiswari Rankappagounder Natarajan .val_bits = 32, 340*2d7a548aSJaghathiswari Rankappagounder Natarajan .reg_stride = 4, 341*2d7a548aSJaghathiswari Rankappagounder Natarajan .max_register = ASPEED_PTCR_TYPEO_LIMIT, 342*2d7a548aSJaghathiswari Rankappagounder Natarajan .reg_write = regmap_aspeed_pwm_tacho_reg_write, 343*2d7a548aSJaghathiswari Rankappagounder Natarajan .reg_read = regmap_aspeed_pwm_tacho_reg_read, 344*2d7a548aSJaghathiswari Rankappagounder Natarajan .fast_io = true, 345*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 346*2d7a548aSJaghathiswari Rankappagounder Natarajan 347*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_clock_enable(struct regmap *regmap, bool val) 348*2d7a548aSJaghathiswari Rankappagounder Natarajan { 349*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_CTRL, 350*2d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_CLK_EN, 351*2d7a548aSJaghathiswari Rankappagounder Natarajan val ? ASPEED_PTCR_CTRL_CLK_EN : 0); 352*2d7a548aSJaghathiswari Rankappagounder Natarajan } 353*2d7a548aSJaghathiswari Rankappagounder Natarajan 354*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_clock_source(struct regmap *regmap, int val) 355*2d7a548aSJaghathiswari Rankappagounder Natarajan { 356*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_CTRL, 357*2d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_CLK_SRC, 358*2d7a548aSJaghathiswari Rankappagounder Natarajan val ? ASPEED_PTCR_CTRL_CLK_SRC : 0); 359*2d7a548aSJaghathiswari Rankappagounder Natarajan } 360*2d7a548aSJaghathiswari Rankappagounder Natarajan 361*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_clock_values(struct regmap *regmap, u8 type, 362*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 div_high, u8 div_low, u8 unit) 363*2d7a548aSJaghathiswari Rankappagounder Natarajan { 364*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = ((div_high << type_params[type].h_value) | 365*2d7a548aSJaghathiswari Rankappagounder Natarajan (div_low << type_params[type].l_value) | 366*2d7a548aSJaghathiswari Rankappagounder Natarajan (unit << type_params[type].unit_value)); 367*2d7a548aSJaghathiswari Rankappagounder Natarajan 368*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].clk_ctrl_reg, 369*2d7a548aSJaghathiswari Rankappagounder Natarajan type_params[type].clk_ctrl_mask, reg_value); 370*2d7a548aSJaghathiswari Rankappagounder Natarajan } 371*2d7a548aSJaghathiswari Rankappagounder Natarajan 372*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_enable(struct regmap *regmap, u8 pwm_port, 373*2d7a548aSJaghathiswari Rankappagounder Natarajan bool enable) 374*2d7a548aSJaghathiswari Rankappagounder Natarajan { 375*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg, 376*2d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].pwm_en, 377*2d7a548aSJaghathiswari Rankappagounder Natarajan enable ? pwm_port_params[pwm_port].pwm_en : 0); 378*2d7a548aSJaghathiswari Rankappagounder Natarajan } 379*2d7a548aSJaghathiswari Rankappagounder Natarajan 380*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_type(struct regmap *regmap, 381*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port, u8 type) 382*2d7a548aSJaghathiswari Rankappagounder Natarajan { 383*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = (type & 0x1) << pwm_port_params[pwm_port].type_part1; 384*2d7a548aSJaghathiswari Rankappagounder Natarajan 385*2d7a548aSJaghathiswari Rankappagounder Natarajan reg_value |= (type & 0x2) << pwm_port_params[pwm_port].type_part2; 386*2d7a548aSJaghathiswari Rankappagounder Natarajan 387*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg, 388*2d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].type_mask, reg_value); 389*2d7a548aSJaghathiswari Rankappagounder Natarajan } 390*2d7a548aSJaghathiswari Rankappagounder Natarajan 391*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_duty_rising_falling(struct regmap *regmap, 392*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port, u8 rising, 393*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 falling) 394*2d7a548aSJaghathiswari Rankappagounder Natarajan { 395*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = (rising << 396*2d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].duty_ctrl_rise_point); 397*2d7a548aSJaghathiswari Rankappagounder Natarajan reg_value |= (falling << 398*2d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].duty_ctrl_fall_point); 399*2d7a548aSJaghathiswari Rankappagounder Natarajan 400*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, pwm_port_params[pwm_port].duty_ctrl_reg, 401*2d7a548aSJaghathiswari Rankappagounder Natarajan pwm_port_params[pwm_port].duty_ctrl_rise_fall_mask, 402*2d7a548aSJaghathiswari Rankappagounder Natarajan reg_value); 403*2d7a548aSJaghathiswari Rankappagounder Natarajan } 404*2d7a548aSJaghathiswari Rankappagounder Natarajan 405*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_tacho_type_enable(struct regmap *regmap, u8 type, 406*2d7a548aSJaghathiswari Rankappagounder Natarajan bool enable) 407*2d7a548aSJaghathiswari Rankappagounder Natarajan { 408*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].ctrl_reg, 409*2d7a548aSJaghathiswari Rankappagounder Natarajan TYPE_CTRL_FAN_TYPE_EN, 410*2d7a548aSJaghathiswari Rankappagounder Natarajan enable ? TYPE_CTRL_FAN_TYPE_EN : 0); 411*2d7a548aSJaghathiswari Rankappagounder Natarajan } 412*2d7a548aSJaghathiswari Rankappagounder Natarajan 413*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_tacho_type_values(struct regmap *regmap, u8 type, 414*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 mode, u16 unit, u8 division) 415*2d7a548aSJaghathiswari Rankappagounder Natarajan { 416*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value = ((mode << TYPE_CTRL_FAN_MODE) | 417*2d7a548aSJaghathiswari Rankappagounder Natarajan (unit << TYPE_CTRL_FAN_PERIOD) | 418*2d7a548aSJaghathiswari Rankappagounder Natarajan (division << TYPE_CTRL_FAN_DIVISION)); 419*2d7a548aSJaghathiswari Rankappagounder Natarajan 420*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].ctrl_reg, 421*2d7a548aSJaghathiswari Rankappagounder Natarajan TYPE_CTRL_FAN_MASK, reg_value); 422*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, type_params[type].ctrl_reg1, 423*2d7a548aSJaghathiswari Rankappagounder Natarajan TYPE_CTRL_FAN1_MASK, unit << 16); 424*2d7a548aSJaghathiswari Rankappagounder Natarajan } 425*2d7a548aSJaghathiswari Rankappagounder Natarajan 426*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_fan_tach_ch_enable(struct regmap *regmap, u8 fan_tach_ch, 427*2d7a548aSJaghathiswari Rankappagounder Natarajan bool enable) 428*2d7a548aSJaghathiswari Rankappagounder Natarajan { 429*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_CTRL, 430*2d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch), 431*2d7a548aSJaghathiswari Rankappagounder Natarajan enable ? 432*2d7a548aSJaghathiswari Rankappagounder Natarajan ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch) : 0); 433*2d7a548aSJaghathiswari Rankappagounder Natarajan } 434*2d7a548aSJaghathiswari Rankappagounder Natarajan 435*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_fan_tach_ch_source(struct regmap *regmap, u8 fan_tach_ch, 436*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch_source) 437*2d7a548aSJaghathiswari Rankappagounder Natarajan { 438*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value1 = ((fan_tach_ch_source & 0x3) << 439*2d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_BIT01(fan_tach_ch)); 440*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 reg_value2 = (((fan_tach_ch_source & 0x4) >> 2) << 441*2d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_BIT2(fan_tach_ch)); 442*2d7a548aSJaghathiswari Rankappagounder Natarajan 443*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE, 444*2d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_MASK_BIT01(fan_tach_ch), 445*2d7a548aSJaghathiswari Rankappagounder Natarajan reg_value1); 446*2d7a548aSJaghathiswari Rankappagounder Natarajan 447*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 448*2d7a548aSJaghathiswari Rankappagounder Natarajan TACH_PWM_SOURCE_MASK_BIT2(fan_tach_ch), 449*2d7a548aSJaghathiswari Rankappagounder Natarajan reg_value2); 450*2d7a548aSJaghathiswari Rankappagounder Natarajan } 451*2d7a548aSJaghathiswari Rankappagounder Natarajan 452*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_set_pwm_port_fan_ctrl(struct aspeed_pwm_tacho_data *priv, 453*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 index, u8 fan_ctrl) 454*2d7a548aSJaghathiswari Rankappagounder Natarajan { 455*2d7a548aSJaghathiswari Rankappagounder Natarajan u16 period, dc_time_on; 456*2d7a548aSJaghathiswari Rankappagounder Natarajan 457*2d7a548aSJaghathiswari Rankappagounder Natarajan period = priv->type_pwm_clock_unit[priv->pwm_port_type[index]]; 458*2d7a548aSJaghathiswari Rankappagounder Natarajan period += 1; 459*2d7a548aSJaghathiswari Rankappagounder Natarajan dc_time_on = (fan_ctrl * period) / PWM_MAX; 460*2d7a548aSJaghathiswari Rankappagounder Natarajan 461*2d7a548aSJaghathiswari Rankappagounder Natarajan if (dc_time_on == 0) { 462*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_enable(priv->regmap, index, false); 463*2d7a548aSJaghathiswari Rankappagounder Natarajan } else { 464*2d7a548aSJaghathiswari Rankappagounder Natarajan if (dc_time_on == period) 465*2d7a548aSJaghathiswari Rankappagounder Natarajan dc_time_on = 0; 466*2d7a548aSJaghathiswari Rankappagounder Natarajan 467*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_duty_rising_falling(priv->regmap, index, 0, 468*2d7a548aSJaghathiswari Rankappagounder Natarajan dc_time_on); 469*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_enable(priv->regmap, index, true); 470*2d7a548aSJaghathiswari Rankappagounder Natarajan } 471*2d7a548aSJaghathiswari Rankappagounder Natarajan } 472*2d7a548aSJaghathiswari Rankappagounder Natarajan 473*2d7a548aSJaghathiswari Rankappagounder Natarajan static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data 474*2d7a548aSJaghathiswari Rankappagounder Natarajan *priv, u8 type) 475*2d7a548aSJaghathiswari Rankappagounder Natarajan { 476*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 clk; 477*2d7a548aSJaghathiswari Rankappagounder Natarajan u16 tacho_unit; 478*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 clk_unit, div_h, div_l, tacho_div; 479*2d7a548aSJaghathiswari Rankappagounder Natarajan 480*2d7a548aSJaghathiswari Rankappagounder Natarajan clk = priv->clk_freq; 481*2d7a548aSJaghathiswari Rankappagounder Natarajan clk_unit = priv->type_pwm_clock_unit[type]; 482*2d7a548aSJaghathiswari Rankappagounder Natarajan div_h = priv->type_pwm_clock_division_h[type]; 483*2d7a548aSJaghathiswari Rankappagounder Natarajan div_h = 0x1 << div_h; 484*2d7a548aSJaghathiswari Rankappagounder Natarajan div_l = priv->type_pwm_clock_division_l[type]; 485*2d7a548aSJaghathiswari Rankappagounder Natarajan if (div_l == 0) 486*2d7a548aSJaghathiswari Rankappagounder Natarajan div_l = 1; 487*2d7a548aSJaghathiswari Rankappagounder Natarajan else 488*2d7a548aSJaghathiswari Rankappagounder Natarajan div_l = div_l * 2; 489*2d7a548aSJaghathiswari Rankappagounder Natarajan 490*2d7a548aSJaghathiswari Rankappagounder Natarajan tacho_unit = priv->type_fan_tach_unit[type]; 491*2d7a548aSJaghathiswari Rankappagounder Natarajan tacho_div = priv->type_fan_tach_clock_division[type]; 492*2d7a548aSJaghathiswari Rankappagounder Natarajan 493*2d7a548aSJaghathiswari Rankappagounder Natarajan tacho_div = 0x4 << (tacho_div * 2); 494*2d7a548aSJaghathiswari Rankappagounder Natarajan return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit); 495*2d7a548aSJaghathiswari Rankappagounder Natarajan } 496*2d7a548aSJaghathiswari Rankappagounder Natarajan 497*2d7a548aSJaghathiswari Rankappagounder Natarajan static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, 498*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch) 499*2d7a548aSJaghathiswari Rankappagounder Natarajan { 500*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 raw_data, tach_div, clk_source, sec, val; 501*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 fan_tach_ch_source, type; 502*2d7a548aSJaghathiswari Rankappagounder Natarajan 503*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); 504*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); 505*2d7a548aSJaghathiswari Rankappagounder Natarajan 506*2d7a548aSJaghathiswari Rankappagounder Natarajan fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch]; 507*2d7a548aSJaghathiswari Rankappagounder Natarajan type = priv->pwm_port_type[fan_tach_ch_source]; 508*2d7a548aSJaghathiswari Rankappagounder Natarajan 509*2d7a548aSJaghathiswari Rankappagounder Natarajan sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type)); 510*2d7a548aSJaghathiswari Rankappagounder Natarajan msleep(sec); 511*2d7a548aSJaghathiswari Rankappagounder Natarajan 512*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val); 513*2d7a548aSJaghathiswari Rankappagounder Natarajan raw_data = val & RESULT_VALUE_MASK; 514*2d7a548aSJaghathiswari Rankappagounder Natarajan tach_div = priv->type_fan_tach_clock_division[type]; 515*2d7a548aSJaghathiswari Rankappagounder Natarajan tach_div = 0x4 << (tach_div * 2); 516*2d7a548aSJaghathiswari Rankappagounder Natarajan clk_source = priv->clk_freq; 517*2d7a548aSJaghathiswari Rankappagounder Natarajan 518*2d7a548aSJaghathiswari Rankappagounder Natarajan if (raw_data == 0) 519*2d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 520*2d7a548aSJaghathiswari Rankappagounder Natarajan 521*2d7a548aSJaghathiswari Rankappagounder Natarajan return (clk_source * 60) / (2 * raw_data * tach_div); 522*2d7a548aSJaghathiswari Rankappagounder Natarajan } 523*2d7a548aSJaghathiswari Rankappagounder Natarajan 524*2d7a548aSJaghathiswari Rankappagounder Natarajan static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, 525*2d7a548aSJaghathiswari Rankappagounder Natarajan const char *buf, size_t count) 526*2d7a548aSJaghathiswari Rankappagounder Natarajan { 527*2d7a548aSJaghathiswari Rankappagounder Natarajan struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 528*2d7a548aSJaghathiswari Rankappagounder Natarajan int index = sensor_attr->index; 529*2d7a548aSJaghathiswari Rankappagounder Natarajan int ret; 530*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 531*2d7a548aSJaghathiswari Rankappagounder Natarajan long fan_ctrl; 532*2d7a548aSJaghathiswari Rankappagounder Natarajan 533*2d7a548aSJaghathiswari Rankappagounder Natarajan ret = kstrtol(buf, 10, &fan_ctrl); 534*2d7a548aSJaghathiswari Rankappagounder Natarajan if (ret != 0) 535*2d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 536*2d7a548aSJaghathiswari Rankappagounder Natarajan 537*2d7a548aSJaghathiswari Rankappagounder Natarajan if (fan_ctrl < 0 || fan_ctrl > PWM_MAX) 538*2d7a548aSJaghathiswari Rankappagounder Natarajan return -EINVAL; 539*2d7a548aSJaghathiswari Rankappagounder Natarajan 540*2d7a548aSJaghathiswari Rankappagounder Natarajan if (priv->pwm_port_fan_ctrl[index] == fan_ctrl) 541*2d7a548aSJaghathiswari Rankappagounder Natarajan return count; 542*2d7a548aSJaghathiswari Rankappagounder Natarajan 543*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_port_fan_ctrl[index] = fan_ctrl; 544*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_fan_ctrl(priv, index, fan_ctrl); 545*2d7a548aSJaghathiswari Rankappagounder Natarajan 546*2d7a548aSJaghathiswari Rankappagounder Natarajan return count; 547*2d7a548aSJaghathiswari Rankappagounder Natarajan } 548*2d7a548aSJaghathiswari Rankappagounder Natarajan 549*2d7a548aSJaghathiswari Rankappagounder Natarajan static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, 550*2d7a548aSJaghathiswari Rankappagounder Natarajan char *buf) 551*2d7a548aSJaghathiswari Rankappagounder Natarajan { 552*2d7a548aSJaghathiswari Rankappagounder Natarajan struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 553*2d7a548aSJaghathiswari Rankappagounder Natarajan int index = sensor_attr->index; 554*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 555*2d7a548aSJaghathiswari Rankappagounder Natarajan 556*2d7a548aSJaghathiswari Rankappagounder Natarajan return sprintf(buf, "%u\n", priv->pwm_port_fan_ctrl[index]); 557*2d7a548aSJaghathiswari Rankappagounder Natarajan } 558*2d7a548aSJaghathiswari Rankappagounder Natarajan 559*2d7a548aSJaghathiswari Rankappagounder Natarajan static ssize_t show_rpm(struct device *dev, struct device_attribute *attr, 560*2d7a548aSJaghathiswari Rankappagounder Natarajan char *buf) 561*2d7a548aSJaghathiswari Rankappagounder Natarajan { 562*2d7a548aSJaghathiswari Rankappagounder Natarajan struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); 563*2d7a548aSJaghathiswari Rankappagounder Natarajan int index = sensor_attr->index; 564*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 rpm; 565*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 566*2d7a548aSJaghathiswari Rankappagounder Natarajan 567*2d7a548aSJaghathiswari Rankappagounder Natarajan rpm = aspeed_get_fan_tach_ch_rpm(priv, index); 568*2d7a548aSJaghathiswari Rankappagounder Natarajan 569*2d7a548aSJaghathiswari Rankappagounder Natarajan return sprintf(buf, "%u\n", rpm); 570*2d7a548aSJaghathiswari Rankappagounder Natarajan } 571*2d7a548aSJaghathiswari Rankappagounder Natarajan 572*2d7a548aSJaghathiswari Rankappagounder Natarajan static umode_t pwm_is_visible(struct kobject *kobj, 573*2d7a548aSJaghathiswari Rankappagounder Natarajan struct attribute *a, int index) 574*2d7a548aSJaghathiswari Rankappagounder Natarajan { 575*2d7a548aSJaghathiswari Rankappagounder Natarajan struct device *dev = container_of(kobj, struct device, kobj); 576*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 577*2d7a548aSJaghathiswari Rankappagounder Natarajan 578*2d7a548aSJaghathiswari Rankappagounder Natarajan if (!priv->pwm_present[index]) 579*2d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 580*2d7a548aSJaghathiswari Rankappagounder Natarajan return a->mode; 581*2d7a548aSJaghathiswari Rankappagounder Natarajan } 582*2d7a548aSJaghathiswari Rankappagounder Natarajan 583*2d7a548aSJaghathiswari Rankappagounder Natarajan static umode_t fan_dev_is_visible(struct kobject *kobj, 584*2d7a548aSJaghathiswari Rankappagounder Natarajan struct attribute *a, int index) 585*2d7a548aSJaghathiswari Rankappagounder Natarajan { 586*2d7a548aSJaghathiswari Rankappagounder Natarajan struct device *dev = container_of(kobj, struct device, kobj); 587*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev); 588*2d7a548aSJaghathiswari Rankappagounder Natarajan 589*2d7a548aSJaghathiswari Rankappagounder Natarajan if (!priv->fan_tach_present[index]) 590*2d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 591*2d7a548aSJaghathiswari Rankappagounder Natarajan return a->mode; 592*2d7a548aSJaghathiswari Rankappagounder Natarajan } 593*2d7a548aSJaghathiswari Rankappagounder Natarajan 594*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm0, 0644, 595*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 0); 596*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm1, 0644, 597*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 1); 598*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm2, 0644, 599*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 2); 600*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm3, 0644, 601*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 3); 602*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm4, 0644, 603*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 4); 604*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm5, 0644, 605*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 5); 606*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm6, 0644, 607*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 6); 608*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(pwm7, 0644, 609*2d7a548aSJaghathiswari Rankappagounder Natarajan show_pwm, set_pwm, 7); 610*2d7a548aSJaghathiswari Rankappagounder Natarajan static struct attribute *pwm_dev_attrs[] = { 611*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm0.dev_attr.attr, 612*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm1.dev_attr.attr, 613*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm2.dev_attr.attr, 614*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm3.dev_attr.attr, 615*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm4.dev_attr.attr, 616*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm5.dev_attr.attr, 617*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm6.dev_attr.attr, 618*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_pwm7.dev_attr.attr, 619*2d7a548aSJaghathiswari Rankappagounder Natarajan NULL, 620*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 621*2d7a548aSJaghathiswari Rankappagounder Natarajan 622*2d7a548aSJaghathiswari Rankappagounder Natarajan static const struct attribute_group pwm_dev_group = { 623*2d7a548aSJaghathiswari Rankappagounder Natarajan .attrs = pwm_dev_attrs, 624*2d7a548aSJaghathiswari Rankappagounder Natarajan .is_visible = pwm_is_visible, 625*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 626*2d7a548aSJaghathiswari Rankappagounder Natarajan 627*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan0_input, 0444, 628*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 0); 629*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan1_input, 0444, 630*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 1); 631*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan2_input, 0444, 632*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 2); 633*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan3_input, 0444, 634*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 3); 635*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan4_input, 0444, 636*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 4); 637*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan5_input, 0444, 638*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 5); 639*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan6_input, 0444, 640*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 6); 641*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan7_input, 0444, 642*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 7); 643*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan8_input, 0444, 644*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 8); 645*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan9_input, 0444, 646*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 9); 647*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan10_input, 0444, 648*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 10); 649*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan11_input, 0444, 650*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 11); 651*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan12_input, 0444, 652*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 12); 653*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan13_input, 0444, 654*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 13); 655*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan14_input, 0444, 656*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 14); 657*2d7a548aSJaghathiswari Rankappagounder Natarajan static SENSOR_DEVICE_ATTR(fan15_input, 0444, 658*2d7a548aSJaghathiswari Rankappagounder Natarajan show_rpm, NULL, 15); 659*2d7a548aSJaghathiswari Rankappagounder Natarajan static struct attribute *fan_dev_attrs[] = { 660*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan0_input.dev_attr.attr, 661*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan1_input.dev_attr.attr, 662*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan2_input.dev_attr.attr, 663*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan3_input.dev_attr.attr, 664*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan4_input.dev_attr.attr, 665*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan5_input.dev_attr.attr, 666*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan6_input.dev_attr.attr, 667*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan7_input.dev_attr.attr, 668*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan8_input.dev_attr.attr, 669*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan9_input.dev_attr.attr, 670*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan10_input.dev_attr.attr, 671*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan11_input.dev_attr.attr, 672*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan12_input.dev_attr.attr, 673*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan13_input.dev_attr.attr, 674*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan14_input.dev_attr.attr, 675*2d7a548aSJaghathiswari Rankappagounder Natarajan &sensor_dev_attr_fan15_input.dev_attr.attr, 676*2d7a548aSJaghathiswari Rankappagounder Natarajan NULL 677*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 678*2d7a548aSJaghathiswari Rankappagounder Natarajan 679*2d7a548aSJaghathiswari Rankappagounder Natarajan static const struct attribute_group fan_dev_group = { 680*2d7a548aSJaghathiswari Rankappagounder Natarajan .attrs = fan_dev_attrs, 681*2d7a548aSJaghathiswari Rankappagounder Natarajan .is_visible = fan_dev_is_visible, 682*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 683*2d7a548aSJaghathiswari Rankappagounder Natarajan 684*2d7a548aSJaghathiswari Rankappagounder Natarajan /* 685*2d7a548aSJaghathiswari Rankappagounder Natarajan * The clock type is type M : 686*2d7a548aSJaghathiswari Rankappagounder Natarajan * The PWM frequency = 24MHz / (type M clock division L bit * 687*2d7a548aSJaghathiswari Rankappagounder Natarajan * type M clock division H bit * (type M PWM period bit + 1)) 688*2d7a548aSJaghathiswari Rankappagounder Natarajan */ 689*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv) 690*2d7a548aSJaghathiswari Rankappagounder Natarajan { 691*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H; 692*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L; 693*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD; 694*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H, 695*2d7a548aSJaghathiswari Rankappagounder Natarajan M_PWM_DIV_L, M_PWM_PERIOD); 696*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true); 697*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV; 698*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT; 699*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE, 700*2d7a548aSJaghathiswari Rankappagounder Natarajan M_TACH_UNIT, M_TACH_CLK_DIV); 701*2d7a548aSJaghathiswari Rankappagounder Natarajan } 702*2d7a548aSJaghathiswari Rankappagounder Natarajan 703*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv, 704*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_port) 705*2d7a548aSJaghathiswari Rankappagounder Natarajan { 706*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true); 707*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_present[pwm_port] = true; 708*2d7a548aSJaghathiswari Rankappagounder Natarajan 709*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_port_type[pwm_port] = TYPEM; 710*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_type(priv->regmap, pwm_port, TYPEM); 711*2d7a548aSJaghathiswari Rankappagounder Natarajan 712*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->pwm_port_fan_ctrl[pwm_port] = INIT_FAN_CTRL; 713*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_pwm_port_fan_ctrl(priv, pwm_port, INIT_FAN_CTRL); 714*2d7a548aSJaghathiswari Rankappagounder Natarajan } 715*2d7a548aSJaghathiswari Rankappagounder Natarajan 716*2d7a548aSJaghathiswari Rankappagounder Natarajan static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv, 717*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 *fan_tach_ch, 718*2d7a548aSJaghathiswari Rankappagounder Natarajan int count, 719*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 pwm_source) 720*2d7a548aSJaghathiswari Rankappagounder Natarajan { 721*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 val, index; 722*2d7a548aSJaghathiswari Rankappagounder Natarajan 723*2d7a548aSJaghathiswari Rankappagounder Natarajan for (val = 0; val < count; val++) { 724*2d7a548aSJaghathiswari Rankappagounder Natarajan index = fan_tach_ch[val]; 725*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_fan_tach_ch_enable(priv->regmap, index, true); 726*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->fan_tach_present[index] = true; 727*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->fan_tach_ch_source[index] = pwm_source; 728*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_fan_tach_ch_source(priv->regmap, index, pwm_source); 729*2d7a548aSJaghathiswari Rankappagounder Natarajan } 730*2d7a548aSJaghathiswari Rankappagounder Natarajan } 731*2d7a548aSJaghathiswari Rankappagounder Natarajan 732*2d7a548aSJaghathiswari Rankappagounder Natarajan static int aspeed_create_fan(struct device *dev, 733*2d7a548aSJaghathiswari Rankappagounder Natarajan struct device_node *child, 734*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv) 735*2d7a548aSJaghathiswari Rankappagounder Natarajan { 736*2d7a548aSJaghathiswari Rankappagounder Natarajan u8 *fan_tach_ch; 737*2d7a548aSJaghathiswari Rankappagounder Natarajan u32 pwm_port; 738*2d7a548aSJaghathiswari Rankappagounder Natarajan int ret, count; 739*2d7a548aSJaghathiswari Rankappagounder Natarajan 740*2d7a548aSJaghathiswari Rankappagounder Natarajan ret = of_property_read_u32(child, "reg", &pwm_port); 741*2d7a548aSJaghathiswari Rankappagounder Natarajan if (ret) 742*2d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 743*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_create_pwm_port(priv, (u8)pwm_port); 744*2d7a548aSJaghathiswari Rankappagounder Natarajan 745*2d7a548aSJaghathiswari Rankappagounder Natarajan count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch"); 746*2d7a548aSJaghathiswari Rankappagounder Natarajan if (count < 1) 747*2d7a548aSJaghathiswari Rankappagounder Natarajan return -EINVAL; 748*2d7a548aSJaghathiswari Rankappagounder Natarajan fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count, 749*2d7a548aSJaghathiswari Rankappagounder Natarajan GFP_KERNEL); 750*2d7a548aSJaghathiswari Rankappagounder Natarajan if (!fan_tach_ch) 751*2d7a548aSJaghathiswari Rankappagounder Natarajan return -ENOMEM; 752*2d7a548aSJaghathiswari Rankappagounder Natarajan ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch", 753*2d7a548aSJaghathiswari Rankappagounder Natarajan fan_tach_ch, count); 754*2d7a548aSJaghathiswari Rankappagounder Natarajan if (ret) 755*2d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 756*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, pwm_port); 757*2d7a548aSJaghathiswari Rankappagounder Natarajan 758*2d7a548aSJaghathiswari Rankappagounder Natarajan return 0; 759*2d7a548aSJaghathiswari Rankappagounder Natarajan } 760*2d7a548aSJaghathiswari Rankappagounder Natarajan 761*2d7a548aSJaghathiswari Rankappagounder Natarajan static int aspeed_pwm_tacho_probe(struct platform_device *pdev) 762*2d7a548aSJaghathiswari Rankappagounder Natarajan { 763*2d7a548aSJaghathiswari Rankappagounder Natarajan struct device *dev = &pdev->dev; 764*2d7a548aSJaghathiswari Rankappagounder Natarajan struct device_node *np, *child; 765*2d7a548aSJaghathiswari Rankappagounder Natarajan struct aspeed_pwm_tacho_data *priv; 766*2d7a548aSJaghathiswari Rankappagounder Natarajan void __iomem *regs; 767*2d7a548aSJaghathiswari Rankappagounder Natarajan struct resource *res; 768*2d7a548aSJaghathiswari Rankappagounder Natarajan struct device *hwmon; 769*2d7a548aSJaghathiswari Rankappagounder Natarajan struct clk *clk; 770*2d7a548aSJaghathiswari Rankappagounder Natarajan int ret; 771*2d7a548aSJaghathiswari Rankappagounder Natarajan 772*2d7a548aSJaghathiswari Rankappagounder Natarajan np = dev->of_node; 773*2d7a548aSJaghathiswari Rankappagounder Natarajan 774*2d7a548aSJaghathiswari Rankappagounder Natarajan res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 775*2d7a548aSJaghathiswari Rankappagounder Natarajan if (!res) 776*2d7a548aSJaghathiswari Rankappagounder Natarajan return -ENOENT; 777*2d7a548aSJaghathiswari Rankappagounder Natarajan regs = devm_ioremap_resource(dev, res); 778*2d7a548aSJaghathiswari Rankappagounder Natarajan if (IS_ERR(regs)) 779*2d7a548aSJaghathiswari Rankappagounder Natarajan return PTR_ERR(regs); 780*2d7a548aSJaghathiswari Rankappagounder Natarajan priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 781*2d7a548aSJaghathiswari Rankappagounder Natarajan if (!priv) 782*2d7a548aSJaghathiswari Rankappagounder Natarajan return -ENOMEM; 783*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, 784*2d7a548aSJaghathiswari Rankappagounder Natarajan &aspeed_pwm_tacho_regmap_config); 785*2d7a548aSJaghathiswari Rankappagounder Natarajan if (IS_ERR(priv->regmap)) 786*2d7a548aSJaghathiswari Rankappagounder Natarajan return PTR_ERR(priv->regmap); 787*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE, 0); 788*2d7a548aSJaghathiswari Rankappagounder Natarajan regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 0); 789*2d7a548aSJaghathiswari Rankappagounder Natarajan 790*2d7a548aSJaghathiswari Rankappagounder Natarajan clk = devm_clk_get(dev, NULL); 791*2d7a548aSJaghathiswari Rankappagounder Natarajan if (IS_ERR(clk)) 792*2d7a548aSJaghathiswari Rankappagounder Natarajan return -ENODEV; 793*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->clk_freq = clk_get_rate(clk); 794*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_clock_enable(priv->regmap, true); 795*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_set_clock_source(priv->regmap, 0); 796*2d7a548aSJaghathiswari Rankappagounder Natarajan 797*2d7a548aSJaghathiswari Rankappagounder Natarajan aspeed_create_type(priv); 798*2d7a548aSJaghathiswari Rankappagounder Natarajan 799*2d7a548aSJaghathiswari Rankappagounder Natarajan for_each_child_of_node(np, child) { 800*2d7a548aSJaghathiswari Rankappagounder Natarajan ret = aspeed_create_fan(dev, child, priv); 801*2d7a548aSJaghathiswari Rankappagounder Natarajan of_node_put(child); 802*2d7a548aSJaghathiswari Rankappagounder Natarajan if (ret) 803*2d7a548aSJaghathiswari Rankappagounder Natarajan return ret; 804*2d7a548aSJaghathiswari Rankappagounder Natarajan } 805*2d7a548aSJaghathiswari Rankappagounder Natarajan of_node_put(np); 806*2d7a548aSJaghathiswari Rankappagounder Natarajan 807*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->groups[0] = &pwm_dev_group; 808*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->groups[1] = &fan_dev_group; 809*2d7a548aSJaghathiswari Rankappagounder Natarajan priv->groups[2] = NULL; 810*2d7a548aSJaghathiswari Rankappagounder Natarajan hwmon = devm_hwmon_device_register_with_groups(dev, 811*2d7a548aSJaghathiswari Rankappagounder Natarajan "aspeed_pwm_tacho", 812*2d7a548aSJaghathiswari Rankappagounder Natarajan priv, priv->groups); 813*2d7a548aSJaghathiswari Rankappagounder Natarajan return PTR_ERR_OR_ZERO(hwmon); 814*2d7a548aSJaghathiswari Rankappagounder Natarajan } 815*2d7a548aSJaghathiswari Rankappagounder Natarajan 816*2d7a548aSJaghathiswari Rankappagounder Natarajan static const struct of_device_id of_pwm_tacho_match_table[] = { 817*2d7a548aSJaghathiswari Rankappagounder Natarajan { .compatible = "aspeed,ast2400-pwm-tacho", }, 818*2d7a548aSJaghathiswari Rankappagounder Natarajan { .compatible = "aspeed,ast2500-pwm-tacho", }, 819*2d7a548aSJaghathiswari Rankappagounder Natarajan {}, 820*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 821*2d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_DEVICE_TABLE(of, of_pwm_tacho_match_table); 822*2d7a548aSJaghathiswari Rankappagounder Natarajan 823*2d7a548aSJaghathiswari Rankappagounder Natarajan static struct platform_driver aspeed_pwm_tacho_driver = { 824*2d7a548aSJaghathiswari Rankappagounder Natarajan .probe = aspeed_pwm_tacho_probe, 825*2d7a548aSJaghathiswari Rankappagounder Natarajan .driver = { 826*2d7a548aSJaghathiswari Rankappagounder Natarajan .name = "aspeed_pwm_tacho", 827*2d7a548aSJaghathiswari Rankappagounder Natarajan .of_match_table = of_pwm_tacho_match_table, 828*2d7a548aSJaghathiswari Rankappagounder Natarajan }, 829*2d7a548aSJaghathiswari Rankappagounder Natarajan }; 830*2d7a548aSJaghathiswari Rankappagounder Natarajan 831*2d7a548aSJaghathiswari Rankappagounder Natarajan module_platform_driver(aspeed_pwm_tacho_driver); 832*2d7a548aSJaghathiswari Rankappagounder Natarajan 833*2d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>"); 834*2d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_DESCRIPTION("ASPEED PWM and Fan Tacho device driver"); 835*2d7a548aSJaghathiswari Rankappagounder Natarajan MODULE_LICENSE("GPL"); 836