18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring 48c2ecf20Sopenharmony_ci * Copyright (c) 2007, 2010 George Joseph <george.joseph@fairview5.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 118c2ecf20Sopenharmony_ci#include <linux/i2c.h> 128c2ecf20Sopenharmony_ci#include <linux/hwmon.h> 138c2ecf20Sopenharmony_ci#include <linux/hwmon-sysfs.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/mutex.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Addresses to scan */ 188c2ecf20Sopenharmony_cistatic const unsigned short normal_i2c[] = { 198c2ecf20Sopenharmony_ci 0x2c, 0x2d, 0x2e, I2C_CLIENT_END 208c2ecf20Sopenharmony_ci}; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cienum asc7621_type { 238c2ecf20Sopenharmony_ci asc7621, 248c2ecf20Sopenharmony_ci asc7621a 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define INTERVAL_HIGH (HZ + HZ / 2) 288c2ecf20Sopenharmony_ci#define INTERVAL_LOW (1 * 60 * HZ) 298c2ecf20Sopenharmony_ci#define PRI_NONE 0 308c2ecf20Sopenharmony_ci#define PRI_LOW 1 318c2ecf20Sopenharmony_ci#define PRI_HIGH 2 328c2ecf20Sopenharmony_ci#define FIRST_CHIP asc7621 338c2ecf20Sopenharmony_ci#define LAST_CHIP asc7621a 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistruct asc7621_chip { 368c2ecf20Sopenharmony_ci char *name; 378c2ecf20Sopenharmony_ci enum asc7621_type chip_type; 388c2ecf20Sopenharmony_ci u8 company_reg; 398c2ecf20Sopenharmony_ci u8 company_id; 408c2ecf20Sopenharmony_ci u8 verstep_reg; 418c2ecf20Sopenharmony_ci u8 verstep_id; 428c2ecf20Sopenharmony_ci const unsigned short *addresses; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic struct asc7621_chip asc7621_chips[] = { 468c2ecf20Sopenharmony_ci { 478c2ecf20Sopenharmony_ci .name = "asc7621", 488c2ecf20Sopenharmony_ci .chip_type = asc7621, 498c2ecf20Sopenharmony_ci .company_reg = 0x3e, 508c2ecf20Sopenharmony_ci .company_id = 0x61, 518c2ecf20Sopenharmony_ci .verstep_reg = 0x3f, 528c2ecf20Sopenharmony_ci .verstep_id = 0x6c, 538c2ecf20Sopenharmony_ci .addresses = normal_i2c, 548c2ecf20Sopenharmony_ci }, 558c2ecf20Sopenharmony_ci { 568c2ecf20Sopenharmony_ci .name = "asc7621a", 578c2ecf20Sopenharmony_ci .chip_type = asc7621a, 588c2ecf20Sopenharmony_ci .company_reg = 0x3e, 598c2ecf20Sopenharmony_ci .company_id = 0x61, 608c2ecf20Sopenharmony_ci .verstep_reg = 0x3f, 618c2ecf20Sopenharmony_ci .verstep_id = 0x6d, 628c2ecf20Sopenharmony_ci .addresses = normal_i2c, 638c2ecf20Sopenharmony_ci }, 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* 678c2ecf20Sopenharmony_ci * Defines the highest register to be used, not the count. 688c2ecf20Sopenharmony_ci * The actual count will probably be smaller because of gaps 698c2ecf20Sopenharmony_ci * in the implementation (unused register locations). 708c2ecf20Sopenharmony_ci * This define will safely set the array size of both the parameter 718c2ecf20Sopenharmony_ci * and data arrays. 728c2ecf20Sopenharmony_ci * This comes from the data sheet register description table. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci#define LAST_REGISTER 0xff 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_cistruct asc7621_data { 778c2ecf20Sopenharmony_ci struct i2c_client client; 788c2ecf20Sopenharmony_ci struct device *class_dev; 798c2ecf20Sopenharmony_ci struct mutex update_lock; 808c2ecf20Sopenharmony_ci int valid; /* !=0 if following fields are valid */ 818c2ecf20Sopenharmony_ci unsigned long last_high_reading; /* In jiffies */ 828c2ecf20Sopenharmony_ci unsigned long last_low_reading; /* In jiffies */ 838c2ecf20Sopenharmony_ci /* 848c2ecf20Sopenharmony_ci * Registers we care about occupy the corresponding index 858c2ecf20Sopenharmony_ci * in the array. Registers we don't care about are left 868c2ecf20Sopenharmony_ci * at 0. 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci u8 reg[LAST_REGISTER + 1]; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* 928c2ecf20Sopenharmony_ci * Macro to get the parent asc7621_param structure 938c2ecf20Sopenharmony_ci * from a sensor_device_attribute passed into the 948c2ecf20Sopenharmony_ci * show/store functions. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci#define to_asc7621_param(_sda) \ 978c2ecf20Sopenharmony_ci container_of(_sda, struct asc7621_param, sda) 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci/* 1008c2ecf20Sopenharmony_ci * Each parameter to be retrieved needs an asc7621_param structure 1018c2ecf20Sopenharmony_ci * allocated. It contains the sensor_device_attribute structure 1028c2ecf20Sopenharmony_ci * and the control info needed to retrieve the value from the register map. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_cistruct asc7621_param { 1058c2ecf20Sopenharmony_ci struct sensor_device_attribute sda; 1068c2ecf20Sopenharmony_ci u8 priority; 1078c2ecf20Sopenharmony_ci u8 msb[3]; 1088c2ecf20Sopenharmony_ci u8 lsb[3]; 1098c2ecf20Sopenharmony_ci u8 mask[3]; 1108c2ecf20Sopenharmony_ci u8 shift[3]; 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci/* 1148c2ecf20Sopenharmony_ci * This is the map that ultimately indicates whether we'll be 1158c2ecf20Sopenharmony_ci * retrieving a register value or not, and at what frequency. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_cistatic u8 asc7621_register_priorities[255]; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic struct asc7621_data *asc7621_update_device(struct device *dev); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic inline u8 read_byte(struct i2c_client *client, u8 reg) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci int res = i2c_smbus_read_byte_data(client, reg); 1248c2ecf20Sopenharmony_ci if (res < 0) { 1258c2ecf20Sopenharmony_ci dev_err(&client->dev, 1268c2ecf20Sopenharmony_ci "Unable to read from register 0x%02x.\n", reg); 1278c2ecf20Sopenharmony_ci return 0; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci return res & 0xff; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic inline int write_byte(struct i2c_client *client, u8 reg, u8 data) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci int res = i2c_smbus_write_byte_data(client, reg, data); 1358c2ecf20Sopenharmony_ci if (res < 0) { 1368c2ecf20Sopenharmony_ci dev_err(&client->dev, 1378c2ecf20Sopenharmony_ci "Unable to write value 0x%02x to register 0x%02x.\n", 1388c2ecf20Sopenharmony_ci data, reg); 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci return res; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/* 1448c2ecf20Sopenharmony_ci * Data Handlers 1458c2ecf20Sopenharmony_ci * Each function handles the formatting, storage 1468c2ecf20Sopenharmony_ci * and retrieval of like parameters. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#define SETUP_SHOW_DATA_PARAM(d, a) \ 1508c2ecf20Sopenharmony_ci struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ 1518c2ecf20Sopenharmony_ci struct asc7621_data *data = asc7621_update_device(d); \ 1528c2ecf20Sopenharmony_ci struct asc7621_param *param = to_asc7621_param(sda) 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#define SETUP_STORE_DATA_PARAM(d, a) \ 1558c2ecf20Sopenharmony_ci struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ 1568c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(d); \ 1578c2ecf20Sopenharmony_ci struct asc7621_data *data = i2c_get_clientdata(client); \ 1588c2ecf20Sopenharmony_ci struct asc7621_param *param = to_asc7621_param(sda) 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * u8 is just what it sounds like...an unsigned byte with no 1628c2ecf20Sopenharmony_ci * special formatting. 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_cistatic ssize_t show_u8(struct device *dev, struct device_attribute *attr, 1658c2ecf20Sopenharmony_ci char *buf) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", data->reg[param->msb[0]]); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic ssize_t store_u8(struct device *dev, struct device_attribute *attr, 1738c2ecf20Sopenharmony_ci const char *buf, size_t count) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 1768c2ecf20Sopenharmony_ci long reqval; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 1798c2ecf20Sopenharmony_ci return -EINVAL; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, 0, 255); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 1848c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = reqval; 1858c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], reqval); 1868c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 1878c2ecf20Sopenharmony_ci return count; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/* 1918c2ecf20Sopenharmony_ci * Many of the config values occupy only a few bits of a register. 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_cistatic ssize_t show_bitmask(struct device *dev, 1948c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", 1998c2ecf20Sopenharmony_ci (data->reg[param->msb[0]] >> param-> 2008c2ecf20Sopenharmony_ci shift[0]) & param->mask[0]); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic ssize_t store_bitmask(struct device *dev, 2048c2ecf20Sopenharmony_ci struct device_attribute *attr, 2058c2ecf20Sopenharmony_ci const char *buf, size_t count) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 2088c2ecf20Sopenharmony_ci long reqval; 2098c2ecf20Sopenharmony_ci u8 currval; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 2128c2ecf20Sopenharmony_ci return -EINVAL; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, 0, param->mask[0]); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci reqval = (reqval & param->mask[0]) << param->shift[0]; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 2198c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 2208c2ecf20Sopenharmony_ci reqval |= (currval & ~(param->mask[0] << param->shift[0])); 2218c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = reqval; 2228c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], reqval); 2238c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 2248c2ecf20Sopenharmony_ci return count; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci/* 2288c2ecf20Sopenharmony_ci * 16 bit fan rpm values 2298c2ecf20Sopenharmony_ci * reported by the device as the number of 11.111us periods (90khz) 2308c2ecf20Sopenharmony_ci * between full fan rotations. Therefore... 2318c2ecf20Sopenharmony_ci * RPM = (90000 * 60) / register value 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_cistatic ssize_t show_fan16(struct device *dev, 2348c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 2378c2ecf20Sopenharmony_ci u16 regval; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 2408c2ecf20Sopenharmony_ci regval = (data->reg[param->msb[0]] << 8) | data->reg[param->lsb[0]]; 2418c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", 2448c2ecf20Sopenharmony_ci (regval == 0 ? -1 : (regval) == 2458c2ecf20Sopenharmony_ci 0xffff ? 0 : 5400000 / regval)); 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistatic ssize_t store_fan16(struct device *dev, 2498c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 2508c2ecf20Sopenharmony_ci size_t count) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 2538c2ecf20Sopenharmony_ci long reqval; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 2568c2ecf20Sopenharmony_ci return -EINVAL; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* 2598c2ecf20Sopenharmony_ci * If a minimum RPM of zero is requested, then we set the register to 2608c2ecf20Sopenharmony_ci * 0xffff. This value allows the fan to be stopped completely without 2618c2ecf20Sopenharmony_ci * generating an alarm. 2628c2ecf20Sopenharmony_ci */ 2638c2ecf20Sopenharmony_ci reqval = 2648c2ecf20Sopenharmony_ci (reqval <= 0 ? 0xffff : clamp_val(5400000 / reqval, 0, 0xfffe)); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 2678c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = (reqval >> 8) & 0xff; 2688c2ecf20Sopenharmony_ci data->reg[param->lsb[0]] = reqval & 0xff; 2698c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], data->reg[param->msb[0]]); 2708c2ecf20Sopenharmony_ci write_byte(client, param->lsb[0], data->reg[param->lsb[0]]); 2718c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci return count; 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci/* 2778c2ecf20Sopenharmony_ci * Voltages are scaled in the device so that the nominal voltage 2788c2ecf20Sopenharmony_ci * is 3/4ths of the 0-255 range (i.e. 192). 2798c2ecf20Sopenharmony_ci * If all voltages are 'normal' then all voltage registers will 2808c2ecf20Sopenharmony_ci * read 0xC0. 2818c2ecf20Sopenharmony_ci * 2828c2ecf20Sopenharmony_ci * The data sheet provides us with the 3/4 scale value for each voltage 2838c2ecf20Sopenharmony_ci * which is stored in in_scaling. The sda->index parameter value provides 2848c2ecf20Sopenharmony_ci * the index into in_scaling. 2858c2ecf20Sopenharmony_ci * 2868c2ecf20Sopenharmony_ci * NOTE: The chip expects the first 2 inputs be 2.5 and 2.25 volts 2878c2ecf20Sopenharmony_ci * respectively. That doesn't mean that's what the motherboard provides. :) 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic const int asc7621_in_scaling[] = { 2918c2ecf20Sopenharmony_ci 2500, 2250, 3300, 5000, 12000 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic ssize_t show_in10(struct device *dev, struct device_attribute *attr, 2958c2ecf20Sopenharmony_ci char *buf) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 2988c2ecf20Sopenharmony_ci u16 regval; 2998c2ecf20Sopenharmony_ci u8 nr = sda->index; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 3028c2ecf20Sopenharmony_ci regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]); 3038c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* The LSB value is a 2-bit scaling of the MSB's LSbit value. */ 3068c2ecf20Sopenharmony_ci regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", regval); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/* 8 bit voltage values (the mins and maxs) */ 3128c2ecf20Sopenharmony_cistatic ssize_t show_in8(struct device *dev, struct device_attribute *attr, 3138c2ecf20Sopenharmony_ci char *buf) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 3168c2ecf20Sopenharmony_ci u8 nr = sda->index; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", 3198c2ecf20Sopenharmony_ci ((data->reg[param->msb[0]] * 3208c2ecf20Sopenharmony_ci asc7621_in_scaling[nr]) / 0xc0)); 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic ssize_t store_in8(struct device *dev, struct device_attribute *attr, 3248c2ecf20Sopenharmony_ci const char *buf, size_t count) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 3278c2ecf20Sopenharmony_ci long reqval; 3288c2ecf20Sopenharmony_ci u8 nr = sda->index; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 3318c2ecf20Sopenharmony_ci return -EINVAL; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, 0, 0xffff); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci reqval = reqval * 0xc0 / asc7621_in_scaling[nr]; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, 0, 0xff); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 3408c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = reqval; 3418c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], reqval); 3428c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci return count; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic ssize_t show_temp8(struct device *dev, 3488c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic ssize_t store_temp8(struct device *dev, 3568c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 3578c2ecf20Sopenharmony_ci size_t count) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 3608c2ecf20Sopenharmony_ci long reqval; 3618c2ecf20Sopenharmony_ci s8 temp; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 3648c2ecf20Sopenharmony_ci return -EINVAL; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, -127000, 127000); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci temp = reqval / 1000; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 3718c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = temp; 3728c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], temp); 3738c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 3748c2ecf20Sopenharmony_ci return count; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci/* 3788c2ecf20Sopenharmony_ci * Temperatures that occupy 2 bytes always have the whole 3798c2ecf20Sopenharmony_ci * number of degrees in the MSB with some part of the LSB 3808c2ecf20Sopenharmony_ci * indicating fractional degrees. 3818c2ecf20Sopenharmony_ci */ 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/* mmmmmmmm.llxxxxxx */ 3848c2ecf20Sopenharmony_cistatic ssize_t show_temp10(struct device *dev, 3858c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 3888c2ecf20Sopenharmony_ci u8 msb, lsb; 3898c2ecf20Sopenharmony_ci int temp; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 3928c2ecf20Sopenharmony_ci msb = data->reg[param->msb[0]]; 3938c2ecf20Sopenharmony_ci lsb = (data->reg[param->lsb[0]] >> 6) & 0x03; 3948c2ecf20Sopenharmony_ci temp = (((s8) msb) * 1000) + (lsb * 250); 3958c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", temp); 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci/* mmmmmm.ll */ 4018c2ecf20Sopenharmony_cistatic ssize_t show_temp62(struct device *dev, 4028c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 4058c2ecf20Sopenharmony_ci u8 regval = data->reg[param->msb[0]]; 4068c2ecf20Sopenharmony_ci int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", temp); 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_cistatic ssize_t store_temp62(struct device *dev, 4128c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 4138c2ecf20Sopenharmony_ci size_t count) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 4168c2ecf20Sopenharmony_ci long reqval, i, f; 4178c2ecf20Sopenharmony_ci s8 temp; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 4208c2ecf20Sopenharmony_ci return -EINVAL; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, -32000, 31750); 4238c2ecf20Sopenharmony_ci i = reqval / 1000; 4248c2ecf20Sopenharmony_ci f = reqval - (i * 1000); 4258c2ecf20Sopenharmony_ci temp = i << 2; 4268c2ecf20Sopenharmony_ci temp |= f / 250; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 4298c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = temp; 4308c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], temp); 4318c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 4328c2ecf20Sopenharmony_ci return count; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/* 4368c2ecf20Sopenharmony_ci * The aSC7621 doesn't provide an "auto_point2". Instead, you 4378c2ecf20Sopenharmony_ci * specify the auto_point1 and a range. To keep with the sysfs 4388c2ecf20Sopenharmony_ci * hwmon specs, we synthesize the auto_point_2 from them. 4398c2ecf20Sopenharmony_ci */ 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic const u32 asc7621_range_map[] = { 4428c2ecf20Sopenharmony_ci 2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000, 4438c2ecf20Sopenharmony_ci 13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000, 4448c2ecf20Sopenharmony_ci}; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic ssize_t show_ap2_temp(struct device *dev, 4478c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 4508c2ecf20Sopenharmony_ci long auto_point1; 4518c2ecf20Sopenharmony_ci u8 regval; 4528c2ecf20Sopenharmony_ci int temp; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 4558c2ecf20Sopenharmony_ci auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000; 4568c2ecf20Sopenharmony_ci regval = 4578c2ecf20Sopenharmony_ci ((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]); 4588c2ecf20Sopenharmony_ci temp = auto_point1 + asc7621_range_map[clamp_val(regval, 0, 15)]; 4598c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", temp); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_cistatic ssize_t store_ap2_temp(struct device *dev, 4668c2ecf20Sopenharmony_ci struct device_attribute *attr, 4678c2ecf20Sopenharmony_ci const char *buf, size_t count) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 4708c2ecf20Sopenharmony_ci long reqval, auto_point1; 4718c2ecf20Sopenharmony_ci int i; 4728c2ecf20Sopenharmony_ci u8 currval, newval = 0; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 4758c2ecf20Sopenharmony_ci return -EINVAL; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 4788c2ecf20Sopenharmony_ci auto_point1 = data->reg[param->msb[1]] * 1000; 4798c2ecf20Sopenharmony_ci reqval = clamp_val(reqval, auto_point1 + 2000, auto_point1 + 80000); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) { 4828c2ecf20Sopenharmony_ci if (reqval >= auto_point1 + asc7621_range_map[i]) { 4838c2ecf20Sopenharmony_ci newval = i; 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci } 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci newval = (newval & param->mask[0]) << param->shift[0]; 4898c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 4908c2ecf20Sopenharmony_ci newval |= (currval & ~(param->mask[0] << param->shift[0])); 4918c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = newval; 4928c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], newval); 4938c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 4948c2ecf20Sopenharmony_ci return count; 4958c2ecf20Sopenharmony_ci} 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cistatic ssize_t show_pwm_ac(struct device *dev, 4988c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 5018c2ecf20Sopenharmony_ci u8 config, altbit, regval; 5028c2ecf20Sopenharmony_ci static const u8 map[] = { 5038c2ecf20Sopenharmony_ci 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10, 5048c2ecf20Sopenharmony_ci 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f 5058c2ecf20Sopenharmony_ci }; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 5088c2ecf20Sopenharmony_ci config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; 5098c2ecf20Sopenharmony_ci altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; 5108c2ecf20Sopenharmony_ci regval = config | (altbit << 3); 5118c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", map[clamp_val(regval, 0, 15)]); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic ssize_t store_pwm_ac(struct device *dev, 5178c2ecf20Sopenharmony_ci struct device_attribute *attr, 5188c2ecf20Sopenharmony_ci const char *buf, size_t count) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 5218c2ecf20Sopenharmony_ci unsigned long reqval; 5228c2ecf20Sopenharmony_ci u8 currval, config, altbit, newval; 5238c2ecf20Sopenharmony_ci static const u16 map[] = { 5248c2ecf20Sopenharmony_ci 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06, 5258c2ecf20Sopenharmony_ci 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 5268c2ecf20Sopenharmony_ci 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 5278c2ecf20Sopenharmony_ci 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 5288c2ecf20Sopenharmony_ci }; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (kstrtoul(buf, 10, &reqval)) 5318c2ecf20Sopenharmony_ci return -EINVAL; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (reqval > 31) 5348c2ecf20Sopenharmony_ci return -EINVAL; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci reqval = map[reqval]; 5378c2ecf20Sopenharmony_ci if (reqval == 0xff) 5388c2ecf20Sopenharmony_ci return -EINVAL; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci config = reqval & 0x07; 5418c2ecf20Sopenharmony_ci altbit = (reqval >> 3) & 0x01; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci config = (config & param->mask[0]) << param->shift[0]; 5448c2ecf20Sopenharmony_ci altbit = (altbit & param->mask[1]) << param->shift[1]; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 5478c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 5488c2ecf20Sopenharmony_ci newval = config | (currval & ~(param->mask[0] << param->shift[0])); 5498c2ecf20Sopenharmony_ci newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); 5508c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = newval; 5518c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], newval); 5528c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 5538c2ecf20Sopenharmony_ci return count; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_cistatic ssize_t show_pwm_enable(struct device *dev, 5578c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 5608c2ecf20Sopenharmony_ci u8 config, altbit, minoff, val, newval; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 5638c2ecf20Sopenharmony_ci config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; 5648c2ecf20Sopenharmony_ci altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; 5658c2ecf20Sopenharmony_ci minoff = (data->reg[param->msb[2]] >> param->shift[2]) & param->mask[2]; 5668c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci val = config | (altbit << 3); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (val == 3 || val >= 10) 5718c2ecf20Sopenharmony_ci newval = 255; 5728c2ecf20Sopenharmony_ci else if (val == 4) 5738c2ecf20Sopenharmony_ci newval = 0; 5748c2ecf20Sopenharmony_ci else if (val == 7) 5758c2ecf20Sopenharmony_ci newval = 1; 5768c2ecf20Sopenharmony_ci else if (minoff == 1) 5778c2ecf20Sopenharmony_ci newval = 2; 5788c2ecf20Sopenharmony_ci else 5798c2ecf20Sopenharmony_ci newval = 3; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", newval); 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic ssize_t store_pwm_enable(struct device *dev, 5858c2ecf20Sopenharmony_ci struct device_attribute *attr, 5868c2ecf20Sopenharmony_ci const char *buf, size_t count) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 5898c2ecf20Sopenharmony_ci long reqval; 5908c2ecf20Sopenharmony_ci u8 currval, config, altbit, newval, minoff = 255; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 5938c2ecf20Sopenharmony_ci return -EINVAL; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci switch (reqval) { 5968c2ecf20Sopenharmony_ci case 0: 5978c2ecf20Sopenharmony_ci newval = 0x04; 5988c2ecf20Sopenharmony_ci break; 5998c2ecf20Sopenharmony_ci case 1: 6008c2ecf20Sopenharmony_ci newval = 0x07; 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci case 2: 6038c2ecf20Sopenharmony_ci newval = 0x00; 6048c2ecf20Sopenharmony_ci minoff = 1; 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci case 3: 6078c2ecf20Sopenharmony_ci newval = 0x00; 6088c2ecf20Sopenharmony_ci minoff = 0; 6098c2ecf20Sopenharmony_ci break; 6108c2ecf20Sopenharmony_ci case 255: 6118c2ecf20Sopenharmony_ci newval = 0x03; 6128c2ecf20Sopenharmony_ci break; 6138c2ecf20Sopenharmony_ci default: 6148c2ecf20Sopenharmony_ci return -EINVAL; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci config = newval & 0x07; 6188c2ecf20Sopenharmony_ci altbit = (newval >> 3) & 0x01; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 6218c2ecf20Sopenharmony_ci config = (config & param->mask[0]) << param->shift[0]; 6228c2ecf20Sopenharmony_ci altbit = (altbit & param->mask[1]) << param->shift[1]; 6238c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 6248c2ecf20Sopenharmony_ci newval = config | (currval & ~(param->mask[0] << param->shift[0])); 6258c2ecf20Sopenharmony_ci newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); 6268c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = newval; 6278c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], newval); 6288c2ecf20Sopenharmony_ci if (minoff < 255) { 6298c2ecf20Sopenharmony_ci minoff = (minoff & param->mask[2]) << param->shift[2]; 6308c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[2]); 6318c2ecf20Sopenharmony_ci newval = 6328c2ecf20Sopenharmony_ci minoff | (currval & ~(param->mask[2] << param->shift[2])); 6338c2ecf20Sopenharmony_ci data->reg[param->msb[2]] = newval; 6348c2ecf20Sopenharmony_ci write_byte(client, param->msb[2], newval); 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 6378c2ecf20Sopenharmony_ci return count; 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_cistatic const u32 asc7621_pwm_freq_map[] = { 6418c2ecf20Sopenharmony_ci 10, 15, 23, 30, 38, 47, 62, 94, 6428c2ecf20Sopenharmony_ci 23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000 6438c2ecf20Sopenharmony_ci}; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic ssize_t show_pwm_freq(struct device *dev, 6468c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 6498c2ecf20Sopenharmony_ci u8 regval = 6508c2ecf20Sopenharmony_ci (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci regval = clamp_val(regval, 0, 15); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", asc7621_pwm_freq_map[regval]); 6558c2ecf20Sopenharmony_ci} 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_cistatic ssize_t store_pwm_freq(struct device *dev, 6588c2ecf20Sopenharmony_ci struct device_attribute *attr, 6598c2ecf20Sopenharmony_ci const char *buf, size_t count) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 6628c2ecf20Sopenharmony_ci unsigned long reqval; 6638c2ecf20Sopenharmony_ci u8 currval, newval = 255; 6648c2ecf20Sopenharmony_ci int i; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci if (kstrtoul(buf, 10, &reqval)) 6678c2ecf20Sopenharmony_ci return -EINVAL; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_pwm_freq_map); i++) { 6708c2ecf20Sopenharmony_ci if (reqval == asc7621_pwm_freq_map[i]) { 6718c2ecf20Sopenharmony_ci newval = i; 6728c2ecf20Sopenharmony_ci break; 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci if (newval == 255) 6768c2ecf20Sopenharmony_ci return -EINVAL; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci newval = (newval & param->mask[0]) << param->shift[0]; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 6818c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 6828c2ecf20Sopenharmony_ci newval |= (currval & ~(param->mask[0] << param->shift[0])); 6838c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = newval; 6848c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], newval); 6858c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 6868c2ecf20Sopenharmony_ci return count; 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic const u32 asc7621_pwm_auto_spinup_map[] = { 6908c2ecf20Sopenharmony_ci 0, 100, 250, 400, 700, 1000, 2000, 4000 6918c2ecf20Sopenharmony_ci}; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic ssize_t show_pwm_ast(struct device *dev, 6948c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 6978c2ecf20Sopenharmony_ci u8 regval = 6988c2ecf20Sopenharmony_ci (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci regval = clamp_val(regval, 0, 7); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", asc7621_pwm_auto_spinup_map[regval]); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic ssize_t store_pwm_ast(struct device *dev, 7078c2ecf20Sopenharmony_ci struct device_attribute *attr, 7088c2ecf20Sopenharmony_ci const char *buf, size_t count) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 7118c2ecf20Sopenharmony_ci long reqval; 7128c2ecf20Sopenharmony_ci u8 currval, newval = 255; 7138c2ecf20Sopenharmony_ci u32 i; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 7168c2ecf20Sopenharmony_ci return -EINVAL; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_pwm_auto_spinup_map); i++) { 7198c2ecf20Sopenharmony_ci if (reqval == asc7621_pwm_auto_spinup_map[i]) { 7208c2ecf20Sopenharmony_ci newval = i; 7218c2ecf20Sopenharmony_ci break; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci } 7248c2ecf20Sopenharmony_ci if (newval == 255) 7258c2ecf20Sopenharmony_ci return -EINVAL; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci newval = (newval & param->mask[0]) << param->shift[0]; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 7308c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 7318c2ecf20Sopenharmony_ci newval |= (currval & ~(param->mask[0] << param->shift[0])); 7328c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = newval; 7338c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], newval); 7348c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 7358c2ecf20Sopenharmony_ci return count; 7368c2ecf20Sopenharmony_ci} 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_cistatic const u32 asc7621_temp_smoothing_time_map[] = { 7398c2ecf20Sopenharmony_ci 35000, 17600, 11800, 7000, 4400, 3000, 1600, 800 7408c2ecf20Sopenharmony_ci}; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic ssize_t show_temp_st(struct device *dev, 7438c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci SETUP_SHOW_DATA_PARAM(dev, attr); 7468c2ecf20Sopenharmony_ci u8 regval = 7478c2ecf20Sopenharmony_ci (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; 7488c2ecf20Sopenharmony_ci regval = clamp_val(regval, 0, 7); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", asc7621_temp_smoothing_time_map[regval]); 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_cistatic ssize_t store_temp_st(struct device *dev, 7548c2ecf20Sopenharmony_ci struct device_attribute *attr, 7558c2ecf20Sopenharmony_ci const char *buf, size_t count) 7568c2ecf20Sopenharmony_ci{ 7578c2ecf20Sopenharmony_ci SETUP_STORE_DATA_PARAM(dev, attr); 7588c2ecf20Sopenharmony_ci long reqval; 7598c2ecf20Sopenharmony_ci u8 currval, newval = 255; 7608c2ecf20Sopenharmony_ci u32 i; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci if (kstrtol(buf, 10, &reqval)) 7638c2ecf20Sopenharmony_ci return -EINVAL; 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_temp_smoothing_time_map); i++) { 7668c2ecf20Sopenharmony_ci if (reqval == asc7621_temp_smoothing_time_map[i]) { 7678c2ecf20Sopenharmony_ci newval = i; 7688c2ecf20Sopenharmony_ci break; 7698c2ecf20Sopenharmony_ci } 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (newval == 255) 7738c2ecf20Sopenharmony_ci return -EINVAL; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci newval = (newval & param->mask[0]) << param->shift[0]; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 7788c2ecf20Sopenharmony_ci currval = read_byte(client, param->msb[0]); 7798c2ecf20Sopenharmony_ci newval |= (currval & ~(param->mask[0] << param->shift[0])); 7808c2ecf20Sopenharmony_ci data->reg[param->msb[0]] = newval; 7818c2ecf20Sopenharmony_ci write_byte(client, param->msb[0], newval); 7828c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 7838c2ecf20Sopenharmony_ci return count; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci/* 7878c2ecf20Sopenharmony_ci * End of data handlers 7888c2ecf20Sopenharmony_ci * 7898c2ecf20Sopenharmony_ci * These defines do nothing more than make the table easier 7908c2ecf20Sopenharmony_ci * to read when wrapped at column 80. 7918c2ecf20Sopenharmony_ci */ 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci/* 7948c2ecf20Sopenharmony_ci * Creates a variable length array inititalizer. 7958c2ecf20Sopenharmony_ci * VAA(1,3,5,7) would produce {1,3,5,7} 7968c2ecf20Sopenharmony_ci */ 7978c2ecf20Sopenharmony_ci#define VAA(args...) {args} 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci#define PREAD(name, n, pri, rm, rl, m, s, r) \ 8008c2ecf20Sopenharmony_ci {.sda = SENSOR_ATTR(name, S_IRUGO, show_##r, NULL, n), \ 8018c2ecf20Sopenharmony_ci .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ 8028c2ecf20Sopenharmony_ci .shift[0] = s,} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci#define PWRITE(name, n, pri, rm, rl, m, s, r) \ 8058c2ecf20Sopenharmony_ci {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ 8068c2ecf20Sopenharmony_ci .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ 8078c2ecf20Sopenharmony_ci .shift[0] = s,} 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci/* 8108c2ecf20Sopenharmony_ci * PWRITEM assumes that the initializers for the .msb, .lsb, .mask and .shift 8118c2ecf20Sopenharmony_ci * were created using the VAA macro. 8128c2ecf20Sopenharmony_ci */ 8138c2ecf20Sopenharmony_ci#define PWRITEM(name, n, pri, rm, rl, m, s, r) \ 8148c2ecf20Sopenharmony_ci {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ 8158c2ecf20Sopenharmony_ci .priority = pri, .msb = rm, .lsb = rl, .mask = m, .shift = s,} 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_cistatic struct asc7621_param asc7621_params[] = { 8188c2ecf20Sopenharmony_ci PREAD(in0_input, 0, PRI_HIGH, 0x20, 0x13, 0, 0, in10), 8198c2ecf20Sopenharmony_ci PREAD(in1_input, 1, PRI_HIGH, 0x21, 0x18, 0, 0, in10), 8208c2ecf20Sopenharmony_ci PREAD(in2_input, 2, PRI_HIGH, 0x22, 0x11, 0, 0, in10), 8218c2ecf20Sopenharmony_ci PREAD(in3_input, 3, PRI_HIGH, 0x23, 0x12, 0, 0, in10), 8228c2ecf20Sopenharmony_ci PREAD(in4_input, 4, PRI_HIGH, 0x24, 0x14, 0, 0, in10), 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci PWRITE(in0_min, 0, PRI_LOW, 0x44, 0, 0, 0, in8), 8258c2ecf20Sopenharmony_ci PWRITE(in1_min, 1, PRI_LOW, 0x46, 0, 0, 0, in8), 8268c2ecf20Sopenharmony_ci PWRITE(in2_min, 2, PRI_LOW, 0x48, 0, 0, 0, in8), 8278c2ecf20Sopenharmony_ci PWRITE(in3_min, 3, PRI_LOW, 0x4a, 0, 0, 0, in8), 8288c2ecf20Sopenharmony_ci PWRITE(in4_min, 4, PRI_LOW, 0x4c, 0, 0, 0, in8), 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci PWRITE(in0_max, 0, PRI_LOW, 0x45, 0, 0, 0, in8), 8318c2ecf20Sopenharmony_ci PWRITE(in1_max, 1, PRI_LOW, 0x47, 0, 0, 0, in8), 8328c2ecf20Sopenharmony_ci PWRITE(in2_max, 2, PRI_LOW, 0x49, 0, 0, 0, in8), 8338c2ecf20Sopenharmony_ci PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), 8348c2ecf20Sopenharmony_ci PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask), 8378c2ecf20Sopenharmony_ci PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask), 8388c2ecf20Sopenharmony_ci PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask), 8398c2ecf20Sopenharmony_ci PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask), 8408c2ecf20Sopenharmony_ci PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask), 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), 8438c2ecf20Sopenharmony_ci PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), 8448c2ecf20Sopenharmony_ci PREAD(fan3_input, 2, PRI_HIGH, 0x2d, 0x2c, 0, 0, fan16), 8458c2ecf20Sopenharmony_ci PREAD(fan4_input, 3, PRI_HIGH, 0x2f, 0x2e, 0, 0, fan16), 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci PWRITE(fan1_min, 0, PRI_LOW, 0x55, 0x54, 0, 0, fan16), 8488c2ecf20Sopenharmony_ci PWRITE(fan2_min, 1, PRI_LOW, 0x57, 0x56, 0, 0, fan16), 8498c2ecf20Sopenharmony_ci PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), 8508c2ecf20Sopenharmony_ci PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask), 8538c2ecf20Sopenharmony_ci PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask), 8548c2ecf20Sopenharmony_ci PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask), 8558c2ecf20Sopenharmony_ci PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask), 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), 8588c2ecf20Sopenharmony_ci PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), 8598c2ecf20Sopenharmony_ci PREAD(temp3_input, 2, PRI_HIGH, 0x27, 0x16, 0, 0, temp10), 8608c2ecf20Sopenharmony_ci PREAD(temp4_input, 3, PRI_HIGH, 0x33, 0x17, 0, 0, temp10), 8618c2ecf20Sopenharmony_ci PREAD(temp5_input, 4, PRI_HIGH, 0xf7, 0xf6, 0, 0, temp10), 8628c2ecf20Sopenharmony_ci PREAD(temp6_input, 5, PRI_HIGH, 0xf9, 0xf8, 0, 0, temp10), 8638c2ecf20Sopenharmony_ci PREAD(temp7_input, 6, PRI_HIGH, 0xfb, 0xfa, 0, 0, temp10), 8648c2ecf20Sopenharmony_ci PREAD(temp8_input, 7, PRI_HIGH, 0xfd, 0xfc, 0, 0, temp10), 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci PWRITE(temp1_min, 0, PRI_LOW, 0x4e, 0, 0, 0, temp8), 8678c2ecf20Sopenharmony_ci PWRITE(temp2_min, 1, PRI_LOW, 0x50, 0, 0, 0, temp8), 8688c2ecf20Sopenharmony_ci PWRITE(temp3_min, 2, PRI_LOW, 0x52, 0, 0, 0, temp8), 8698c2ecf20Sopenharmony_ci PWRITE(temp4_min, 3, PRI_LOW, 0x34, 0, 0, 0, temp8), 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci PWRITE(temp1_max, 0, PRI_LOW, 0x4f, 0, 0, 0, temp8), 8728c2ecf20Sopenharmony_ci PWRITE(temp2_max, 1, PRI_LOW, 0x51, 0, 0, 0, temp8), 8738c2ecf20Sopenharmony_ci PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), 8748c2ecf20Sopenharmony_ci PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask), 8778c2ecf20Sopenharmony_ci PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask), 8788c2ecf20Sopenharmony_ci PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask), 8798c2ecf20Sopenharmony_ci PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask), 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), 8828c2ecf20Sopenharmony_ci PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), 8838c2ecf20Sopenharmony_ci PWRITE(temp3_source, 2, PRI_LOW, 0x03, 0, 0x07, 4, bitmask), 8848c2ecf20Sopenharmony_ci PWRITE(temp4_source, 3, PRI_LOW, 0x03, 0, 0x07, 0, bitmask), 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), 8878c2ecf20Sopenharmony_ci PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), 8888c2ecf20Sopenharmony_ci PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask), 8898c2ecf20Sopenharmony_ci PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), 8928c2ecf20Sopenharmony_ci PWRITE(temp2_smoothing_time, 1, PRI_LOW, 0x63, 0, 0x07, 4, temp_st), 8938c2ecf20Sopenharmony_ci PWRITE(temp3_smoothing_time, 2, PRI_LOW, 0x63, 0, 0x07, 0, temp_st), 8948c2ecf20Sopenharmony_ci PWRITE(temp4_smoothing_time, 3, PRI_LOW, 0x3c, 0, 0x07, 0, temp_st), 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci PWRITE(temp1_auto_point1_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, 8978c2ecf20Sopenharmony_ci bitmask), 8988c2ecf20Sopenharmony_ci PWRITE(temp2_auto_point1_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, 8998c2ecf20Sopenharmony_ci bitmask), 9008c2ecf20Sopenharmony_ci PWRITE(temp3_auto_point1_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, 9018c2ecf20Sopenharmony_ci bitmask), 9028c2ecf20Sopenharmony_ci PWRITE(temp4_auto_point1_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, 9038c2ecf20Sopenharmony_ci bitmask), 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci PREAD(temp1_auto_point2_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, 9068c2ecf20Sopenharmony_ci bitmask), 9078c2ecf20Sopenharmony_ci PREAD(temp2_auto_point2_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, 9088c2ecf20Sopenharmony_ci bitmask), 9098c2ecf20Sopenharmony_ci PREAD(temp3_auto_point2_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, 9108c2ecf20Sopenharmony_ci bitmask), 9118c2ecf20Sopenharmony_ci PREAD(temp4_auto_point2_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, 9128c2ecf20Sopenharmony_ci bitmask), 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci PWRITE(temp1_auto_point1_temp, 0, PRI_LOW, 0x67, 0, 0, 0, temp8), 9158c2ecf20Sopenharmony_ci PWRITE(temp2_auto_point1_temp, 1, PRI_LOW, 0x68, 0, 0, 0, temp8), 9168c2ecf20Sopenharmony_ci PWRITE(temp3_auto_point1_temp, 2, PRI_LOW, 0x69, 0, 0, 0, temp8), 9178c2ecf20Sopenharmony_ci PWRITE(temp4_auto_point1_temp, 3, PRI_LOW, 0x3b, 0, 0, 0, temp8), 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci PWRITEM(temp1_auto_point2_temp, 0, PRI_LOW, VAA(0x5f, 0x67), VAA(0), 9208c2ecf20Sopenharmony_ci VAA(0x0f), VAA(4), ap2_temp), 9218c2ecf20Sopenharmony_ci PWRITEM(temp2_auto_point2_temp, 1, PRI_LOW, VAA(0x60, 0x68), VAA(0), 9228c2ecf20Sopenharmony_ci VAA(0x0f), VAA(4), ap2_temp), 9238c2ecf20Sopenharmony_ci PWRITEM(temp3_auto_point2_temp, 2, PRI_LOW, VAA(0x61, 0x69), VAA(0), 9248c2ecf20Sopenharmony_ci VAA(0x0f), VAA(4), ap2_temp), 9258c2ecf20Sopenharmony_ci PWRITEM(temp4_auto_point2_temp, 3, PRI_LOW, VAA(0x3c, 0x3b), VAA(0), 9268c2ecf20Sopenharmony_ci VAA(0x0f), VAA(4), ap2_temp), 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci PWRITE(temp1_crit, 0, PRI_LOW, 0x6a, 0, 0, 0, temp8), 9298c2ecf20Sopenharmony_ci PWRITE(temp2_crit, 1, PRI_LOW, 0x6b, 0, 0, 0, temp8), 9308c2ecf20Sopenharmony_ci PWRITE(temp3_crit, 2, PRI_LOW, 0x6c, 0, 0, 0, temp8), 9318c2ecf20Sopenharmony_ci PWRITE(temp4_crit, 3, PRI_LOW, 0x3d, 0, 0, 0, temp8), 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci PWRITE(temp5_enable, 4, PRI_LOW, 0x0e, 0, 0x01, 0, bitmask), 9348c2ecf20Sopenharmony_ci PWRITE(temp6_enable, 5, PRI_LOW, 0x0e, 0, 0x01, 1, bitmask), 9358c2ecf20Sopenharmony_ci PWRITE(temp7_enable, 6, PRI_LOW, 0x0e, 0, 0x01, 2, bitmask), 9368c2ecf20Sopenharmony_ci PWRITE(temp8_enable, 7, PRI_LOW, 0x0e, 0, 0x01, 3, bitmask), 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci PWRITE(remote1_offset, 0, PRI_LOW, 0x1c, 0, 0, 0, temp62), 9398c2ecf20Sopenharmony_ci PWRITE(remote2_offset, 1, PRI_LOW, 0x1d, 0, 0, 0, temp62), 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci PWRITE(pwm1, 0, PRI_HIGH, 0x30, 0, 0, 0, u8), 9428c2ecf20Sopenharmony_ci PWRITE(pwm2, 1, PRI_HIGH, 0x31, 0, 0, 0, u8), 9438c2ecf20Sopenharmony_ci PWRITE(pwm3, 2, PRI_HIGH, 0x32, 0, 0, 0, u8), 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci PWRITE(pwm1_invert, 0, PRI_LOW, 0x5c, 0, 0x01, 4, bitmask), 9468c2ecf20Sopenharmony_ci PWRITE(pwm2_invert, 1, PRI_LOW, 0x5d, 0, 0x01, 4, bitmask), 9478c2ecf20Sopenharmony_ci PWRITE(pwm3_invert, 2, PRI_LOW, 0x5e, 0, 0x01, 4, bitmask), 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci PWRITEM(pwm1_enable, 0, PRI_LOW, VAA(0x5c, 0x5c, 0x62), VAA(0, 0, 0), 9508c2ecf20Sopenharmony_ci VAA(0x07, 0x01, 0x01), VAA(5, 3, 5), pwm_enable), 9518c2ecf20Sopenharmony_ci PWRITEM(pwm2_enable, 1, PRI_LOW, VAA(0x5d, 0x5d, 0x62), VAA(0, 0, 0), 9528c2ecf20Sopenharmony_ci VAA(0x07, 0x01, 0x01), VAA(5, 3, 6), pwm_enable), 9538c2ecf20Sopenharmony_ci PWRITEM(pwm3_enable, 2, PRI_LOW, VAA(0x5e, 0x5e, 0x62), VAA(0, 0, 0), 9548c2ecf20Sopenharmony_ci VAA(0x07, 0x01, 0x01), VAA(5, 3, 7), pwm_enable), 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci PWRITEM(pwm1_auto_channels, 0, PRI_LOW, VAA(0x5c, 0x5c), VAA(0, 0), 9578c2ecf20Sopenharmony_ci VAA(0x07, 0x01), VAA(5, 3), pwm_ac), 9588c2ecf20Sopenharmony_ci PWRITEM(pwm2_auto_channels, 1, PRI_LOW, VAA(0x5d, 0x5d), VAA(0, 0), 9598c2ecf20Sopenharmony_ci VAA(0x07, 0x01), VAA(5, 3), pwm_ac), 9608c2ecf20Sopenharmony_ci PWRITEM(pwm3_auto_channels, 2, PRI_LOW, VAA(0x5e, 0x5e), VAA(0, 0), 9618c2ecf20Sopenharmony_ci VAA(0x07, 0x01), VAA(5, 3), pwm_ac), 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci PWRITE(pwm1_auto_point1_pwm, 0, PRI_LOW, 0x64, 0, 0, 0, u8), 9648c2ecf20Sopenharmony_ci PWRITE(pwm2_auto_point1_pwm, 1, PRI_LOW, 0x65, 0, 0, 0, u8), 9658c2ecf20Sopenharmony_ci PWRITE(pwm3_auto_point1_pwm, 2, PRI_LOW, 0x66, 0, 0, 0, u8), 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci PWRITE(pwm1_auto_point2_pwm, 0, PRI_LOW, 0x38, 0, 0, 0, u8), 9688c2ecf20Sopenharmony_ci PWRITE(pwm2_auto_point2_pwm, 1, PRI_LOW, 0x39, 0, 0, 0, u8), 9698c2ecf20Sopenharmony_ci PWRITE(pwm3_auto_point2_pwm, 2, PRI_LOW, 0x3a, 0, 0, 0, u8), 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci PWRITE(pwm1_freq, 0, PRI_LOW, 0x5f, 0, 0x0f, 0, pwm_freq), 9728c2ecf20Sopenharmony_ci PWRITE(pwm2_freq, 1, PRI_LOW, 0x60, 0, 0x0f, 0, pwm_freq), 9738c2ecf20Sopenharmony_ci PWRITE(pwm3_freq, 2, PRI_LOW, 0x61, 0, 0x0f, 0, pwm_freq), 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci PREAD(pwm1_auto_zone_assigned, 0, PRI_LOW, 0, 0, 0x03, 2, bitmask), 9768c2ecf20Sopenharmony_ci PREAD(pwm2_auto_zone_assigned, 1, PRI_LOW, 0, 0, 0x03, 4, bitmask), 9778c2ecf20Sopenharmony_ci PREAD(pwm3_auto_zone_assigned, 2, PRI_LOW, 0, 0, 0x03, 6, bitmask), 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci PWRITE(pwm1_auto_spinup_time, 0, PRI_LOW, 0x5c, 0, 0x07, 0, pwm_ast), 9808c2ecf20Sopenharmony_ci PWRITE(pwm2_auto_spinup_time, 1, PRI_LOW, 0x5d, 0, 0x07, 0, pwm_ast), 9818c2ecf20Sopenharmony_ci PWRITE(pwm3_auto_spinup_time, 2, PRI_LOW, 0x5e, 0, 0x07, 0, pwm_ast), 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci PWRITE(peci_enable, 0, PRI_LOW, 0x40, 0, 0x01, 4, bitmask), 9848c2ecf20Sopenharmony_ci PWRITE(peci_avg, 0, PRI_LOW, 0x36, 0, 0x07, 0, bitmask), 9858c2ecf20Sopenharmony_ci PWRITE(peci_domain, 0, PRI_LOW, 0x36, 0, 0x01, 3, bitmask), 9868c2ecf20Sopenharmony_ci PWRITE(peci_legacy, 0, PRI_LOW, 0x36, 0, 0x01, 4, bitmask), 9878c2ecf20Sopenharmony_ci PWRITE(peci_diode, 0, PRI_LOW, 0x0e, 0, 0x07, 4, bitmask), 9888c2ecf20Sopenharmony_ci PWRITE(peci_4domain, 0, PRI_LOW, 0x0e, 0, 0x01, 4, bitmask), 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci}; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic struct asc7621_data *asc7621_update_device(struct device *dev) 9938c2ecf20Sopenharmony_ci{ 9948c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 9958c2ecf20Sopenharmony_ci struct asc7621_data *data = i2c_get_clientdata(client); 9968c2ecf20Sopenharmony_ci int i; 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ci/* 9998c2ecf20Sopenharmony_ci * The asc7621 chips guarantee consistent reads of multi-byte values 10008c2ecf20Sopenharmony_ci * regardless of the order of the reads. No special logic is needed 10018c2ecf20Sopenharmony_ci * so we can just read the registers in whatever order they appear 10028c2ecf20Sopenharmony_ci * in the asc7621_params array. 10038c2ecf20Sopenharmony_ci */ 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci mutex_lock(&data->update_lock); 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci /* Read all the high priority registers */ 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci if (!data->valid || 10108c2ecf20Sopenharmony_ci time_after(jiffies, data->last_high_reading + INTERVAL_HIGH)) { 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_register_priorities); i++) { 10138c2ecf20Sopenharmony_ci if (asc7621_register_priorities[i] == PRI_HIGH) { 10148c2ecf20Sopenharmony_ci data->reg[i] = 10158c2ecf20Sopenharmony_ci i2c_smbus_read_byte_data(client, i) & 0xff; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci data->last_high_reading = jiffies; 10198c2ecf20Sopenharmony_ci } /* last_reading */ 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci /* Read all the low priority registers. */ 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci if (!data->valid || 10248c2ecf20Sopenharmony_ci time_after(jiffies, data->last_low_reading + INTERVAL_LOW)) { 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { 10278c2ecf20Sopenharmony_ci if (asc7621_register_priorities[i] == PRI_LOW) { 10288c2ecf20Sopenharmony_ci data->reg[i] = 10298c2ecf20Sopenharmony_ci i2c_smbus_read_byte_data(client, i) & 0xff; 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci } 10328c2ecf20Sopenharmony_ci data->last_low_reading = jiffies; 10338c2ecf20Sopenharmony_ci } /* last_reading */ 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci data->valid = 1; 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci mutex_unlock(&data->update_lock); 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci return data; 10408c2ecf20Sopenharmony_ci} 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci/* 10438c2ecf20Sopenharmony_ci * Standard detection and initialization below 10448c2ecf20Sopenharmony_ci * 10458c2ecf20Sopenharmony_ci * Helper function that checks if an address is valid 10468c2ecf20Sopenharmony_ci * for a particular chip. 10478c2ecf20Sopenharmony_ci */ 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_cistatic inline int valid_address_for_chip(int chip_type, int address) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci int i; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci for (i = 0; asc7621_chips[chip_type].addresses[i] != I2C_CLIENT_END; 10548c2ecf20Sopenharmony_ci i++) { 10558c2ecf20Sopenharmony_ci if (asc7621_chips[chip_type].addresses[i] == address) 10568c2ecf20Sopenharmony_ci return 1; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci return 0; 10598c2ecf20Sopenharmony_ci} 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_cistatic void asc7621_init_client(struct i2c_client *client) 10628c2ecf20Sopenharmony_ci{ 10638c2ecf20Sopenharmony_ci int value; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci /* Warn if part was not "READY" */ 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci value = read_byte(client, 0x40); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci if (value & 0x02) { 10708c2ecf20Sopenharmony_ci dev_err(&client->dev, 10718c2ecf20Sopenharmony_ci "Client (%d,0x%02x) config is locked.\n", 10728c2ecf20Sopenharmony_ci i2c_adapter_id(client->adapter), client->addr); 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci if (!(value & 0x04)) { 10758c2ecf20Sopenharmony_ci dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n", 10768c2ecf20Sopenharmony_ci i2c_adapter_id(client->adapter), client->addr); 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci/* 10808c2ecf20Sopenharmony_ci * Start monitoring 10818c2ecf20Sopenharmony_ci * 10828c2ecf20Sopenharmony_ci * Try to clear LOCK, Set START, save everything else 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ci value = (value & ~0x02) | 0x01; 10858c2ecf20Sopenharmony_ci write_byte(client, 0x40, value & 0xff); 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci} 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_cistatic int 10908c2ecf20Sopenharmony_ciasc7621_probe(struct i2c_client *client) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci struct asc7621_data *data; 10938c2ecf20Sopenharmony_ci int i, err; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 10968c2ecf20Sopenharmony_ci return -EIO; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci data = devm_kzalloc(&client->dev, sizeof(struct asc7621_data), 10998c2ecf20Sopenharmony_ci GFP_KERNEL); 11008c2ecf20Sopenharmony_ci if (data == NULL) 11018c2ecf20Sopenharmony_ci return -ENOMEM; 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci i2c_set_clientdata(client, data); 11048c2ecf20Sopenharmony_ci mutex_init(&data->update_lock); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci /* Initialize the asc7621 chip */ 11078c2ecf20Sopenharmony_ci asc7621_init_client(client); 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci /* Create the sysfs entries */ 11108c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { 11118c2ecf20Sopenharmony_ci err = 11128c2ecf20Sopenharmony_ci device_create_file(&client->dev, 11138c2ecf20Sopenharmony_ci &(asc7621_params[i].sda.dev_attr)); 11148c2ecf20Sopenharmony_ci if (err) 11158c2ecf20Sopenharmony_ci goto exit_remove; 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci data->class_dev = hwmon_device_register(&client->dev); 11198c2ecf20Sopenharmony_ci if (IS_ERR(data->class_dev)) { 11208c2ecf20Sopenharmony_ci err = PTR_ERR(data->class_dev); 11218c2ecf20Sopenharmony_ci goto exit_remove; 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci return 0; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ciexit_remove: 11278c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { 11288c2ecf20Sopenharmony_ci device_remove_file(&client->dev, 11298c2ecf20Sopenharmony_ci &(asc7621_params[i].sda.dev_attr)); 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci return err; 11338c2ecf20Sopenharmony_ci} 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic int asc7621_detect(struct i2c_client *client, 11368c2ecf20Sopenharmony_ci struct i2c_board_info *info) 11378c2ecf20Sopenharmony_ci{ 11388c2ecf20Sopenharmony_ci struct i2c_adapter *adapter = client->adapter; 11398c2ecf20Sopenharmony_ci int company, verstep, chip_index; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 11428c2ecf20Sopenharmony_ci return -ENODEV; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci for (chip_index = FIRST_CHIP; chip_index <= LAST_CHIP; chip_index++) { 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci if (!valid_address_for_chip(chip_index, client->addr)) 11478c2ecf20Sopenharmony_ci continue; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci company = read_byte(client, 11508c2ecf20Sopenharmony_ci asc7621_chips[chip_index].company_reg); 11518c2ecf20Sopenharmony_ci verstep = read_byte(client, 11528c2ecf20Sopenharmony_ci asc7621_chips[chip_index].verstep_reg); 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci if (company == asc7621_chips[chip_index].company_id && 11558c2ecf20Sopenharmony_ci verstep == asc7621_chips[chip_index].verstep_id) { 11568c2ecf20Sopenharmony_ci strlcpy(info->type, asc7621_chips[chip_index].name, 11578c2ecf20Sopenharmony_ci I2C_NAME_SIZE); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci dev_info(&adapter->dev, "Matched %s at 0x%02x\n", 11608c2ecf20Sopenharmony_ci asc7621_chips[chip_index].name, client->addr); 11618c2ecf20Sopenharmony_ci return 0; 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci return -ENODEV; 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cistatic int asc7621_remove(struct i2c_client *client) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci struct asc7621_data *data = i2c_get_clientdata(client); 11718c2ecf20Sopenharmony_ci int i; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci hwmon_device_unregister(data->class_dev); 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { 11768c2ecf20Sopenharmony_ci device_remove_file(&client->dev, 11778c2ecf20Sopenharmony_ci &(asc7621_params[i].sda.dev_attr)); 11788c2ecf20Sopenharmony_ci } 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci return 0; 11818c2ecf20Sopenharmony_ci} 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_cistatic const struct i2c_device_id asc7621_id[] = { 11848c2ecf20Sopenharmony_ci {"asc7621", asc7621}, 11858c2ecf20Sopenharmony_ci {"asc7621a", asc7621a}, 11868c2ecf20Sopenharmony_ci {}, 11878c2ecf20Sopenharmony_ci}; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, asc7621_id); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_cistatic struct i2c_driver asc7621_driver = { 11928c2ecf20Sopenharmony_ci .class = I2C_CLASS_HWMON, 11938c2ecf20Sopenharmony_ci .driver = { 11948c2ecf20Sopenharmony_ci .name = "asc7621", 11958c2ecf20Sopenharmony_ci }, 11968c2ecf20Sopenharmony_ci .probe_new = asc7621_probe, 11978c2ecf20Sopenharmony_ci .remove = asc7621_remove, 11988c2ecf20Sopenharmony_ci .id_table = asc7621_id, 11998c2ecf20Sopenharmony_ci .detect = asc7621_detect, 12008c2ecf20Sopenharmony_ci .address_list = normal_i2c, 12018c2ecf20Sopenharmony_ci}; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_cistatic int __init sm_asc7621_init(void) 12048c2ecf20Sopenharmony_ci{ 12058c2ecf20Sopenharmony_ci int i, j; 12068c2ecf20Sopenharmony_ci/* 12078c2ecf20Sopenharmony_ci * Collect all the registers needed into a single array. 12088c2ecf20Sopenharmony_ci * This way, if a register isn't actually used for anything, 12098c2ecf20Sopenharmony_ci * we don't retrieve it. 12108c2ecf20Sopenharmony_ci */ 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { 12138c2ecf20Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(asc7621_params[i].msb); j++) 12148c2ecf20Sopenharmony_ci asc7621_register_priorities[asc7621_params[i].msb[j]] = 12158c2ecf20Sopenharmony_ci asc7621_params[i].priority; 12168c2ecf20Sopenharmony_ci for (j = 0; j < ARRAY_SIZE(asc7621_params[i].lsb); j++) 12178c2ecf20Sopenharmony_ci asc7621_register_priorities[asc7621_params[i].lsb[j]] = 12188c2ecf20Sopenharmony_ci asc7621_params[i].priority; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci return i2c_add_driver(&asc7621_driver); 12218c2ecf20Sopenharmony_ci} 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_cistatic void __exit sm_asc7621_exit(void) 12248c2ecf20Sopenharmony_ci{ 12258c2ecf20Sopenharmony_ci i2c_del_driver(&asc7621_driver); 12268c2ecf20Sopenharmony_ci} 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 12298c2ecf20Sopenharmony_ciMODULE_AUTHOR("George Joseph"); 12308c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Andigilog aSC7621 and aSC7621a driver"); 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_cimodule_init(sm_asc7621_init); 12338c2ecf20Sopenharmony_cimodule_exit(sm_asc7621_exit); 1234