1b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/*
2ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * amc6821.c - Part of lm_sensors, Linux kernel modules for hardware
3ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck *	       monitoring
4ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si>
5ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck *
6ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * Based on max6650.c:
7ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
8ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck *
9ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * This program is free software; you can redistribute it and/or modify
10ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * it under the terms of the GNU General Public License as published by
11ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * the Free Software Foundation; either version 2 of the License, or
12ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * (at your option) any later version.
13ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck *
14ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * This program is distributed in the hope that it will be useful,
15ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
16ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * GNU General Public License for more details.
18ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck *
19ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * You should have received a copy of the GNU General Public License
20ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * along with this program; if not, write to the Free Software
21ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck */
23b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
24b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/kernel.h>	/* Needed for KERN_INFO */
25b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/module.h>
26b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/init.h>
27b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/slab.h>
28b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/jiffies.h>
29b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/i2c.h>
30b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/hwmon.h>
31b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/hwmon-sysfs.h>
32b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/err.h>
33b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#include <linux/mutex.h>
34b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
35b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/*
36b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Addresses to scan.
37b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */
38b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
39b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
40b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	0x4c, 0x4d, 0x4e, I2C_CLIENT_END};
41b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
42b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/*
43b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Insmod parameters
44b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj */
45b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
46a6bee4a5571d24b9ba7c98f6becc7c45312a537dFrans Meulenbroeksstatic int pwminv;	/*Inverted PWM output. */
47b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljmodule_param(pwminv, int, S_IRUGO);
48b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
49b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int init = 1; /*Power-on initialization.*/
50b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljmodule_param(init, int, S_IRUGO);
51b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
52b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljenum chips { amc6821 };
53b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
54b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_DEV_ID 0x3D
55b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_COMP_ID 0x3E
56b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF1 0x00
57b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF2 0x01
58b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF3 0x3F
59b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_CONF4 0x04
60b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_STAT1 0x02
61b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_STAT2 0x03
62b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TDATA_LOW 0x08
63b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TDATA_HI 0x09
64b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_HI 0x0A
65b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_HI 0x0B
66b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15
67b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14
68b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19
69b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18
70b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_CRIT 0x1B
71b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_CRIT 0x1D
72b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_PSV_TEMP 0x1C
73b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_DCY 0x22
74b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_LTEMP_FAN_CTRL 0x24
75b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_RTEMP_FAN_CTRL 0x25
76b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_DCY_LOW_TEMP 0x21
77b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
78b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_LLIMITL 0x10
79b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_LLIMITH 0x11
80b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_HLIMITL 0x12
81b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_REG_TACH_HLIMITH 0x13
82b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
83b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_START 0x01
84b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FAN_INT_EN 0x02
85b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FANIE 0x04
86b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_PWMINV 0x08
87b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FAN_FAULT_EN 0x10
88b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FDRC0 0x20
89b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_FDRC1 0x40
90b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF1_THERMOVIE 0x80
91b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
92b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_PWM_EN 0x01
93b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_TACH_MODE 0x02
94b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_TACH_EN 0x04
95b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_RTFIE 0x08
96b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_LTOIE 0x10
97b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_RTOIE 0x20
98b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_PSVIE 0x40
99b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF2_RST 0x80
100b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
101b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF3_THERM_FAN_EN 0x80
102b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF3_REV_MASK 0x0F
103b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
104b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_OVREN 0x10
105b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_TACH_FAST 0x20
106b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_PSPR 0x40
107b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_CONF4_MODE 0x80
108b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
109b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RPM_ALARM 0x01
110b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_FANS 0x02
111b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RTH 0x04
112b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RTL 0x08
113b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_R_THERM 0x10
114b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_RTF 0x20
115b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_LTH 0x40
116b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT1_LTL 0x80
117b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
118b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_RTC 0x08
119b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_LTC 0x10
120b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_LPSV 0x20
121b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_L_THERM 0x40
122b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj#define AMC6821_STAT2_THERM_IN 0x80
123b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
124b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljenum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX,
125b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN,
126b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	IDX_TEMP2_MAX, IDX_TEMP2_CRIT,
127b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	TEMP_IDX_LEN, };
128b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
129b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI,
130b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_LTEMP_LIMIT_MIN,
131b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_LTEMP_LIMIT_MAX,
132b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_LTEMP_CRIT,
133b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_RTEMP_HI,
134b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_RTEMP_LIMIT_MIN,
135b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_RTEMP_LIMIT_MAX,
136b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_RTEMP_CRIT, };
137b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
138b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljenum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX,
139b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	FAN1_IDX_LEN, };
140b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
141b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW,
142b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_TACH_LLIMITL,
143b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_TACH_HLIMITL, };
144b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
145b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
146b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI,
147b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_TACH_LLIMITH,
148b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			AMC6821_REG_TACH_HLIMITH, };
149b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
150b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/*
151b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj * Client data (each client gets its own)
152ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck */
153b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
154b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstruct amc6821_data {
1551276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client;
156b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct mutex update_lock;
157b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	char valid; /* zero until following fields are valid */
158b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	unsigned long last_updated; /* in jiffies */
159b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
160b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	/* register values */
161b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int temp[TEMP_IDX_LEN];
162b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
163b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u16 fan[FAN1_IDX_LEN];
164b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 fan1_div;
165b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
166b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 pwm1;
167b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 temp1_auto_point_temp[3];
168b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 temp2_auto_point_temp[3];
169b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 pwm1_auto_point_pwm[3];
170b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 pwm1_enable;
171b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 pwm1_auto_channels_temp;
172b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
173b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 stat1;
174b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 stat2;
175b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj};
176b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
17728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Linstatic struct amc6821_data *amc6821_update_device(struct device *dev)
17828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin{
1791276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
1801276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
18128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	int timeout = HZ;
18228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	u8 reg;
18328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	int i;
18428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
18528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	mutex_lock(&data->update_lock);
18628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
18728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	if (time_after(jiffies, data->last_updated + timeout) ||
18828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			!data->valid) {
18928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
19028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		for (i = 0; i < TEMP_IDX_LEN; i++)
19128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->temp[i] = i2c_smbus_read_byte_data(client,
19228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				temp_reg[i]);
19328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
19428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->stat1 = i2c_smbus_read_byte_data(client,
19528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_STAT1);
19628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->stat2 = i2c_smbus_read_byte_data(client,
19728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_STAT2);
19828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
19928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->pwm1 = i2c_smbus_read_byte_data(client,
20028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_DCY);
20128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		for (i = 0; i < FAN1_IDX_LEN; i++) {
20228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->fan[i] = i2c_smbus_read_byte_data(
20328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin					client,
20428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin					fan_reg_low[i]);
20528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->fan[i] += i2c_smbus_read_byte_data(
20628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin					client,
20728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin					fan_reg_hi[i]) << 8;
20828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		}
20928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->fan1_div = i2c_smbus_read_byte_data(client,
21028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_CONF4);
21128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2;
21228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
21328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->pwm1_auto_point_pwm[0] = 0;
21428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->pwm1_auto_point_pwm[2] = 255;
21528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client,
21628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_DCY_LOW_TEMP);
21728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
21828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->temp1_auto_point_temp[0] =
21928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			i2c_smbus_read_byte_data(client,
22028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin					AMC6821_REG_PSV_TEMP);
22128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->temp2_auto_point_temp[0] =
22228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				data->temp1_auto_point_temp[0];
22328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg = i2c_smbus_read_byte_data(client,
22428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_LTEMP_FAN_CTRL);
22528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1;
22628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg &= 0x07;
22728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg = 0x20 >> reg;
22828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		if (reg > 0)
22928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->temp1_auto_point_temp[2] =
23028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				data->temp1_auto_point_temp[1] +
23128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				(data->pwm1_auto_point_pwm[2] -
23228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				data->pwm1_auto_point_pwm[1]) / reg;
23328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		else
23428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->temp1_auto_point_temp[2] = 255;
23528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
23628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg = i2c_smbus_read_byte_data(client,
23728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			AMC6821_REG_RTEMP_FAN_CTRL);
23828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1;
23928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg &= 0x07;
24028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg = 0x20 >> reg;
24128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		if (reg > 0)
24228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->temp2_auto_point_temp[2] =
24328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				data->temp2_auto_point_temp[1] +
24428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				(data->pwm1_auto_point_pwm[2] -
24528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin				data->pwm1_auto_point_pwm[1]) / reg;
24628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		else
24728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->temp2_auto_point_temp[2] = 255;
24828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
24928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
25028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		reg = (reg >> 5) & 0x3;
25128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		switch (reg) {
25228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		case 0: /*open loop: software sets pwm1*/
25328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_auto_channels_temp = 0;
25428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_enable = 1;
25528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			break;
25628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		case 2: /*closed loop: remote T (temp2)*/
25728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_auto_channels_temp = 2;
25828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_enable = 2;
25928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			break;
26028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		case 3: /*closed loop: local and remote T (temp2)*/
26128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_auto_channels_temp = 3;
26228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_enable = 3;
26328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			break;
26428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		case 1: /*
26528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			 * semi-open loop: software sets rpm, chip controls
26628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			 * pwm1, currently not implemented
26728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			 */
26828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_auto_channels_temp = 0;
26928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			data->pwm1_enable = 0;
27028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			break;
27128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		}
27228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
27328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->last_updated = jiffies;
27428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		data->valid = 1;
27528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	}
27628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	mutex_unlock(&data->update_lock);
27728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	return data;
27828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin}
279b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
280b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp(
281b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
282b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
283b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
284b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
285b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
286b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr(devattr)->index;
287b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
288b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", data->temp[ix] * 1000);
289b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
290b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
291b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_temp(
292b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
293b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *attr,
294b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf,
295b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		size_t count)
296b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
2971276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
2981276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
299b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr(attr)->index;
300b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
301b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
302179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int ret = kstrtol(buf, 10, &val);
303b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (ret)
304b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return ret;
3052a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	val = clamp_val(val / 1000, -128, 127);
306b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
307b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_lock(&data->update_lock);
308b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	data->temp[ix] = val;
309b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) {
310b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev, "Register write error, aborting.\n");
311b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
312b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
313b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
314b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
315b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
316b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
317b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp_alarm(
318b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct device *dev,
319b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct device_attribute *devattr,
320b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	char *buf)
321b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
322b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
323b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr(devattr)->index;
324b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 flag;
325b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
326b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	switch (ix) {
327b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case IDX_TEMP1_MIN:
328b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		flag = data->stat1 & AMC6821_STAT1_LTL;
329b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
330b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case IDX_TEMP1_MAX:
331b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		flag = data->stat1 & AMC6821_STAT1_LTH;
332b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
333b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case IDX_TEMP1_CRIT:
334b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		flag = data->stat2 & AMC6821_STAT2_LTC;
335b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
336b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case IDX_TEMP2_MIN:
337b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		flag = data->stat1 & AMC6821_STAT1_RTL;
338b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
339b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case IDX_TEMP2_MAX:
340b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		flag = data->stat1 & AMC6821_STAT1_RTH;
341b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
342b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case IDX_TEMP2_CRIT:
343b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		flag = data->stat2 & AMC6821_STAT2_RTC;
344b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
345b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	default:
346b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
347b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -EINVAL;
348b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
349b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (flag)
350b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "1");
351b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	else
352b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "0");
353b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
354b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
355b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp2_fault(
356b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
357b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
358b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
359b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
360b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
361b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (data->stat1 & AMC6821_STAT1_RTF)
362b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "1");
363b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	else
364b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "0");
365b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
366b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
367b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1(
368b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
369b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
370b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
371b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
372b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
373b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", data->pwm1);
374b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
375b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
376b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_pwm1(
377b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
378b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
379b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf,
380b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		size_t count)
381b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
3821276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
3831276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
384b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
385179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int ret = kstrtol(buf, 10, &val);
386b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (ret)
387b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return ret;
388b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
389b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_lock(&data->update_lock);
3902a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	data->pwm1 = clamp_val(val , 0, 255);
391b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1);
392b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
393b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
394b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
395b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
396b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1_enable(
397b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
398b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
399b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
400b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
401b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
402b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", data->pwm1_enable);
403b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
404b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
405b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_pwm1_enable(
406b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
407b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *attr,
408b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf,
409b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		size_t count)
410b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
4111276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
4121276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
413b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
414179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int config = kstrtol(buf, 10, &val);
415b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (config)
416b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return config;
417b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
418cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin	mutex_lock(&data->update_lock);
419b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
420b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (config < 0) {
421b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
422b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Error reading configuration register, aborting.\n");
423cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin			count = config;
424cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin			goto unlock;
425b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
426b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
427b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	switch (val) {
428b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 1:
429b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF1_FDRC0;
430b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF1_FDRC1;
431b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
432b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 2:
433b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF1_FDRC0;
434b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config |= AMC6821_CONF1_FDRC1;
435b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
436b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 3:
437b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config |= AMC6821_CONF1_FDRC0;
438b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config |= AMC6821_CONF1_FDRC1;
439b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
440b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	default:
441cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin		count = -EINVAL;
442cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin		goto unlock;
443b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
444b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
445b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
446b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Configuration register write error, aborting.\n");
447b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			count = -EIO;
448b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
449cf44819c98db11163f58f08b822d626c7a8f5188Axel Linunlock:
450b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
451b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
452b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
453b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
454b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1_auto_channels_temp(
455b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
456b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
457b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
458b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
459b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
460b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp);
461b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
462b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
463b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_temp_auto_point_temp(
464b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
465b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
466b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
467b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
468b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr_2(devattr)->index;
469b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int nr = to_sensor_dev_attr_2(devattr)->nr;
470b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
471b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	switch (nr) {
472b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 1:
473b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "%d\n",
474b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			data->temp1_auto_point_temp[ix] * 1000);
475b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 2:
476b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "%d\n",
477b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			data->temp2_auto_point_temp[ix] * 1000);
478b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	default:
479b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(dev, "Unknown attr->nr (%d).\n", nr);
480b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -EINVAL;
481b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
482b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
483b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
484b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_pwm1_auto_point_pwm(
485b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
486b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
487b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
488b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
489b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr(devattr)->index;
490b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
491b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]);
492b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
493b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
494b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic inline ssize_t set_slope_register(struct i2c_client *client,
495b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		u8 reg,
496b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		u8 dpwm,
497b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		u8 *ptemp)
498b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
499b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int dt;
500b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 tmp;
501b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
502b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dt = ptemp[2]-ptemp[1];
503b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	for (tmp = 4; tmp > 0; tmp--) {
504b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (dt * (0x20 >> tmp) >= dpwm)
505b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			break;
506b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
507b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	tmp |= (ptemp[1] & 0x7C) << 1;
508b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client,
509b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			reg, tmp)) {
510b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev, "Register write error, aborting.\n");
511b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -EIO;
512b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
513b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return 0;
514b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
515b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
516b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_temp_auto_point_temp(
517b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
518b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *attr,
519b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf,
520b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		size_t count)
521b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
522b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
5231276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
524b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr_2(attr)->index;
525b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int nr = to_sensor_dev_attr_2(attr)->nr;
526b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 *ptemp;
527b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	u8 reg;
528b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int dpwm;
529b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
530179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int ret = kstrtol(buf, 10, &val);
531b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (ret)
532b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return ret;
533b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
534b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	switch (nr) {
535b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 1:
536b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		ptemp = data->temp1_auto_point_temp;
537b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		reg = AMC6821_REG_LTEMP_FAN_CTRL;
538b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
539b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 2:
540b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		ptemp = data->temp2_auto_point_temp;
541b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		reg = AMC6821_REG_RTEMP_FAN_CTRL;
542b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
543b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	default:
544b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(dev, "Unknown attr->nr (%d).\n", nr);
545b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -EINVAL;
546b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
547b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
548b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_lock(&data->update_lock);
549cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin	data->valid = 0;
550cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin
551b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	switch (ix) {
552b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 0:
5532a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck		ptemp[0] = clamp_val(val / 1000, 0,
5542a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck				     data->temp1_auto_point_temp[1]);
5552a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck		ptemp[0] = clamp_val(ptemp[0], 0,
5562a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck				     data->temp2_auto_point_temp[1]);
5572a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck		ptemp[0] = clamp_val(ptemp[0], 0, 63);
558b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (i2c_smbus_write_byte_data(
559b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj					client,
560b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj					AMC6821_REG_PSV_TEMP,
561b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj					ptemp[0])) {
562b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				dev_err(&client->dev,
563b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj					"Register write error, aborting.\n");
564b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				count = -EIO;
565b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
566b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
567b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 1:
5682a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck		ptemp[1] = clamp_val(val / 1000, (ptemp[0] & 0x7C) + 4, 124);
569b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		ptemp[1] &= 0x7C;
5702a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck		ptemp[2] = clamp_val(ptemp[2], ptemp[1] + 1, 255);
571b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
572b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 2:
5732a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck		ptemp[2] = clamp_val(val / 1000, ptemp[1]+1, 255);
574b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
575b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	default:
576b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(dev, "Unknown attr->index (%d).\n", ix);
577b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EINVAL;
578b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
579b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
580b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1];
581b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (set_slope_register(client, reg, dpwm, ptemp))
582b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
583b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
584b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT:
585b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
586b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
587b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
588b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
589b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_pwm1_auto_point_pwm(
590b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
591b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *attr,
592b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf,
593b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		size_t count)
594b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
5951276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
5961276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
597b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int dpwm;
598b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
599179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int ret = kstrtol(buf, 10, &val);
600b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (ret)
601b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return ret;
602b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
603b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_lock(&data->update_lock);
6042a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	data->pwm1_auto_point_pwm[1] = clamp_val(val, 0, 254);
605b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP,
606b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			data->pwm1_auto_point_pwm[1])) {
607b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev, "Register write error, aborting.\n");
608b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
609b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
610b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
611b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1];
612b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm,
613b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			data->temp1_auto_point_temp)) {
614b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
615b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
616b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
617b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm,
618b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			data->temp2_auto_point_temp)) {
619b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
620b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
621b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
622b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
623b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT:
624b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	data->valid = 0;
625b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
626b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
627b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
628b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
629b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_fan(
630b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
631b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
632b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
633b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
634b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
635b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr(devattr)->index;
636b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (0 == data->fan[ix])
637b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "0");
638b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix]));
639b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
640b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
641b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_fan1_fault(
642b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
643b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
644b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
645b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
646b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
647b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (data->stat1 & AMC6821_STAT1_FANS)
648b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "1");
649b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	else
650b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return sprintf(buf, "0");
651b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
652b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
653b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_fan(
654b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
655b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *attr,
656b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf, size_t count)
657b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
6581276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
6591276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
660b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
661b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int ix = to_sensor_dev_attr(attr)->index;
662179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int ret = kstrtol(buf, 10, &val);
663b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (ret)
664b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return ret;
665b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	val = 1 > val ? 0xFFFF : 6000000/val;
666b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
667b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_lock(&data->update_lock);
6682a844c148e1f714ebf42cb96e1b172ce394c36c9Guenter Roeck	data->fan[ix] = (u16) clamp_val(val, 1, 0xFFFF);
669b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client, fan_reg_low[ix],
670b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			data->fan[ix] & 0xFF)) {
671b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev, "Register write error, aborting.\n");
672b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
673b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
674b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
675b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client,
676b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			fan_reg_hi[ix], data->fan[ix] >> 8)) {
677b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev, "Register write error, aborting.\n");
678b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
679b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
680b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT:
681b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
682b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
683b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
684b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
685b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t get_fan1_div(
686b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
687b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *devattr,
688b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		char *buf)
689b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
690b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct amc6821_data *data = amc6821_update_device(dev);
691b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return sprintf(buf, "%d\n", data->fan1_div);
692b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
693b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
694b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic ssize_t set_fan1_div(
695b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device *dev,
696b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct device_attribute *attr,
697b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		const char *buf, size_t count)
698b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
6991276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct amc6821_data *data = dev_get_drvdata(dev);
7001276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct i2c_client *client = data->client;
701b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	long val;
702179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	int config = kstrtol(buf, 10, &val);
703b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (config)
704b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return config;
705b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
706cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin	mutex_lock(&data->update_lock);
707b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
708b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (config < 0) {
709b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev,
710b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Error reading configuration register, aborting.\n");
711cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin		count = config;
712cf44819c98db11163f58f08b822d626c7a8f5188Axel Lin		goto EXIT;
713b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
714b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	switch (val) {
715b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 2:
716b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF4_PSPR;
717b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		data->fan1_div = 2;
718b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
719b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	case 4:
720b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config |= AMC6821_CONF4_PSPR;
721b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		data->fan1_div = 4;
722b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		break;
723b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	default:
724b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EINVAL;
725b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		goto EXIT;
726b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
727b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) {
728b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_err(&client->dev,
729b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Configuration register write error, aborting.\n");
730b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		count = -EIO;
731b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
732b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljEXIT:
733b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	mutex_unlock(&data->update_lock);
734b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return count;
735b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
736b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
737b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
738b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp, NULL, IDX_TEMP1_INPUT);
739b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp,
740b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	set_temp, IDX_TEMP1_MIN);
741b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp,
742b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	set_temp, IDX_TEMP1_MAX);
743b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp,
744b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	set_temp, IDX_TEMP1_CRIT);
745b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO,
746b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_alarm, NULL, IDX_TEMP1_MIN);
747b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
748b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_alarm, NULL, IDX_TEMP1_MAX);
749b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
750b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_alarm, NULL, IDX_TEMP1_CRIT);
751df86754b746e9a0ff6f863f690b1c01d408e3cdcAxel Linstatic SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO,
752b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp, NULL, IDX_TEMP2_INPUT);
753b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp,
754b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	set_temp, IDX_TEMP2_MIN);
755b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp,
756b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	set_temp, IDX_TEMP2_MAX);
757b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp,
758b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	set_temp, IDX_TEMP2_CRIT);
759b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO,
760b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp2_fault, NULL, 0);
761b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO,
762b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_alarm, NULL, IDX_TEMP2_MIN);
763b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO,
764b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_alarm, NULL, IDX_TEMP2_MAX);
765b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO,
766b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_alarm, NULL, IDX_TEMP2_CRIT);
767b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT);
768b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR,
769b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_fan, set_fan, IDX_FAN1_MIN);
770b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR,
771b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_fan, set_fan, IDX_FAN1_MAX);
772b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0);
773b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
774b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_fan1_div, set_fan1_div, 0);
775b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
776b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0);
777b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
778b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_pwm1_enable, set_pwm1_enable, 0);
779b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO,
780b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_pwm1_auto_point_pwm, NULL, 0);
781b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
782b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1);
783b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO,
784b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_pwm1_auto_point_pwm, NULL, 2);
785b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO,
786b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_pwm1_auto_channels_temp, NULL, 0);
787b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO,
788b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_auto_point_temp, NULL, 1, 0);
789b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO,
790b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1);
791b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO,
792b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2);
793b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
794b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO,
795b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0);
796b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
797b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1);
798b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO,
799b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2);
800b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
801b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic struct attribute *amc6821_attrs[] = {
802b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_input.dev_attr.attr,
803b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_min.dev_attr.attr,
804b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_max.dev_attr.attr,
805b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_crit.dev_attr.attr,
806b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
807b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
808b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
809b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_input.dev_attr.attr,
810b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_min.dev_attr.attr,
811b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_max.dev_attr.attr,
812b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_crit.dev_attr.attr,
813b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
814b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
815b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
816b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_fault.dev_attr.attr,
817b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_fan1_input.dev_attr.attr,
818b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_fan1_min.dev_attr.attr,
819b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_fan1_max.dev_attr.attr,
820b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_fan1_fault.dev_attr.attr,
821b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_fan1_div.dev_attr.attr,
822b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_pwm1.dev_attr.attr,
823b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
824b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
825b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
826b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
827b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
828b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
829b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
830b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr,
831b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
832b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
833b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	&sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr,
834b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	NULL
835b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj};
836b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
8371276fae2a93142525580d6f6ab77105f4d7a0e09Axel LinATTRIBUTE_GROUPS(amc6821);
838b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
839b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj/* Return 0 if detection is successful, -ENODEV otherwise */
840b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_detect(
841b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct i2c_client *client,
842b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		struct i2c_board_info *info)
843b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
844b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	struct i2c_adapter *adapter = client->adapter;
845b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int address = client->addr;
846b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int dev_id, comp_id;
847b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
848b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dev_dbg(&adapter->dev, "amc6821_detect called.\n");
849b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
850b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
851b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(&adapter->dev,
852b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"amc6821: I2C bus doesn't support byte mode, "
853b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"skipping.\n");
854b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -ENODEV;
855b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
856b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
857b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID);
858b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID);
859b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (dev_id != 0x21 || comp_id != 0x49) {
860b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(&adapter->dev,
861b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"amc6821: detection failed at 0x%02x.\n",
862b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			address);
863b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -ENODEV;
864b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
865b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
866ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck	/*
867ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck	 * Bit 7 of the address register is ignored, so we can check the
868ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck	 * ID registers again
869ca3c7b63423c7f723258797bcb5b11652d32500bGuenter Roeck	 */
870b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID);
871b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID);
872b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (dev_id != 0x21 || comp_id != 0x49) {
873b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_dbg(&adapter->dev,
874b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"amc6821: detection failed at 0x%02x.\n",
875b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			address);
876b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		return -ENODEV;
877b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
878b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
879b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address);
880b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	strlcpy(info->type, "amc6821", I2C_NAME_SIZE);
881b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
882b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return 0;
883b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
884b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
885b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Merteljstatic int amc6821_init_client(struct i2c_client *client)
886b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
887b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int config;
888b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	int err = -EIO;
889b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
890b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	if (init) {
891b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
892b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
893b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (config < 0) {
894b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				dev_err(&client->dev,
895b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Error reading configuration register, aborting.\n");
896b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				return err;
897b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
898b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
899b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config |= AMC6821_CONF4_MODE;
900b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
901b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4,
902b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				config)) {
903b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
904b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Configuration register write error, aborting.\n");
905b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
906b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
907b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
908b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3);
909b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
910b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (config < 0) {
911b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
912b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Error reading configuration register, aborting.\n");
913b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
914b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
915b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
916b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		dev_info(&client->dev, "Revision %d\n", config & 0x0f);
917b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
918b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF3_THERM_FAN_EN;
919b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
920b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3,
921b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				config)) {
922b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
923b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Configuration register write error, aborting.\n");
924b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
925b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
926b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
927b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2);
928b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
929b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (config < 0) {
930b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
931b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Error reading configuration register, aborting.\n");
932b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
933b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
934b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
935b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF2_RTFIE;
936b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF2_LTOIE;
937b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF2_RTOIE;
938b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (i2c_smbus_write_byte_data(client,
939b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				AMC6821_REG_CONF2, config)) {
940b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
941b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Configuration register write error, aborting.\n");
942b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
943b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
944b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
945b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
946b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
947b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (config < 0) {
948b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
949b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Error reading configuration register, aborting.\n");
950b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
951b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
952b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
953b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF1_THERMOVIE;
954b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config &= ~AMC6821_CONF1_FANIE;
955b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		config |= AMC6821_CONF1_START;
956b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (pwminv)
957b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			config |= AMC6821_CONF1_PWMINV;
958b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		else
959b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			config &= ~AMC6821_CONF1_PWMINV;
960b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
961b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		if (i2c_smbus_write_byte_data(
962b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj				client, AMC6821_REG_CONF1, config)) {
963b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			dev_err(&client->dev,
964b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			"Configuration register write error, aborting.\n");
965b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj			return err;
966b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj		}
967b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	}
968b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj	return 0;
969b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
970b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
97128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Linstatic int amc6821_probe(struct i2c_client *client,
97228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin			 const struct i2c_device_id *id)
973b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj{
9741276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct device *dev = &client->dev;
97528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	struct amc6821_data *data;
9761276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	struct device *hwmon_dev;
97728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	int err;
978b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
9791276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL);
98028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	if (!data)
98128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		return -ENOMEM;
982b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
9831276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	data->client = client;
98428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	mutex_init(&data->update_lock);
985b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
98628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	/*
98728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	 * Initialize the amc6821 chip
98828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	 */
98928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	err = amc6821_init_client(client);
99028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	if (err)
99128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		return err;
992b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
9931276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
9941276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin							   data,
9951276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin							   amc6821_groups);
9961276fae2a93142525580d6f6ab77105f4d7a0e09Axel Lin	return PTR_ERR_OR_ZERO(hwmon_dev);
997b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj}
998b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
99928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Linstatic const struct i2c_device_id amc6821_id[] = {
100028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	{ "amc6821", amc6821 },
100128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	{ }
100228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin};
100328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
100428e6274d8fa67ecb468eaa219c45595384e3bda8Axel LinMODULE_DEVICE_TABLE(i2c, amc6821_id);
100528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
100628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Linstatic struct i2c_driver amc6821_driver = {
100728e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	.class = I2C_CLASS_HWMON,
100828e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	.driver = {
100928e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin		.name	= "amc6821",
101028e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	},
101128e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	.probe = amc6821_probe,
101228e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	.id_table = amc6821_id,
101328e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	.detect = amc6821_detect,
101428e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin	.address_list = normal_i2c,
101528e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin};
101628e6274d8fa67ecb468eaa219c45595384e3bda8Axel Lin
1017f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(amc6821_driver);
1018b5430a04e995081a308b4419bd0940f2badc6e6bTomaz Mertelj
1019b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_LICENSE("GPL");
1020b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_AUTHOR("T. Mertelj <tomaz.mertelj@guest.arnes.si>");
1021b5430a04e995081a308b4419bd0940f2badc6e6bTomaz MerteljMODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver");
1022