Skip to content

Commit

Permalink
Update ITHC from module repo
Browse files Browse the repository at this point in the history
Changes:
 - Added some comments and fixed a few checkpatch warnings
 - Improved CPU latency QoS handling
 - Retry reading the report descriptor on error / timeout

Based on quo/ithc-linux@0b8b45d

Signed-off-by: Dorian Stoll <dorian.stoll@tmsp.io>
Patchset: ithc
  • Loading branch information
quo authored and qzed committed Oct 23, 2023
1 parent c119659 commit da50bc9
Show file tree
Hide file tree
Showing 7 changed files with 623 additions and 236 deletions.
94 changes: 64 additions & 30 deletions drivers/hid/ithc/ithc-debug.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause

#include "ithc.h"

void ithc_log_regs(struct ithc *ithc) {
if (!ithc->prev_regs) return;
u32 __iomem *cur = (__iomem void*)ithc->regs;
u32 *prev = (void*)ithc->prev_regs;
for (int i = 1024; i < sizeof *ithc->regs / 4; i++) {
void ithc_log_regs(struct ithc *ithc)
{
if (!ithc->prev_regs)
return;
u32 __iomem *cur = (__iomem void *)ithc->regs;
u32 *prev = (void *)ithc->prev_regs;
for (int i = 1024; i < sizeof(*ithc->regs) / 4; i++) {
u32 x = readl(cur + i);
if (x != prev[i]) {
pci_info(ithc->pci, "reg %04x: %08x -> %08x\n", i * 4, prev[i], x);
Expand All @@ -13,55 +17,79 @@ void ithc_log_regs(struct ithc *ithc) {
}
}

static ssize_t ithc_debugfs_cmd_write(struct file *f, const char __user *buf, size_t len, loff_t *offset) {
static ssize_t ithc_debugfs_cmd_write(struct file *f, const char __user *buf, size_t len,
loff_t *offset)
{
// Debug commands consist of a single letter followed by a list of numbers (decimal or
// hexadecimal, space-separated).
struct ithc *ithc = file_inode(f)->i_private;
char cmd[256];
if (!ithc || !ithc->pci) return -ENODEV;
if (!len) return -EINVAL;
if (len >= sizeof cmd) return -EINVAL;
if (copy_from_user(cmd, buf, len)) return -EFAULT;
if (!ithc || !ithc->pci)
return -ENODEV;
if (!len)
return -EINVAL;
if (len >= sizeof(cmd))
return -EINVAL;
if (copy_from_user(cmd, buf, len))
return -EFAULT;
cmd[len] = 0;
if (cmd[len-1] == '\n') cmd[len-1] = 0;
if (cmd[len-1] == '\n')
cmd[len-1] = 0;
pci_info(ithc->pci, "debug command: %s\n", cmd);

// Parse the list of arguments into a u32 array.
u32 n = 0;
const char *s = cmd + 1;
u32 a[32];
while (*s && *s != '\n') {
if (n >= ARRAY_SIZE(a)) return -EINVAL;
if (*s++ != ' ') return -EINVAL;
if (n >= ARRAY_SIZE(a))
return -EINVAL;
if (*s++ != ' ')
return -EINVAL;
char *e;
a[n++] = simple_strtoul(s, &e, 0);
if (e == s) return -EINVAL;
if (e == s)
return -EINVAL;
s = e;
}
ithc_log_regs(ithc);
switch(cmd[0]) {

// Execute the command.
switch (cmd[0]) {
case 'x': // reset
ithc_reset(ithc);
break;
case 'w': // write register: offset mask value
if (n != 3 || (a[0] & 3)) return -EINVAL;
pci_info(ithc->pci, "debug write 0x%04x = 0x%08x (mask 0x%08x)\n", a[0], a[2], a[1]);
if (n != 3 || (a[0] & 3))
return -EINVAL;
pci_info(ithc->pci, "debug write 0x%04x = 0x%08x (mask 0x%08x)\n",
a[0], a[2], a[1]);
bitsl(((__iomem u32 *)ithc->regs) + a[0] / 4, a[1], a[2]);
break;
case 'r': // read register: offset
if (n != 1 || (a[0] & 3)) return -EINVAL;
pci_info(ithc->pci, "debug read 0x%04x = 0x%08x\n", a[0], readl(((__iomem u32 *)ithc->regs) + a[0] / 4));
if (n != 1 || (a[0] & 3))
return -EINVAL;
pci_info(ithc->pci, "debug read 0x%04x = 0x%08x\n", a[0],
readl(((__iomem u32 *)ithc->regs) + a[0] / 4));
break;
case 's': // spi command: cmd offset len data...
// read config: s 4 0 64 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
// set touch cfg: s 6 12 4 XX
if (n < 3 || a[2] > (n - 3) * 4) return -EINVAL;
if (n < 3 || a[2] > (n - 3) * 4)
return -EINVAL;
pci_info(ithc->pci, "debug spi command %u with %u bytes of data\n", a[0], a[2]);
if (!CHECK(ithc_spi_command, ithc, a[0], a[1], a[2], a + 3))
for (u32 i = 0; i < (a[2] + 3) / 4; i++) pci_info(ithc->pci, "resp %u = 0x%08x\n", i, a[3+i]);
for (u32 i = 0; i < (a[2] + 3) / 4; i++)
pci_info(ithc->pci, "resp %u = 0x%08x\n", i, a[3+i]);
break;
case 'd': // dma command: cmd len data...
// get report descriptor: d 7 8 0 0
// enable multitouch: d 3 2 0x0105
if (n < 2 || a[1] > (n - 2) * 4) return -EINVAL;
if (n < 2 || a[1] > (n - 2) * 4)
return -EINVAL;
pci_info(ithc->pci, "debug dma command %u with %u bytes of data\n", a[0], a[1]);
if (ithc_dma_tx(ithc, a[0], a[1], a + 2)) pci_err(ithc->pci, "dma tx failed\n");
if (ithc_dma_tx(ithc, a[0], a[1], a + 2))
pci_err(ithc->pci, "dma tx failed\n");
break;
default:
return -EINVAL;
Expand All @@ -75,21 +103,27 @@ static const struct file_operations ithc_debugfops_cmd = {
.write = ithc_debugfs_cmd_write,
};

static void ithc_debugfs_devres_release(struct device *dev, void *res) {
static void ithc_debugfs_devres_release(struct device *dev, void *res)
{
struct dentry **dbgm = res;
if (*dbgm) debugfs_remove_recursive(*dbgm);
if (*dbgm)
debugfs_remove_recursive(*dbgm);
}

int ithc_debug_init(struct ithc *ithc) {
struct dentry **dbgm = devres_alloc(ithc_debugfs_devres_release, sizeof *dbgm, GFP_KERNEL);
if (!dbgm) return -ENOMEM;
int ithc_debug_init(struct ithc *ithc)
{
struct dentry **dbgm = devres_alloc(ithc_debugfs_devres_release, sizeof(*dbgm), GFP_KERNEL);
if (!dbgm)
return -ENOMEM;
devres_add(&ithc->pci->dev, dbgm);
struct dentry *dbg = debugfs_create_dir(DEVNAME, NULL);
if (IS_ERR(dbg)) return PTR_ERR(dbg);
if (IS_ERR(dbg))
return PTR_ERR(dbg);
*dbgm = dbg;

struct dentry *cmd = debugfs_create_file("cmd", 0220, dbg, ithc, &ithc_debugfops_cmd);
if (IS_ERR(cmd)) return PTR_ERR(cmd);
if (IS_ERR(cmd))
return PTR_ERR(cmd);

return 0;
}
Expand Down
Loading

0 comments on commit da50bc9

Please sign in to comment.