Re: [PATCH v5 2/6] HID: Add Himax HX83102J touchscreen driver
From: Krzysztof Kozlowski <krzk@kernel.org>
Date: 2026-10-04 07:50:03
Also in:
linux-arm-kernel, linux-devicetree, linux-mediatek, lkml
On Sat, Oct 03, 2026 at 04:27:37PM +0200, Michał Kopeć wrote:
quoted hunk ↗ jump to hunk
+/** + * himax_spi_drv_probe - Probe function for the SPI driver + * @spi: Pointer to the spi_device structure + * + * This function is called when the SPI driver is probed. It initializes the + * himax_ts_data structure and assign the settings from spi device to + * himax_ts_data. The buffer for SPI transfer is allocate here. The SPI + * transfer settings also setup before any communication starts. + * + * Return: 0 on success, negative error code on failure + */ +static int himax_spi_drv_probe(struct spi_device *spi) +{ + int ret; + struct himax_ts_data *ts; + static struct himax_platform_data *pdata; + + dev_info(&spi->dev, "%s: Himax SPI driver probe\n", __func__);
NAK, that's not acceptable. We do not have such code upstream.
quoted hunk ↗ jump to hunk
+ ts = devm_kzalloc(&spi->dev, sizeof(struct himax_ts_data), GFP_KERNEL); + if (!ts) + return -ENOMEM; + if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) { + dev_err(ts->dev, "%s: Full duplex not supported by host\n", __func__);
Stop printing __func__ everywhere.
quoted hunk ↗ jump to hunk
+ return -EIO; + } + pdata = &ts->pdata; + ts->dev = &spi->dev; + if (!spi->irq) { + dev_err(ts->dev, "%s: no IRQ?\n", __func__); + return -EINVAL; + } + ts->himax_irq = spi->irq; + pdata->gpiod_rst = devm_gpiod_get(ts->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(pdata->gpiod_rst)) { + dev_err(ts->dev, "%s: gpio-rst value is not valid\n", __func__);
Syntax is return dev_err_probe
quoted hunk ↗ jump to hunk
+ return -EIO; + } + + spi->bits_per_word = 8; + spi->mode = SPI_MODE_3; + spi->cs_setup.value = HIMAX_SPI_CS_SETUP_TIME; + + ts->spi = spi; + /* + * The max_transfer_size is used to allocate the buffer for SPI transfer. + * The size should be given by the SPI master driver, but if not available + * then use the HIMAX_MAX_TP_EV_STACK_SZ as default. Which is the least size for + * each TP event data. + */ + if (spi->controller->max_transfer_size) + ts->spi_xfer_max_sz = spi->controller->max_transfer_size(spi); + else + ts->spi_xfer_max_sz = HIMAX_MAX_TP_EV_STACK_SZ; + + ts->spi_xfer_max_sz = min(ts->spi_xfer_max_sz, HIMAX_BUS_RW_MAX_LEN); + /* SPI full-duplex rx_buf and tx_buf should be equal */ + ts->xfer_rx_data = devm_kzalloc(ts->dev, ts->spi_xfer_max_sz, GFP_KERNEL); + if (!ts->xfer_rx_data) + return -ENOMEM; + + ts->xfer_tx_data = devm_kzalloc(ts->dev, ts->spi_xfer_max_sz, GFP_KERNEL); + if (!ts->xfer_tx_data) + return -ENOMEM; + + spin_lock_init(&ts->irq_lock); + mutex_init(&ts->rw_lock); + mutex_init(&ts->reg_lock); + dev_set_drvdata(&spi->dev, ts); + spi_set_drvdata(spi, ts); + + ts->probe_finish = false; + ts->initialized = false; + ts->ic_boot_done = false; + + ret = himax_platform_init(ts); + if (ret) { + dev_err(ts->dev, "%s: platform init failed\n", __func__); + return ret; + } + + ret = himax_chip_detect(ts); + if (ret) { + dev_err(ts->dev, "%s: IC detect failed\n", __func__); + return ret; + } + + ret = himax_chip_init(ts); + if (ret < 0) + return ret; + ts->probe_finish = true; + + return ret; + himax_platform_deinit(ts); +} + +/** + * himax_spi_drv_remove - Remove function for the SPI driver + * @spi: Pointer to the spi_device structure + * + * This function is called when the SPI driver is removed. It deinitializes the
Really? Can a remove callback be called in other context? Why are you explaining obvious parts?
quoted hunk ↗ jump to hunk
+ * himax_ts_data structure and free the resources allocated for the SPI + * communication. + */ +static void himax_spi_drv_remove(struct spi_device *spi) +{ + struct himax_ts_data *ts = spi_get_drvdata(spi); + + if (ts->probe_finish) { + if (ts->ic_boot_done) { + himax_int_enable(ts, false); + + if (ts->hid_probed) + himax_hid_remove(ts); + } + himax_platform_deinit(ts); + } +} + +/**
Really, why kerneldoc for standard functions?
quoted hunk ↗ jump to hunk
+ * himax_shutdown - Shutdown the touch screen + * @spi: Himax touch screen spi device + * + * This function is used to shutdown the touch screen. It will disable the + * interrupt, set the reset pin to activate state. Then remove the hid device.
Why are you describing what the code is doing? Drop all such comments. Look at other drivers how they do it.
quoted hunk ↗ jump to hunk
+ * + * Return: None + */ +static void himax_shutdown(struct spi_device *spi) +{ + struct himax_ts_data *ts = spi_get_drvdata(spi); + + if (!ts->initialized) { + dev_err(ts->dev, "%s: init not ready, skip!\n", __func__); + return; + } + + himax_int_enable(ts, false); + gpiod_set_value(ts->pdata.gpiod_rst, 1); + himax_power_deconfig(&ts->pdata); + himax_hid_remove(ts); +} + +#if defined(CONFIG_OF)
Drop
quoted hunk ↗ jump to hunk
+static const struct of_device_id himax_table[] = { + { .compatible = "himax,hx83102j" }, + {}, +}; +MODULE_DEVICE_TABLE(of, himax_table); +#endif + +static struct spi_driver himax_hid_over_spi_driver = { + .driver = { + .name = "hx83102j", + .owner = THIS_MODULE,
Drop, this is some ancient downstream code
+#if defined(CONFIG_OF)
Drop
quoted hunk ↗ jump to hunk
+ .of_match_table = of_match_ptr(himax_table), +#endif + }, + .probe = himax_spi_drv_probe, + .remove = himax_spi_drv_remove, + .shutdown = himax_shutdown, +}; + +static int __init himax_ic_init(void) +{ + return spi_register_driver(&himax_hid_over_spi_driver); +} + +static void __exit himax_ic_exit(void) +{ + spi_unregister_driver(&himax_hid_over_spi_driver); +} + +module_init(himax_ic_init); +module_exit(himax_ic_exit);
Why this is not standard module spi driver? It seems you upstream some old, vendor code. Don't. Instead take newest, reviewed mainline driver and customize it, so you will not repeat trivial issues we fixed 13 years ago like that owner thingy, wrong return messages, usage of __func__, not using dev_err_probe and even the kerneldoc. This is not how upstream drivers are written. Best regards, Krzysztof