--- /dev/null
+From 0065390921085a7d416a5333356bf6264a309d76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 22 Sep 2022 07:20:56 -0400
+Subject: counter: 104-quad-8: Fix skipped IRQ lines during events
+ configuration
+
+From: William Breathitt Gray <william.gray@linaro.org>
+
+[ Upstream commit 2bc54aaa65d2126ae629919175708a28ce7ef06e ]
+
+IRQ trigger configuration is skipped if it has already been set before;
+however, the IRQ line still needs to be OR'd to irq_enabled because
+irq_enabled is reset for every events_configure call. This patch moves
+the irq_enabled OR operation update to before the irq_trigger check so
+that IRQ line enablement is not skipped.
+
+Fixes: c95cc0d95702 ("counter: 104-quad-8: Fix persistent enabled events bug")
+Cc: stable <stable@kernel.org>
+Link: https://lore.kernel.org/r/20220815122301.2750-1-william.gray@linaro.org/
+Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
+Link: https://lore.kernel.org/r/179eed11eaf225dbd908993b510df0c8f67b1230.1663844776.git.william.gray@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/104-quad-8.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
+index 62c2b7ac4339..4407203e0c9b 100644
+--- a/drivers/counter/104-quad-8.c
++++ b/drivers/counter/104-quad-8.c
+@@ -449,6 +449,9 @@ static int quad8_events_configure(struct counter_device *counter)
+ return -EINVAL;
+ }
+
++ /* Enable IRQ line */
++ irq_enabled |= BIT(event_node->channel);
++
+ /* Skip configuration if it is the same as previously set */
+ if (priv->irq_trigger[event_node->channel] == next_irq_trigger)
+ continue;
+@@ -462,9 +465,6 @@ static int quad8_events_configure(struct counter_device *counter)
+ priv->irq_trigger[event_node->channel] << 3;
+ iowrite8(QUAD8_CTR_IOR | ior_cfg,
+ &priv->reg->channel[event_node->channel].control);
+-
+- /* Enable IRQ line */
+- irq_enabled |= BIT(event_node->channel);
+ }
+
+ iowrite8(irq_enabled, &priv->reg->index_interrupt);
+--
+2.35.1
+
--- /dev/null
+From 5ea881f1eafbc400c3fd912ad3f5e0e6e3713e03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 12:07:14 -0400
+Subject: counter: 104-quad-8: Implement and utilize register structures
+
+From: William Breathitt Gray <william.gray@linaro.org>
+
+[ Upstream commit daae1ee572d1f99daddef26afe6c6fc7aeea741d ]
+
+Reduce magic numbers and improve code readability by implementing and
+utilizing named register data structures.
+
+Link: https://lore.kernel.org/r/20220707171709.36010-1-william.gray@linaro.org/
+Cc: Syed Nayyar Waris <syednwaris@gmail.com>
+Tested-by: Fred Eckert <Frede@cmslaser.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
+Link: https://lore.kernel.org/r/285fdc7c03892251f50bdbf2c28c19998243a6a3.1657813472.git.william.gray@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 2bc54aaa65d2 ("counter: 104-quad-8: Fix skipped IRQ lines during events configuration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/104-quad-8.c | 166 ++++++++++++++++++++---------------
+ 1 file changed, 93 insertions(+), 73 deletions(-)
+
+diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
+index 43dde9abfdcf..62c2b7ac4339 100644
+--- a/drivers/counter/104-quad-8.c
++++ b/drivers/counter/104-quad-8.c
+@@ -33,6 +33,36 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
+
+ #define QUAD8_NUM_COUNTERS 8
+
++/**
++ * struct channel_reg - channel register structure
++ * @data: Count data
++ * @control: Channel flags and control
++ */
++struct channel_reg {
++ u8 data;
++ u8 control;
++};
++
++/**
++ * struct quad8_reg - device register structure
++ * @channel: quadrature counter data and control
++ * @interrupt_status: channel interrupt status
++ * @channel_oper: enable/reset counters and interrupt functions
++ * @index_interrupt: enable channel interrupts
++ * @reserved: reserved for Factory Use
++ * @index_input_levels: index signal logical input level
++ * @cable_status: differential encoder cable status
++ */
++struct quad8_reg {
++ struct channel_reg channel[QUAD8_NUM_COUNTERS];
++ u8 interrupt_status;
++ u8 channel_oper;
++ u8 index_interrupt;
++ u8 reserved[3];
++ u8 index_input_levels;
++ u8 cable_status;
++};
++
+ /**
+ * struct quad8 - device private data structure
+ * @lock: lock to prevent clobbering device states during R/W ops
+@@ -48,7 +78,7 @@ MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
+ * @synchronous_mode: array of index function synchronous mode configurations
+ * @index_polarity: array of index function polarity configurations
+ * @cable_fault_enable: differential encoder cable status enable configurations
+- * @base: base port address of the device
++ * @reg: I/O address offset for the device registers
+ */
+ struct quad8 {
+ spinlock_t lock;
+@@ -63,14 +93,9 @@ struct quad8 {
+ unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
+ unsigned int index_polarity[QUAD8_NUM_COUNTERS];
+ unsigned int cable_fault_enable;
+- void __iomem *base;
++ struct quad8_reg __iomem *reg;
+ };
+
+-#define QUAD8_REG_INTERRUPT_STATUS 0x10
+-#define QUAD8_REG_CHAN_OP 0x11
+-#define QUAD8_REG_INDEX_INTERRUPT 0x12
+-#define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
+-#define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17
+ /* Borrow Toggle flip-flop */
+ #define QUAD8_FLAG_BT BIT(0)
+ /* Carry Toggle flip-flop */
+@@ -118,8 +143,7 @@ static int quad8_signal_read(struct counter_device *counter,
+ if (signal->id < 16)
+ return -EINVAL;
+
+- state = ioread8(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS) &
+- BIT(signal->id - 16);
++ state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16);
+
+ *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
+
+@@ -130,14 +154,14 @@ static int quad8_count_read(struct counter_device *counter,
+ struct counter_count *count, u64 *val)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- void __iomem *const base_offset = priv->base + 2 * count->id;
++ struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
+ unsigned int flags;
+ unsigned int borrow;
+ unsigned int carry;
+ unsigned long irqflags;
+ int i;
+
+- flags = ioread8(base_offset + 1);
++ flags = ioread8(&chan->control);
+ borrow = flags & QUAD8_FLAG_BT;
+ carry = !!(flags & QUAD8_FLAG_CT);
+
+@@ -148,10 +172,10 @@ static int quad8_count_read(struct counter_device *counter,
+
+ /* Reset Byte Pointer; transfer Counter to Output Latch */
+ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
+- base_offset + 1);
++ &chan->control);
+
+ for (i = 0; i < 3; i++)
+- *val |= (unsigned long)ioread8(base_offset) << (8 * i);
++ *val |= (unsigned long)ioread8(&chan->data) << (8 * i);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -162,7 +186,7 @@ static int quad8_count_write(struct counter_device *counter,
+ struct counter_count *count, u64 val)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- void __iomem *const base_offset = priv->base + 2 * count->id;
++ struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
+ unsigned long irqflags;
+ int i;
+
+@@ -173,27 +197,27 @@ static int quad8_count_write(struct counter_device *counter,
+ spin_lock_irqsave(&priv->lock, irqflags);
+
+ /* Reset Byte Pointer */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+
+ /* Counter can only be set via Preset Register */
+ for (i = 0; i < 3; i++)
+- iowrite8(val >> (8 * i), base_offset);
++ iowrite8(val >> (8 * i), &chan->data);
+
+ /* Transfer Preset Register to Counter */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control);
+
+ /* Reset Byte Pointer */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+
+ /* Set Preset Register back to original value */
+ val = priv->preset[count->id];
+ for (i = 0; i < 3; i++)
+- iowrite8(val >> (8 * i), base_offset);
++ iowrite8(val >> (8 * i), &chan->data);
+
+ /* Reset Borrow, Carry, Compare, and Sign flags */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
+ /* Reset Error flag */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -246,7 +270,7 @@ static int quad8_function_write(struct counter_device *counter,
+ unsigned int *const quadrature_mode = priv->quadrature_mode + id;
+ unsigned int *const scale = priv->quadrature_scale + id;
+ unsigned int *const synchronous_mode = priv->synchronous_mode + id;
+- void __iomem *const base_offset = priv->base + 2 * id + 1;
++ u8 __iomem *const control = &priv->reg->channel[id].control;
+ unsigned long irqflags;
+ unsigned int mode_cfg;
+ unsigned int idr_cfg;
+@@ -266,7 +290,7 @@ static int quad8_function_write(struct counter_device *counter,
+ if (*synchronous_mode) {
+ *synchronous_mode = 0;
+ /* Disable synchronous function mode */
+- iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+ }
+ } else {
+ *quadrature_mode = 1;
+@@ -292,7 +316,7 @@ static int quad8_function_write(struct counter_device *counter,
+ }
+
+ /* Load mode configuration to Counter Mode Register */
+- iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset);
++ iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -305,7 +329,7 @@ static int quad8_direction_read(struct counter_device *counter,
+ {
+ const struct quad8 *const priv = counter_priv(counter);
+ unsigned int ud_flag;
+- void __iomem *const flag_addr = priv->base + 2 * count->id + 1;
++ u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
+
+ /* U/D flag: nonzero = up, zero = down */
+ ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
+@@ -402,7 +426,6 @@ static int quad8_events_configure(struct counter_device *counter)
+ struct counter_event_node *event_node;
+ unsigned int next_irq_trigger;
+ unsigned long ior_cfg;
+- void __iomem *base_offset;
+
+ spin_lock_irqsave(&priv->lock, irqflags);
+
+@@ -437,14 +460,14 @@ static int quad8_events_configure(struct counter_device *counter)
+ ior_cfg = priv->ab_enable[event_node->channel] |
+ priv->preset_enable[event_node->channel] << 1 |
+ priv->irq_trigger[event_node->channel] << 3;
+- base_offset = priv->base + 2 * event_node->channel + 1;
+- iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IOR | ior_cfg,
++ &priv->reg->channel[event_node->channel].control);
+
+ /* Enable IRQ line */
+ irq_enabled |= BIT(event_node->channel);
+ }
+
+- iowrite8(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT);
++ iowrite8(irq_enabled, &priv->reg->index_interrupt);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -508,7 +531,7 @@ static int quad8_index_polarity_set(struct counter_device *counter,
+ {
+ struct quad8 *const priv = counter_priv(counter);
+ const size_t channel_id = signal->id - 16;
+- void __iomem *const base_offset = priv->base + 2 * channel_id + 1;
++ u8 __iomem *const control = &priv->reg->channel[channel_id].control;
+ unsigned long irqflags;
+ unsigned int idr_cfg = index_polarity << 1;
+
+@@ -519,7 +542,7 @@ static int quad8_index_polarity_set(struct counter_device *counter,
+ priv->index_polarity[channel_id] = index_polarity;
+
+ /* Load Index Control configuration to Index Control Register */
+- iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -549,7 +572,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
+ {
+ struct quad8 *const priv = counter_priv(counter);
+ const size_t channel_id = signal->id - 16;
+- void __iomem *const base_offset = priv->base + 2 * channel_id + 1;
++ u8 __iomem *const control = &priv->reg->channel[channel_id].control;
+ unsigned long irqflags;
+ unsigned int idr_cfg = synchronous_mode;
+
+@@ -566,7 +589,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
+ priv->synchronous_mode[channel_id] = synchronous_mode;
+
+ /* Load Index Control configuration to Index Control Register */
+- iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IDR | idr_cfg, control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -614,7 +637,7 @@ static int quad8_count_mode_write(struct counter_device *counter,
+ struct quad8 *const priv = counter_priv(counter);
+ unsigned int count_mode;
+ unsigned int mode_cfg;
+- void __iomem *const base_offset = priv->base + 2 * count->id + 1;
++ u8 __iomem *const control = &priv->reg->channel[count->id].control;
+ unsigned long irqflags;
+
+ /* Map Generic Counter count mode to 104-QUAD-8 count mode */
+@@ -648,7 +671,7 @@ static int quad8_count_mode_write(struct counter_device *counter,
+ mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
+
+ /* Load mode configuration to Counter Mode Register */
+- iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset);
++ iowrite8(QUAD8_CTR_CMR | mode_cfg, control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -669,7 +692,7 @@ static int quad8_count_enable_write(struct counter_device *counter,
+ struct counter_count *count, u8 enable)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- void __iomem *const base_offset = priv->base + 2 * count->id;
++ u8 __iomem *const control = &priv->reg->channel[count->id].control;
+ unsigned long irqflags;
+ unsigned int ior_cfg;
+
+@@ -681,7 +704,7 @@ static int quad8_count_enable_write(struct counter_device *counter,
+ priv->irq_trigger[count->id] << 3;
+
+ /* Load I/O control configuration */
+- iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
++ iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -697,9 +720,9 @@ static int quad8_error_noise_get(struct counter_device *counter,
+ struct counter_count *count, u32 *noise_error)
+ {
+ const struct quad8 *const priv = counter_priv(counter);
+- void __iomem *const base_offset = priv->base + 2 * count->id + 1;
++ u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control;
+
+- *noise_error = !!(ioread8(base_offset) & QUAD8_FLAG_E);
++ *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E);
+
+ return 0;
+ }
+@@ -717,17 +740,17 @@ static int quad8_count_preset_read(struct counter_device *counter,
+ static void quad8_preset_register_set(struct quad8 *const priv, const int id,
+ const unsigned int preset)
+ {
+- void __iomem *const base_offset = priv->base + 2 * id;
++ struct channel_reg __iomem *const chan = priv->reg->channel + id;
+ int i;
+
+ priv->preset[id] = preset;
+
+ /* Reset Byte Pointer */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+
+ /* Set Preset Register */
+ for (i = 0; i < 3; i++)
+- iowrite8(preset >> (8 * i), base_offset);
++ iowrite8(preset >> (8 * i), &chan->data);
+ }
+
+ static int quad8_count_preset_write(struct counter_device *counter,
+@@ -816,7 +839,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter,
+ u8 preset_enable)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- void __iomem *const base_offset = priv->base + 2 * count->id + 1;
++ u8 __iomem *const control = &priv->reg->channel[count->id].control;
+ unsigned long irqflags;
+ unsigned int ior_cfg;
+
+@@ -831,7 +854,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter,
+ priv->irq_trigger[count->id] << 3;
+
+ /* Load I/O control configuration to Input / Output Control Register */
+- iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IOR | ior_cfg, control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -858,7 +881,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter,
+ }
+
+ /* Logic 0 = cable fault */
+- status = ioread8(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
++ status = ioread8(&priv->reg->cable_status);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -899,8 +922,7 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
+ /* Enable is active low in Differential Encoder Cable Status register */
+ cable_fault_enable = ~priv->cable_fault_enable;
+
+- iowrite8(cable_fault_enable,
+- priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
++ iowrite8(cable_fault_enable, &priv->reg->cable_status);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -924,7 +946,7 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
+ {
+ struct quad8 *const priv = counter_priv(counter);
+ const size_t channel_id = signal->id / 2;
+- void __iomem *const base_offset = priv->base + 2 * channel_id;
++ struct channel_reg __iomem *const chan = priv->reg->channel + channel_id;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&priv->lock, irqflags);
+@@ -932,12 +954,12 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
+ priv->fck_prescaler[channel_id] = prescaler;
+
+ /* Reset Byte Pointer */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+
+ /* Set filter clock factor */
+- iowrite8(prescaler, base_offset);
++ iowrite8(prescaler, &chan->data);
+ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
+- base_offset + 1);
++ &chan->control);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -1085,12 +1107,11 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
+ {
+ struct counter_device *counter = private;
+ struct quad8 *const priv = counter_priv(counter);
+- void __iomem *const base = priv->base;
+ unsigned long irq_status;
+ unsigned long channel;
+ u8 event;
+
+- irq_status = ioread8(base + QUAD8_REG_INTERRUPT_STATUS);
++ irq_status = ioread8(&priv->reg->interrupt_status);
+ if (!irq_status)
+ return IRQ_NONE;
+
+@@ -1119,36 +1140,36 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
+ }
+
+ /* Clear pending interrupts on device */
+- iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP);
++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
+
+ return IRQ_HANDLED;
+ }
+
+-static void quad8_init_counter(void __iomem *const base_offset)
++static void quad8_init_counter(struct channel_reg __iomem *const chan)
+ {
+ unsigned long i;
+
+ /* Reset Byte Pointer */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+ /* Reset filter clock factor */
+- iowrite8(0, base_offset);
++ iowrite8(0, &chan->data);
+ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
+- base_offset + 1);
++ &chan->control);
+ /* Reset Byte Pointer */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control);
+ /* Reset Preset Register */
+ for (i = 0; i < 3; i++)
+- iowrite8(0x00, base_offset);
++ iowrite8(0x00, &chan->data);
+ /* Reset Borrow, Carry, Compare, and Sign flags */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control);
+ /* Reset Error flag */
+- iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control);
+ /* Binary encoding; Normal count; non-quadrature mode */
+- iowrite8(QUAD8_CTR_CMR, base_offset + 1);
++ iowrite8(QUAD8_CTR_CMR, &chan->control);
+ /* Disable A and B inputs; preset on index; FLG1 as Carry */
+- iowrite8(QUAD8_CTR_IOR, base_offset + 1);
++ iowrite8(QUAD8_CTR_IOR, &chan->control);
+ /* Disable index function; negative index polarity */
+- iowrite8(QUAD8_CTR_IDR, base_offset + 1);
++ iowrite8(QUAD8_CTR_IDR, &chan->control);
+ }
+
+ static int quad8_probe(struct device *dev, unsigned int id)
+@@ -1169,8 +1190,8 @@ static int quad8_probe(struct device *dev, unsigned int id)
+ return -ENOMEM;
+ priv = counter_priv(counter);
+
+- priv->base = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
+- if (!priv->base)
++ priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
++ if (!priv->reg)
+ return -ENOMEM;
+
+ /* Initialize Counter device and driver data */
+@@ -1185,17 +1206,16 @@ static int quad8_probe(struct device *dev, unsigned int id)
+ spin_lock_init(&priv->lock);
+
+ /* Reset Index/Interrupt Register */
+- iowrite8(0x00, priv->base + QUAD8_REG_INDEX_INTERRUPT);
++ iowrite8(0x00, &priv->reg->index_interrupt);
+ /* Reset all counters and disable interrupt function */
+- iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, priv->base + QUAD8_REG_CHAN_OP);
++ iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper);
+ /* Set initial configuration for all counters */
+ for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
+- quad8_init_counter(priv->base + 2 * i);
++ quad8_init_counter(priv->reg->channel + i);
+ /* Disable Differential Encoder Cable Status for all channels */
+- iowrite8(0xFF, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
++ iowrite8(0xFF, &priv->reg->cable_status);
+ /* Enable all counters and enable interrupt function */
+- iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC,
+- priv->base + QUAD8_REG_CHAN_OP);
++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper);
+
+ err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
+ IRQF_SHARED, counter->name, counter);
+--
+2.35.1
+
--- /dev/null
+From 25ebedbb5ed2470217a480bf5fe7f16ccf1867ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 12:07:13 -0400
+Subject: counter: 104-quad-8: Utilize iomap interface
+
+From: William Breathitt Gray <william.gray@linaro.org>
+
+[ Upstream commit b6e9cded90d46b1066a1ca260d8b5ecf67787aba ]
+
+This driver doesn't need to access I/O ports directly via inb()/outb()
+and friends. This patch abstracts such access by calling ioport_map()
+to enable the use of more typical ioread8()/iowrite8() I/O memory
+accessor calls.
+
+Link: https://lore.kernel.org/r/861c003318dce3d2bef4061711643bb04f5ec14f.1652201921.git.william.gray@linaro.org
+Cc: Syed Nayyar Waris <syednwaris@gmail.com>
+Suggested-by: David Laight <David.Laight@ACULAB.COM>
+Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: William Breathitt Gray <william.gray@linaro.org>
+Link: https://lore.kernel.org/r/e971b897cacfac4cb2eca478f5533d2875f5cadd.1657813472.git.william.gray@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 2bc54aaa65d2 ("counter: 104-quad-8: Fix skipped IRQ lines during events configuration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/counter/104-quad-8.c | 169 ++++++++++++++++++-----------------
+ 1 file changed, 89 insertions(+), 80 deletions(-)
+
+diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
+index a17e51d65aca..43dde9abfdcf 100644
+--- a/drivers/counter/104-quad-8.c
++++ b/drivers/counter/104-quad-8.c
+@@ -63,7 +63,7 @@ struct quad8 {
+ unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
+ unsigned int index_polarity[QUAD8_NUM_COUNTERS];
+ unsigned int cable_fault_enable;
+- unsigned int base;
++ void __iomem *base;
+ };
+
+ #define QUAD8_REG_INTERRUPT_STATUS 0x10
+@@ -118,8 +118,8 @@ static int quad8_signal_read(struct counter_device *counter,
+ if (signal->id < 16)
+ return -EINVAL;
+
+- state = inb(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS)
+- & BIT(signal->id - 16);
++ state = ioread8(priv->base + QUAD8_REG_INDEX_INPUT_LEVELS) &
++ BIT(signal->id - 16);
+
+ *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
+
+@@ -130,14 +130,14 @@ static int quad8_count_read(struct counter_device *counter,
+ struct counter_count *count, u64 *val)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- const int base_offset = priv->base + 2 * count->id;
++ void __iomem *const base_offset = priv->base + 2 * count->id;
+ unsigned int flags;
+ unsigned int borrow;
+ unsigned int carry;
+ unsigned long irqflags;
+ int i;
+
+- flags = inb(base_offset + 1);
++ flags = ioread8(base_offset + 1);
+ borrow = flags & QUAD8_FLAG_BT;
+ carry = !!(flags & QUAD8_FLAG_CT);
+
+@@ -147,11 +147,11 @@ static int quad8_count_read(struct counter_device *counter,
+ spin_lock_irqsave(&priv->lock, irqflags);
+
+ /* Reset Byte Pointer; transfer Counter to Output Latch */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
+- base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
++ base_offset + 1);
+
+ for (i = 0; i < 3; i++)
+- *val |= (unsigned long)inb(base_offset) << (8 * i);
++ *val |= (unsigned long)ioread8(base_offset) << (8 * i);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -162,7 +162,7 @@ static int quad8_count_write(struct counter_device *counter,
+ struct counter_count *count, u64 val)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- const int base_offset = priv->base + 2 * count->id;
++ void __iomem *const base_offset = priv->base + 2 * count->id;
+ unsigned long irqflags;
+ int i;
+
+@@ -173,27 +173,27 @@ static int quad8_count_write(struct counter_device *counter,
+ spin_lock_irqsave(&priv->lock, irqflags);
+
+ /* Reset Byte Pointer */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+
+ /* Counter can only be set via Preset Register */
+ for (i = 0; i < 3; i++)
+- outb(val >> (8 * i), base_offset);
++ iowrite8(val >> (8 * i), base_offset);
+
+ /* Transfer Preset Register to Counter */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, base_offset + 1);
+
+ /* Reset Byte Pointer */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+
+ /* Set Preset Register back to original value */
+ val = priv->preset[count->id];
+ for (i = 0; i < 3; i++)
+- outb(val >> (8 * i), base_offset);
++ iowrite8(val >> (8 * i), base_offset);
+
+ /* Reset Borrow, Carry, Compare, and Sign flags */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
+ /* Reset Error flag */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -246,7 +246,7 @@ static int quad8_function_write(struct counter_device *counter,
+ unsigned int *const quadrature_mode = priv->quadrature_mode + id;
+ unsigned int *const scale = priv->quadrature_scale + id;
+ unsigned int *const synchronous_mode = priv->synchronous_mode + id;
+- const int base_offset = priv->base + 2 * id + 1;
++ void __iomem *const base_offset = priv->base + 2 * id + 1;
+ unsigned long irqflags;
+ unsigned int mode_cfg;
+ unsigned int idr_cfg;
+@@ -266,7 +266,7 @@ static int quad8_function_write(struct counter_device *counter,
+ if (*synchronous_mode) {
+ *synchronous_mode = 0;
+ /* Disable synchronous function mode */
+- outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset);
+ }
+ } else {
+ *quadrature_mode = 1;
+@@ -292,7 +292,7 @@ static int quad8_function_write(struct counter_device *counter,
+ }
+
+ /* Load mode configuration to Counter Mode Register */
+- outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
++ iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -305,10 +305,10 @@ static int quad8_direction_read(struct counter_device *counter,
+ {
+ const struct quad8 *const priv = counter_priv(counter);
+ unsigned int ud_flag;
+- const unsigned int flag_addr = priv->base + 2 * count->id + 1;
++ void __iomem *const flag_addr = priv->base + 2 * count->id + 1;
+
+ /* U/D flag: nonzero = up, zero = down */
+- ud_flag = inb(flag_addr) & QUAD8_FLAG_UD;
++ ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD;
+
+ *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD :
+ COUNTER_COUNT_DIRECTION_BACKWARD;
+@@ -402,7 +402,7 @@ static int quad8_events_configure(struct counter_device *counter)
+ struct counter_event_node *event_node;
+ unsigned int next_irq_trigger;
+ unsigned long ior_cfg;
+- unsigned long base_offset;
++ void __iomem *base_offset;
+
+ spin_lock_irqsave(&priv->lock, irqflags);
+
+@@ -438,13 +438,13 @@ static int quad8_events_configure(struct counter_device *counter)
+ priv->preset_enable[event_node->channel] << 1 |
+ priv->irq_trigger[event_node->channel] << 3;
+ base_offset = priv->base + 2 * event_node->channel + 1;
+- outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset);
+
+ /* Enable IRQ line */
+ irq_enabled |= BIT(event_node->channel);
+ }
+
+- outb(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT);
++ iowrite8(irq_enabled, priv->base + QUAD8_REG_INDEX_INTERRUPT);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -508,7 +508,7 @@ static int quad8_index_polarity_set(struct counter_device *counter,
+ {
+ struct quad8 *const priv = counter_priv(counter);
+ const size_t channel_id = signal->id - 16;
+- const int base_offset = priv->base + 2 * channel_id + 1;
++ void __iomem *const base_offset = priv->base + 2 * channel_id + 1;
+ unsigned long irqflags;
+ unsigned int idr_cfg = index_polarity << 1;
+
+@@ -519,7 +519,7 @@ static int quad8_index_polarity_set(struct counter_device *counter,
+ priv->index_polarity[channel_id] = index_polarity;
+
+ /* Load Index Control configuration to Index Control Register */
+- outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -549,7 +549,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
+ {
+ struct quad8 *const priv = counter_priv(counter);
+ const size_t channel_id = signal->id - 16;
+- const int base_offset = priv->base + 2 * channel_id + 1;
++ void __iomem *const base_offset = priv->base + 2 * channel_id + 1;
+ unsigned long irqflags;
+ unsigned int idr_cfg = synchronous_mode;
+
+@@ -566,7 +566,7 @@ static int quad8_synchronous_mode_set(struct counter_device *counter,
+ priv->synchronous_mode[channel_id] = synchronous_mode;
+
+ /* Load Index Control configuration to Index Control Register */
+- outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IDR | idr_cfg, base_offset);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -614,7 +614,7 @@ static int quad8_count_mode_write(struct counter_device *counter,
+ struct quad8 *const priv = counter_priv(counter);
+ unsigned int count_mode;
+ unsigned int mode_cfg;
+- const int base_offset = priv->base + 2 * count->id + 1;
++ void __iomem *const base_offset = priv->base + 2 * count->id + 1;
+ unsigned long irqflags;
+
+ /* Map Generic Counter count mode to 104-QUAD-8 count mode */
+@@ -648,7 +648,7 @@ static int quad8_count_mode_write(struct counter_device *counter,
+ mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3;
+
+ /* Load mode configuration to Counter Mode Register */
+- outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
++ iowrite8(QUAD8_CTR_CMR | mode_cfg, base_offset);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -669,7 +669,7 @@ static int quad8_count_enable_write(struct counter_device *counter,
+ struct counter_count *count, u8 enable)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- const int base_offset = priv->base + 2 * count->id;
++ void __iomem *const base_offset = priv->base + 2 * count->id;
+ unsigned long irqflags;
+ unsigned int ior_cfg;
+
+@@ -681,7 +681,7 @@ static int quad8_count_enable_write(struct counter_device *counter,
+ priv->irq_trigger[count->id] << 3;
+
+ /* Load I/O control configuration */
+- outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
++ iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -697,9 +697,9 @@ static int quad8_error_noise_get(struct counter_device *counter,
+ struct counter_count *count, u32 *noise_error)
+ {
+ const struct quad8 *const priv = counter_priv(counter);
+- const int base_offset = priv->base + 2 * count->id + 1;
++ void __iomem *const base_offset = priv->base + 2 * count->id + 1;
+
+- *noise_error = !!(inb(base_offset) & QUAD8_FLAG_E);
++ *noise_error = !!(ioread8(base_offset) & QUAD8_FLAG_E);
+
+ return 0;
+ }
+@@ -717,17 +717,17 @@ static int quad8_count_preset_read(struct counter_device *counter,
+ static void quad8_preset_register_set(struct quad8 *const priv, const int id,
+ const unsigned int preset)
+ {
+- const unsigned int base_offset = priv->base + 2 * id;
++ void __iomem *const base_offset = priv->base + 2 * id;
+ int i;
+
+ priv->preset[id] = preset;
+
+ /* Reset Byte Pointer */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+
+ /* Set Preset Register */
+ for (i = 0; i < 3; i++)
+- outb(preset >> (8 * i), base_offset);
++ iowrite8(preset >> (8 * i), base_offset);
+ }
+
+ static int quad8_count_preset_write(struct counter_device *counter,
+@@ -816,7 +816,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter,
+ u8 preset_enable)
+ {
+ struct quad8 *const priv = counter_priv(counter);
+- const int base_offset = priv->base + 2 * count->id + 1;
++ void __iomem *const base_offset = priv->base + 2 * count->id + 1;
+ unsigned long irqflags;
+ unsigned int ior_cfg;
+
+@@ -831,7 +831,7 @@ static int quad8_count_preset_enable_write(struct counter_device *counter,
+ priv->irq_trigger[count->id] << 3;
+
+ /* Load I/O control configuration to Input / Output Control Register */
+- outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
++ iowrite8(QUAD8_CTR_IOR | ior_cfg, base_offset);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -858,7 +858,7 @@ static int quad8_signal_cable_fault_read(struct counter_device *counter,
+ }
+
+ /* Logic 0 = cable fault */
+- status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
++ status = ioread8(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -899,7 +899,8 @@ static int quad8_signal_cable_fault_enable_write(struct counter_device *counter,
+ /* Enable is active low in Differential Encoder Cable Status register */
+ cable_fault_enable = ~priv->cable_fault_enable;
+
+- outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
++ iowrite8(cable_fault_enable,
++ priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -923,7 +924,7 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
+ {
+ struct quad8 *const priv = counter_priv(counter);
+ const size_t channel_id = signal->id / 2;
+- const int base_offset = priv->base + 2 * channel_id;
++ void __iomem *const base_offset = priv->base + 2 * channel_id;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&priv->lock, irqflags);
+@@ -931,12 +932,12 @@ static int quad8_signal_fck_prescaler_write(struct counter_device *counter,
+ priv->fck_prescaler[channel_id] = prescaler;
+
+ /* Reset Byte Pointer */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+
+ /* Set filter clock factor */
+- outb(prescaler, base_offset);
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
+- base_offset + 1);
++ iowrite8(prescaler, base_offset);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
++ base_offset + 1);
+
+ spin_unlock_irqrestore(&priv->lock, irqflags);
+
+@@ -1084,12 +1085,12 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
+ {
+ struct counter_device *counter = private;
+ struct quad8 *const priv = counter_priv(counter);
+- const unsigned long base = priv->base;
++ void __iomem *const base = priv->base;
+ unsigned long irq_status;
+ unsigned long channel;
+ u8 event;
+
+- irq_status = inb(base + QUAD8_REG_INTERRUPT_STATUS);
++ irq_status = ioread8(base + QUAD8_REG_INTERRUPT_STATUS);
+ if (!irq_status)
+ return IRQ_NONE;
+
+@@ -1118,17 +1119,43 @@ static irqreturn_t quad8_irq_handler(int irq, void *private)
+ }
+
+ /* Clear pending interrupts on device */
+- outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP);
++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base + QUAD8_REG_CHAN_OP);
+
+ return IRQ_HANDLED;
+ }
+
++static void quad8_init_counter(void __iomem *const base_offset)
++{
++ unsigned long i;
++
++ /* Reset Byte Pointer */
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ /* Reset filter clock factor */
++ iowrite8(0, base_offset);
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
++ base_offset + 1);
++ /* Reset Byte Pointer */
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
++ /* Reset Preset Register */
++ for (i = 0; i < 3; i++)
++ iowrite8(0x00, base_offset);
++ /* Reset Borrow, Carry, Compare, and Sign flags */
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
++ /* Reset Error flag */
++ iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
++ /* Binary encoding; Normal count; non-quadrature mode */
++ iowrite8(QUAD8_CTR_CMR, base_offset + 1);
++ /* Disable A and B inputs; preset on index; FLG1 as Carry */
++ iowrite8(QUAD8_CTR_IOR, base_offset + 1);
++ /* Disable index function; negative index polarity */
++ iowrite8(QUAD8_CTR_IDR, base_offset + 1);
++}
++
+ static int quad8_probe(struct device *dev, unsigned int id)
+ {
+ struct counter_device *counter;
+ struct quad8 *priv;
+- int i, j;
+- unsigned int base_offset;
++ unsigned long i;
+ int err;
+
+ if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) {
+@@ -1142,6 +1169,10 @@ static int quad8_probe(struct device *dev, unsigned int id)
+ return -ENOMEM;
+ priv = counter_priv(counter);
+
++ priv->base = devm_ioport_map(dev, base[id], QUAD8_EXTENT);
++ if (!priv->base)
++ return -ENOMEM;
++
+ /* Initialize Counter device and driver data */
+ counter->name = dev_name(dev);
+ counter->parent = dev;
+@@ -1150,43 +1181,21 @@ static int quad8_probe(struct device *dev, unsigned int id)
+ counter->num_counts = ARRAY_SIZE(quad8_counts);
+ counter->signals = quad8_signals;
+ counter->num_signals = ARRAY_SIZE(quad8_signals);
+- priv->base = base[id];
+
+ spin_lock_init(&priv->lock);
+
+ /* Reset Index/Interrupt Register */
+- outb(0x00, base[id] + QUAD8_REG_INDEX_INTERRUPT);
++ iowrite8(0x00, priv->base + QUAD8_REG_INDEX_INTERRUPT);
+ /* Reset all counters and disable interrupt function */
+- outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
++ iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, priv->base + QUAD8_REG_CHAN_OP);
+ /* Set initial configuration for all counters */
+- for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
+- base_offset = base[id] + 2 * i;
+- /* Reset Byte Pointer */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+- /* Reset filter clock factor */
+- outb(0, base_offset);
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC,
+- base_offset + 1);
+- /* Reset Byte Pointer */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+- /* Reset Preset Register */
+- for (j = 0; j < 3; j++)
+- outb(0x00, base_offset);
+- /* Reset Borrow, Carry, Compare, and Sign flags */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, base_offset + 1);
+- /* Reset Error flag */
+- outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
+- /* Binary encoding; Normal count; non-quadrature mode */
+- outb(QUAD8_CTR_CMR, base_offset + 1);
+- /* Disable A and B inputs; preset on index; FLG1 as Carry */
+- outb(QUAD8_CTR_IOR, base_offset + 1);
+- /* Disable index function; negative index polarity */
+- outb(QUAD8_CTR_IDR, base_offset + 1);
+- }
++ for (i = 0; i < QUAD8_NUM_COUNTERS; i++)
++ quad8_init_counter(priv->base + 2 * i);
+ /* Disable Differential Encoder Cable Status for all channels */
+- outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS);
++ iowrite8(0xFF, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
+ /* Enable all counters and enable interrupt function */
+- outb(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, base[id] + QUAD8_REG_CHAN_OP);
++ iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC,
++ priv->base + QUAD8_REG_CHAN_OP);
+
+ err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler,
+ IRQF_SHARED, counter->name, counter);
+--
+2.35.1
+
--- /dev/null
+From 57224444030ba3d24e26a125231d5b7c56fb0bd8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Sep 2022 15:26:11 +0300
+Subject: perf record: Fix cpu mask bit setting for mixed mmaps
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit ca76d7d2812b46124291f99c9b50aaf63a936f23 ]
+
+With mixed per-thread and (system-wide) per-cpu maps, the "any cpu" value
+ -1 must be skipped when setting CPU mask bits.
+
+Prior to commit cbd7bfc7fd99acdd ("tools/perf: Fix out of bound access
+to cpu mask array") the invalid setting went unnoticed, but since then
+it causes perf record to fail with an error.
+
+Example:
+
+ Before:
+
+ $ perf record -e intel_pt// --per-thread uname
+ Failed to initialize parallel data streaming masks
+
+ After:
+
+ $ perf record -e intel_pt// --per-thread uname
+ Linux
+ [ perf record: Woken up 1 times to write data ]
+ [ perf record: Captured and wrote 0.068 MB perf.data ]
+
+Fixes: ae4f8ae16a078964 ("libperf evlist: Allow mixing per-thread and per-cpu mmaps")
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Acked-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20220915122612.81738-2-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-record.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index 708880a1c83c..7fbc85c1da81 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -3344,6 +3344,8 @@ static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cp
+ return 0;
+
+ perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
++ if (cpu.cpu == -1)
++ continue;
+ /* Return ENODEV is input cpu is greater than max cpu */
+ if ((unsigned long)cpu.cpu > mask->nbits)
+ return -ENODEV;
+--
+2.35.1
+
--- /dev/null
+From c516c7a2f5d290f4c3e3b9a527a25309a5cbe793 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Sep 2022 17:49:32 +0200
+Subject: riscv: make t-head erratas depend on MMU
+
+From: Heiko Stuebner <heiko@sntech.de>
+
+[ Upstream commit 2a2018c3ac84c2dc7cfbad117ce9339ea0914622 ]
+
+Both basic extensions of SVPBMT and ZICBOM depend on CONFIG_MMU.
+Make the T-Head errata implementations of the similar functionality
+also depend on it to prevent build errors.
+
+Fixes: a35707c3d850 ("riscv: add memory-type errata for T-Head")
+Fixes: d20ec7529236 ("riscv: implement cache-management errata for T-Head SoCs")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Reviewed-by: Guo Ren <guoren@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20220907154932.2858518-1-heiko@sntech.de
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/Kconfig.erratas | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
+index 457ac72c9b36..e59a770b4432 100644
+--- a/arch/riscv/Kconfig.erratas
++++ b/arch/riscv/Kconfig.erratas
+@@ -46,7 +46,7 @@ config ERRATA_THEAD
+
+ config ERRATA_THEAD_PBMT
+ bool "Apply T-Head memory type errata"
+- depends on ERRATA_THEAD && 64BIT
++ depends on ERRATA_THEAD && 64BIT && MMU
+ select RISCV_ALTERNATIVE_EARLY
+ default y
+ help
+--
+2.35.1
+
--- /dev/null
+riscv-make-t-head-erratas-depend-on-mmu.patch
+tools-perf-fix-out-of-bound-access-to-cpu-mask-array.patch
+perf-record-fix-cpu-mask-bit-setting-for-mixed-mmaps.patch
+counter-104-quad-8-utilize-iomap-interface.patch
+counter-104-quad-8-implement-and-utilize-register-st.patch
+counter-104-quad-8-fix-skipped-irq-lines-during-even.patch
--- /dev/null
+From 02f569478c767d5365ece100794c29dca8e76eb5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Sep 2022 19:49:29 +0530
+Subject: tools/perf: Fix out of bound access to cpu mask array
+
+From: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+
+[ Upstream commit cbd7bfc7fd99acdde58ec2b0bce990158fba1654 ]
+
+The cpu mask init code in "record__mmap_cpu_mask_init" function access
+"bits" array part of "struct mmap_cpu_mask". The size of this array is
+the value from cpu__max_cpu().cpu. This array is used to contain the
+cpumask value for each cpu. While setting bit for each cpu, it calls
+"set_bit" function which access index in "bits" array.
+
+If we provide a command line option to -C which is greater than the
+number of CPU's present in the system, the set_bit could access an array
+member which is out-of the array size. This is because currently, there
+is no boundary check for the CPU. This will result in seg fault:
+
+<<>>
+ ./perf record -C 12341234 ls
+ Perf can support 2048 CPUs. Consider raising MAX_NR_CPUS
+ Segmentation fault (core dumped)
+<<>>
+
+Debugging with gdb, points to function flow as below:
+
+<<>>
+ set_bit
+ record__mmap_cpu_mask_init
+ record__init_thread_default_masks
+ record__init_thread_masks
+ cmd_record
+<<>>
+
+Fix this by adding boundary check for the array.
+
+After the patch:
+
+<<>>
+./perf record -C 12341234 ls
+ Perf can support 2048 CPUs. Consider raising MAX_NR_CPUS
+ Failed to initialize parallel data streaming masks
+<<>>
+
+With this fix, if -C is given a non-exsiting CPU, perf
+record will fail with:
+
+<<>>
+ ./perf record -C 50 ls
+ Failed to initialize parallel data streaming masks
+<<>>
+
+Reported-by: Nageswara R Sastry <rnsastry@linux.ibm.com>
+Signed-off-by: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
+Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Tested-by: Nageswara R Sastry <rnsastry@linux.ibm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: linuxppc-dev@lists.ozlabs.org
+Link: https://lore.kernel.org/r/20220905141929.7171-2-atrajeev@linux.vnet.ibm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: ca76d7d2812b ("perf record: Fix cpu mask bit setting for mixed mmaps")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-record.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index 68c878b4e5e4..708880a1c83c 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -3335,16 +3335,22 @@ static struct option __record_options[] = {
+
+ struct option *record_options = __record_options;
+
+-static void record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus)
++static int record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus)
+ {
+ struct perf_cpu cpu;
+ int idx;
+
+ if (cpu_map__is_dummy(cpus))
+- return;
++ return 0;
+
+- perf_cpu_map__for_each_cpu(cpu, idx, cpus)
++ perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
++ /* Return ENODEV is input cpu is greater than max cpu */
++ if ((unsigned long)cpu.cpu > mask->nbits)
++ return -ENODEV;
+ set_bit(cpu.cpu, mask->bits);
++ }
++
++ return 0;
+ }
+
+ static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const char *mask_spec)
+@@ -3356,7 +3362,9 @@ static int record__mmap_cpu_mask_init_spec(struct mmap_cpu_mask *mask, const cha
+ return -ENOMEM;
+
+ bitmap_zero(mask->bits, mask->nbits);
+- record__mmap_cpu_mask_init(mask, cpus);
++ if (record__mmap_cpu_mask_init(mask, cpus))
++ return -ENODEV;
++
+ perf_cpu_map__put(cpus);
+
+ return 0;
+@@ -3438,7 +3446,12 @@ static int record__init_thread_masks_spec(struct record *rec, struct perf_cpu_ma
+ pr_err("Failed to allocate CPUs mask\n");
+ return ret;
+ }
+- record__mmap_cpu_mask_init(&cpus_mask, cpus);
++
++ ret = record__mmap_cpu_mask_init(&cpus_mask, cpus);
++ if (ret) {
++ pr_err("Failed to init cpu mask\n");
++ goto out_free_cpu_mask;
++ }
+
+ ret = record__thread_mask_alloc(&full_mask, cpu__max_cpu().cpu);
+ if (ret) {
+@@ -3679,7 +3692,8 @@ static int record__init_thread_default_masks(struct record *rec, struct perf_cpu
+ if (ret)
+ return ret;
+
+- record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus);
++ if (record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus))
++ return -ENODEV;
+
+ rec->nr_threads = 1;
+
+--
+2.35.1
+