From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/pinctrl/pinctrl-single.c | 127 +++++++++++++++++++++++++---------------- 1 files changed, 77 insertions(+), 50 deletions(-) diff --git a/kernel/drivers/pinctrl/pinctrl-single.c b/kernel/drivers/pinctrl/pinctrl-single.c index c2f807b..22e4719 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); @@ -345,6 +372,8 @@ if (!pcs->fmask) return 0; function = pinmux_generic_get_function(pctldev, fselector); + if (!function) + return -EINVAL; func = function->data; if (!func) return -EINVAL; @@ -381,7 +410,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 +417,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 +586,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 +680,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 +728,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 +749,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 +975,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 +1027,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 +1161,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 +1174,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 +1183,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 +1195,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 +1281,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 +1370,9 @@ } return ret; } + /** + * struct pcs_interrupt * @reg: virtual address of interrupt register * @hwirq: hardware irq number * @irq: virtual irq number @@ -1362,6 +1387,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 +1470,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 +1518,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