Skip to content

Commit 800cda7

Browse files
sudeep-hollaJassiBrar
authored andcommitted
mailbox: pcc: Add PCC register bundle and associated accessor functions
Extended PCC subspaces introduces more registers into the PCCT. In order to consolidate access to these registers and to keep all the details contained in one place, let us introduce PCC register bundle that holds the ACPI Generic Address Structure as well as the virtual address for the same if it is mapped in the OS. It also contains the various masks used to access the register and the associated read, write and read-modify-write accessors. We can also clean up the initialisations by having a helper function for the same. Signed-off-by: Sudeep Holla <[email protected]> Signed-off-by: Jassi Brar <[email protected]>
1 parent f92ae90 commit 800cda7

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

drivers/mailbox/pcc.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include <linux/init.h>
5353
#include <linux/interrupt.h>
5454
#include <linux/list.h>
55+
#include <linux/log2.h>
5556
#include <linux/platform_device.h>
5657
#include <linux/mailbox_controller.h>
5758
#include <linux/mailbox_client.h>
@@ -64,6 +65,23 @@
6465

6566
static struct mbox_chan *pcc_mbox_channels;
6667

68+
/**
69+
* struct pcc_chan_reg - PCC register bundle
70+
*
71+
* @vaddr: cached virtual address for this register
72+
* @gas: pointer to the generic address structure for this register
73+
* @preserve_mask: bitmask to preserve when writing to this register
74+
* @set_mask: bitmask to set when writing to this register
75+
* @status_mask: bitmask to determine and/or update the status for this register
76+
*/
77+
struct pcc_chan_reg {
78+
void __iomem *vaddr;
79+
struct acpi_generic_address *gas;
80+
u64 preserve_mask;
81+
u64 set_mask;
82+
u64 status_mask;
83+
};
84+
6785
/**
6886
* struct pcc_chan_info - PCC channel specific information
6987
*
@@ -144,6 +162,53 @@ static int write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
144162
return ret_val;
145163
}
146164

165+
static int pcc_chan_reg_read(struct pcc_chan_reg *reg, u64 *val)
166+
{
167+
int ret = 0;
168+
169+
if (!reg->gas) {
170+
*val = 0;
171+
return 0;
172+
}
173+
174+
if (reg->vaddr)
175+
ret = read_register(reg->vaddr, val, reg->gas->bit_width);
176+
else
177+
ret = acpi_read(val, reg->gas);
178+
179+
return ret;
180+
}
181+
182+
static int pcc_chan_reg_write(struct pcc_chan_reg *reg, u64 val)
183+
{
184+
int ret = 0;
185+
186+
if (!reg->gas)
187+
return 0;
188+
189+
if (reg->vaddr)
190+
ret = write_register(reg->vaddr, val, reg->gas->bit_width);
191+
else
192+
ret = acpi_write(val, reg->gas);
193+
194+
return ret;
195+
}
196+
197+
static int pcc_chan_reg_read_modify_write(struct pcc_chan_reg *reg)
198+
{
199+
int ret = 0;
200+
u64 val;
201+
202+
ret = pcc_chan_reg_read(reg, &val);
203+
if (ret)
204+
return ret;
205+
206+
val &= reg->preserve_mask;
207+
val |= reg->set_mask;
208+
209+
return pcc_chan_reg_write(reg, val);
210+
}
211+
147212
/**
148213
* pcc_map_interrupt - Map a PCC subspace GSI to a linux IRQ number
149214
* @interrupt: GSI number.
@@ -379,6 +444,31 @@ static int parse_pcc_subspace(union acpi_subtable_headers *header,
379444
return -EINVAL;
380445
}
381446

447+
static int
448+
pcc_chan_reg_init(struct pcc_chan_reg *reg, struct acpi_generic_address *gas,
449+
u64 preserve_mask, u64 set_mask, u64 status_mask, char *name)
450+
{
451+
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
452+
if (!(gas->bit_width >= 8 && gas->bit_width <= 64 &&
453+
is_power_of_2(gas->bit_width))) {
454+
pr_err("Error: Cannot access register of %u bit width",
455+
gas->bit_width);
456+
return -EFAULT;
457+
}
458+
459+
reg->vaddr = acpi_os_ioremap(gas->address, gas->bit_width / 8);
460+
if (!reg->vaddr) {
461+
pr_err("Failed to ioremap PCC %s register\n", name);
462+
return -ENOMEM;
463+
}
464+
}
465+
reg->gas = gas;
466+
reg->preserve_mask = preserve_mask;
467+
reg->set_mask = set_mask;
468+
reg->status_mask = status_mask;
469+
return 0;
470+
}
471+
382472
/**
383473
* pcc_parse_subspace_irq - Parse the PCC IRQ and PCC ACK register
384474
*

0 commit comments

Comments
 (0)