From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:46:07 +0000
Subject: [PATCH] add audio
---
kernel/drivers/pinctrl/pinctrl-single.c | 125 +++++++++++++++++++++++++----------------
1 files changed, 75 insertions(+), 50 deletions(-)
diff --git a/kernel/drivers/pinctrl/pinctrl-single.c b/kernel/drivers/pinctrl/pinctrl-single.c
index c2f807b..d139cd9 100644
--- a/kernel/drivers/pinctrl/pinctrl-single.c
+++ b/kernel/drivers/pinctrl/pinctrl-single.c
@@ -42,6 +42,7 @@
* struct pcs_func_vals - mux function register offset and value pair
* @reg: register virtual address
* @val: register value
+ * @mask: mask
*/
struct pcs_func_vals {
void __iomem *reg;
@@ -83,6 +84,8 @@
* @nvals: number of entries in vals array
* @pgnames: array of pingroup names the function uses
* @npgnames: number of pingroup names the function uses
+ * @conf: array of pin configurations
+ * @nconfs: number of pin configurations available
* @node: list node
*/
struct pcs_function {
@@ -267,20 +270,44 @@
writel(val, reg);
}
+static unsigned int pcs_pin_reg_offset_get(struct pcs_device *pcs,
+ unsigned int pin)
+{
+ unsigned int mux_bytes = pcs->width / BITS_PER_BYTE;
+
+ if (pcs->bits_per_mux) {
+ unsigned int pin_offset_bytes;
+
+ pin_offset_bytes = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
+ return (pin_offset_bytes / mux_bytes) * mux_bytes;
+ }
+
+ return pin * mux_bytes;
+}
+
+static unsigned int pcs_pin_shift_reg_get(struct pcs_device *pcs,
+ unsigned int pin)
+{
+ return (pin % (pcs->width / pcs->bits_per_pin)) * pcs->bits_per_pin;
+}
+
static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned pin)
{
struct pcs_device *pcs;
- unsigned val, mux_bytes;
+ unsigned int val;
unsigned long offset;
size_t pa;
pcs = pinctrl_dev_get_drvdata(pctldev);
- mux_bytes = pcs->width / BITS_PER_BYTE;
- offset = pin * mux_bytes;
+ offset = pcs_pin_reg_offset_get(pcs, pin);
val = pcs->read(pcs->base + offset);
+
+ if (pcs->bits_per_mux)
+ val &= pcs->fmask << pcs_pin_shift_reg_get(pcs, pin);
+
pa = pcs->res->start + offset;
seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME);
@@ -381,7 +408,6 @@
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_gpiofunc_range *frange = NULL;
struct list_head *pos, *tmp;
- int mux_bytes = 0;
unsigned data;
/* If function mask is null, return directly. */
@@ -389,29 +415,27 @@
return -ENOTSUPP;
list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
+ u32 offset;
+
frange = list_entry(pos, struct pcs_gpiofunc_range, node);
if (pin >= frange->offset + frange->npins
|| pin < frange->offset)
continue;
- mux_bytes = pcs->width / BITS_PER_BYTE;
+
+ offset = pcs_pin_reg_offset_get(pcs, pin);
if (pcs->bits_per_mux) {
- int byte_num, offset, pin_shift;
-
- byte_num = (pcs->bits_per_pin * pin) / BITS_PER_BYTE;
- offset = (byte_num / mux_bytes) * mux_bytes;
- pin_shift = pin % (pcs->width / pcs->bits_per_pin) *
- pcs->bits_per_pin;
+ int pin_shift = pcs_pin_shift_reg_get(pcs, pin);
data = pcs->read(pcs->base + offset);
data &= ~(pcs->fmask << pin_shift);
data |= frange->gpiofunc << pin_shift;
pcs->write(data, pcs->base + offset);
} else {
- data = pcs->read(pcs->base + pin * mux_bytes);
+ data = pcs->read(pcs->base + offset);
data &= ~pcs->fmask;
data |= frange->gpiofunc;
- pcs->write(data, pcs->base + pin * mux_bytes);
+ pcs->write(data, pcs->base + offset);
}
break;
}
@@ -560,7 +584,7 @@
case PIN_CONFIG_BIAS_PULL_UP:
if (arg)
pcs_pinconf_clear_bias(pctldev, pin);
- /* fall through */
+ fallthrough;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
data &= ~func->conf[i].mask;
if (arg)
@@ -654,8 +678,7 @@
* @pcs: pcs driver instance
* @offset: register offset from base
*/
-static int pcs_add_pin(struct pcs_device *pcs, unsigned offset,
- unsigned pin_pos)
+static int pcs_add_pin(struct pcs_device *pcs, unsigned int offset)
{
struct pcs_soc_data *pcs_soc = &pcs->socdata;
struct pinctrl_pin_desc *pin;
@@ -703,7 +726,7 @@
mux_bytes = pcs->width / BITS_PER_BYTE;
- if (pcs->bits_per_mux) {
+ if (pcs->bits_per_mux && pcs->fmask) {
pcs->bits_per_pin = fls(pcs->fmask);
nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
num_pins_in_register = pcs->width / pcs->bits_per_pin;
@@ -724,17 +747,9 @@
for (i = 0; i < pcs->desc.npins; i++) {
unsigned offset;
int res;
- int byte_num;
- int pin_pos = 0;
- if (pcs->bits_per_mux) {
- byte_num = (pcs->bits_per_pin * i) / BITS_PER_BYTE;
- offset = (byte_num / mux_bytes) * mux_bytes;
- pin_pos = i % num_pins_in_register;
- } else {
- offset = i * mux_bytes;
- }
- res = pcs_add_pin(pcs, offset, pin_pos);
+ offset = pcs_pin_reg_offset_get(pcs, i);
+ res = pcs_add_pin(pcs, offset);
if (res < 0) {
dev_err(pcs->dev, "error adding pins: %i\n", res);
return res;
@@ -958,8 +973,7 @@
}
/**
- * smux_parse_one_pinctrl_entry() - parses a device tree mux entry
- * @pctldev: pin controller device
+ * pcs_parse_one_pinctrl_entry() - parses a device tree mux entry
* @pcs: pinctrl driver instance
* @np: device node of the mux entry
* @map: map entry
@@ -1011,25 +1025,32 @@
if (res)
return res;
- if (pinctrl_spec.args_count < 2) {
+ if (pinctrl_spec.args_count < 2 || pinctrl_spec.args_count > 3) {
dev_err(pcs->dev, "invalid args_count for spec: %i\n",
pinctrl_spec.args_count);
break;
}
- /* Index plus one value cell */
offset = pinctrl_spec.args[0];
vals[found].reg = pcs->base + offset;
- vals[found].val = pinctrl_spec.args[1];
- dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n",
- pinctrl_spec.np->name, offset, pinctrl_spec.args[1]);
+ switch (pinctrl_spec.args_count) {
+ case 2:
+ vals[found].val = pinctrl_spec.args[1];
+ break;
+ case 3:
+ vals[found].val = (pinctrl_spec.args[1] | pinctrl_spec.args[2]);
+ break;
+ }
+
+ dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x\n",
+ pinctrl_spec.np, offset, vals[found].val);
pin = pcs_get_pin_by_offset(pcs, offset);
if (pin < 0) {
dev_err(pcs->dev,
- "could not add functions for %s %ux\n",
- np->name, offset);
+ "could not add functions for %pOFn %ux\n",
+ np, offset);
break;
}
pins[found++] = pin;
@@ -1138,8 +1159,8 @@
val = pinctrl_spec.args[1];
mask = pinctrl_spec.args[2];
- dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n",
- pinctrl_spec.np->name, offset, val, mask);
+ dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x mask: 0x%x\n",
+ pinctrl_spec.np, offset, val, mask);
/* Parse pins in each row from LSB */
while (mask) {
@@ -1151,8 +1172,8 @@
if ((mask & mask_pos) == 0) {
dev_err(pcs->dev,
- "Invalid mask for %s at 0x%x\n",
- np->name, offset);
+ "Invalid mask for %pOFn at 0x%x\n",
+ np, offset);
break;
}
@@ -1160,8 +1181,8 @@
if (submask != mask_pos) {
dev_warn(pcs->dev,
- "Invalid submask 0x%x for %s at 0x%x\n",
- submask, np->name, offset);
+ "Invalid submask 0x%x for %pOFn at 0x%x\n",
+ submask, np, offset);
continue;
}
@@ -1172,8 +1193,8 @@
pin = pcs_get_pin_by_offset(pcs, offset);
if (pin < 0) {
dev_err(pcs->dev,
- "could not add functions for %s %ux\n",
- np->name, offset);
+ "could not add functions for %pOFn %ux\n",
+ np, offset);
break;
}
pins[found++] = pin + pin_num_from_lsb;
@@ -1258,16 +1279,16 @@
ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map,
num_maps, pgnames);
if (ret < 0) {
- dev_err(pcs->dev, "no pins entries for %s\n",
- np_config->name);
+ dev_err(pcs->dev, "no pins entries for %pOFn\n",
+ np_config);
goto free_pgnames;
}
} else {
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map,
num_maps, pgnames);
if (ret < 0) {
- dev_err(pcs->dev, "no pins entries for %s\n",
- np_config->name);
+ dev_err(pcs->dev, "no pins entries for %pOFn\n",
+ np_config);
goto free_pgnames;
}
}
@@ -1347,7 +1368,9 @@
}
return ret;
}
+
/**
+ * struct pcs_interrupt
* @reg: virtual address of interrupt register
* @hwirq: hardware irq number
* @irq: virtual irq number
@@ -1362,6 +1385,9 @@
/**
* pcs_irq_set() - enables or disables an interrupt
+ * @pcs_soc: SoC specific settings
+ * @irq: interrupt
+ * @enable: enable or disable the interrupt
*
* Note that this currently assumes one interrupt per pinctrl
* register that is typically used for wake-up events.
@@ -1442,7 +1468,7 @@
/**
* pcs_irq_handle() - common interrupt handler
- * @pcs_irq: interrupt data
+ * @pcs_soc: SoC specific settings
*
* Note that this currently assumes we have one interrupt bit per
* mux register. This interrupt is typically used for wake-up events.
@@ -1490,7 +1516,6 @@
/**
* pcs_irq_handle() - handler for the dedicated chained interrupt case
- * @irq: interrupt
* @desc: interrupt descriptor
*
* Use this if you have a separate interrupt for each
--
Gitblit v1.6.2