module stuff (hwmon: check hardware state, spi: try to bind spidev stuff)

This commit is contained in:
Triss 2021-07-17 18:26:25 +02:00
parent 46227bacb0
commit 8f1f4b1ad0
3 changed files with 86 additions and 3 deletions

View File

@ -43,6 +43,7 @@ static umode_t dmj_hwmon_is_visible(const void *data, enum hwmon_sensor_types ty
uint32_t attr, int ch)
{
switch (attr) {
case hwmon_temp_type:
case hwmon_temp_input:
case hwmon_temp_min:
case hwmon_temp_max:
@ -112,19 +113,77 @@ static const struct hwmon_chip_info dmj_chip_info = {
.info = dmj_hwmon_info
};
static int dmj_hwmon_check_hw(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
uint16_t m1ver;
uint8_t curmode, m1feat;
const int ver_min = 0x0010, ver_max = 0x0010;
int ret = 0, len;
uint8_t *buf = NULL;
ret = dmj_transfer(pdev, DMJ_CMD_CFG_GET_CUR_MODE,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, (void**)&buf, &len);
ret = dmj_check_retval(ret, len, dev, "hwmon test 1", true, sizeof(curmode), sizeof(curmode));
if (ret < 0 || !buf) goto out;
curmode = buf[0];
kfree(buf); buf = NULL;
if (curmode != 0x1) {
dev_err(dev, "device must be in mode 1 for hwmon to work, but it is in mode %d\n", curmode);
ret = -EIO;
goto out;
}
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_VERSION,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, (void**)&buf, &len);
ret = dmj_check_retval(ret, len, dev, "hwmon test 2", true, sizeof(m1ver), sizeof(m1ver));
if (ret < 0 || !buf) goto out;
m1ver = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
kfree(buf); buf = NULL;
if (m1ver > ver_max || m1ver < ver_min) {
dev_err(dev, "bad mode 1 version %04x on device, must be between %04x and %04x\n",
m1ver, ver_min, ver_max);
ret = -EIO;
goto out;
}
ret = dmj_transfer(pdev, (1<<4) | DMJ_CMD_MODE_GET_FEATURES,
DMJ_XFER_FLAGS_PARSE_RESP, NULL, 0, (void**)&buf, &len);
ret = dmj_check_retval(ret, len, dev, "hwmon test 3", true, sizeof(m1feat), sizeof(m1feat));
if (ret < 0 || !buf) goto out;
m1feat = buf[0];
kfree(buf); buf = NULL;
if (!(m1feat & DMJ_FEATURE_MODE1_I2C)) {
dev_err(dev, "device's mode 1 does not support hwmon tempsensor\n");
ret = -EIO;
goto out;
}
ret = 0;
out:
return ret;
}
static int dmj_hwmon_probe(struct platform_device *pdev)
{
struct dmj_hwmon *dmjh;
struct device *dev = &pdev->dev;
int ret;
ret = dmj_hwmon_check_hw(pdev);
if (ret) {
dev_err(dev, "hw check failed: %d\n", ret);
return -ENODEV;
}
dmjh = devm_kzalloc(dev, sizeof(*dmjh), GFP_KERNEL);
if (!dmjh) return -ENOMEM;
dmjh->pdev = pdev;
/* TODO: check usb stuff? (mode1, tempsensor feature) */
platform_set_drvdata(pdev, dmjh);
dmjh->hwmon_dev = hwmon_device_register_with_info(dev, HWMON_NAME, dmjh,

View File

@ -224,7 +224,7 @@ static int dmj_i2c_check_hw(struct platform_device *pdev)
curmode = buf[0];
kfree(buf); buf = NULL;
if (curmode != 0x1) {
dev_err(dev, "device must be in mode 1 for ICD to work, but it is in mode %d\n", curmode);
dev_err(dev, "device must be in mode 1 for I2C to work, but it is in mode %d\n", curmode);
ret = -EIO;
goto out;
}

View File

@ -118,6 +118,8 @@ struct dmj_spi {
uint8_t cmdmap[32];
spinlock_t csmap_lock;
struct spi_board_info binfo[8];
};
static int dmj_check_retval_sp(int ret, int len, struct device *dev,
@ -169,6 +171,19 @@ static int devcaps_to_kernmode(uint16_t caps)
return ret;
}
static void caps_to_binfo(struct dmj_spi *dmjs, int busnum)
{
int i;
for (i = 0; i < dmjs->caps.num_cs; ++i) {
snprintf(dmjs->binfo[i].modalias, SPI_NAME_SIZE, "spidev");
dmjs->binfo[i].controller_data = dmjs;
dmjs->binfo[i].max_speed_hz = dmjs->caps.freq_max;
dmjs->binfo[i].bus_num = busnum;
dmjs->binfo[i].chip_select = i;
dmjs->binfo[i].mode = 0; /* shrug */
}
}
static void bufconv_to_le(void *dst, const void *src, size_t len_bytes, uint8_t bpw)
{
@ -867,6 +882,15 @@ static int dmj_spi_probe(struct platform_device *pdev)
goto err_dereg;
}
dev_info(dev, "SPI bus number is %d\n", spictl->bus_num);
caps_to_binfo(dmjs, spictl->bus_num);
for (i = 0; i < dmjs->caps.num_cs; ++i) {
if (!spi_new_device(spictl, &dmjs->binfo[i])) {
dev_warn(dev, "failed to create %s device %d\n", dmjs->binfo[i].modalias, i);
}
}
return dmj_spi_set_pinstate(dmjs, true);
err_dereg: