Skip to content

Commit 7ba6352

Browse files
Tharun Kumar Pbroonie
authored andcommitted
spi: microchip: pci1xxxx: Add suspend and resume support for PCI1XXXX SPI driver
Implement suspend, resume callbacks, store config at suspend and restore config at time of resume Signed-off-by: Tharun Kumar P <tharunkumar.pasumarthi@microchip.com> Link: https://lore.kernel.org/r/20221006050514.115564-3-tharunkumar.pasumarthi@microchip.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent c771b4e commit 7ba6352

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

drivers/spi/spi-pci1xxxx.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@
5757
#define SPI_CHIP_SEL_COUNT 7
5858
#define VENDOR_ID_MCHP 0x1055
5959

60+
#define SPI_SUSPEND_CONFIG 0x101
61+
#define SPI_RESUME_CONFIG 0x303
62+
6063
struct pci1xxxx_spi_internal {
6164
u8 hw_inst;
6265
bool spi_xfer_in_progress;
@@ -383,10 +386,85 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id *
383386
return ret;
384387
}
385388

389+
static void store_restore_config(struct pci1xxxx_spi *spi_ptr,
390+
struct pci1xxxx_spi_internal *spi_sub_ptr,
391+
u8 inst, bool store)
392+
{
393+
u32 regval;
394+
395+
if (store) {
396+
regval = readl(spi_ptr->reg_base +
397+
SPI_MST_CTL_REG_OFFSET(spi_sub_ptr->hw_inst));
398+
regval &= SPI_MST_CTL_DEVSEL_MASK;
399+
spi_sub_ptr->prev_val.dev_sel = (regval >> 25) & 7;
400+
regval = readl(spi_ptr->reg_base +
401+
SPI_PCI_CTRL_REG_OFFSET(spi_sub_ptr->hw_inst));
402+
regval &= SPI_MSI_VECTOR_SEL_MASK;
403+
spi_sub_ptr->prev_val.msi_vector_sel = (regval >> 4) & 1;
404+
} else {
405+
regval = readl(spi_ptr->reg_base + SPI_MST_CTL_REG_OFFSET(inst));
406+
regval &= ~SPI_MST_CTL_DEVSEL_MASK;
407+
regval |= (spi_sub_ptr->prev_val.dev_sel << 25);
408+
writel(regval,
409+
spi_ptr->reg_base + SPI_MST_CTL_REG_OFFSET(inst));
410+
writel((spi_sub_ptr->prev_val.msi_vector_sel << 4),
411+
spi_ptr->reg_base + SPI_PCI_CTRL_REG_OFFSET(inst));
412+
}
413+
}
414+
415+
static int pci1xxxx_spi_resume(struct device *dev)
416+
{
417+
struct pci1xxxx_spi *spi_ptr = dev_get_drvdata(dev);
418+
struct pci1xxxx_spi_internal *spi_sub_ptr;
419+
u32 regval = SPI_RESUME_CONFIG;
420+
u8 iter;
421+
422+
for (iter = 0; iter < spi_ptr->total_hw_instances; iter++) {
423+
spi_sub_ptr = spi_ptr->spi_int[iter];
424+
spi_master_resume(spi_sub_ptr->spi_host);
425+
writel(regval, spi_ptr->reg_base +
426+
SPI_MST_EVENT_MASK_REG_OFFSET(iter));
427+
428+
/* Restore config at resume */
429+
store_restore_config(spi_ptr, spi_sub_ptr, iter, 0);
430+
}
431+
432+
return 0;
433+
}
434+
435+
static int pci1xxxx_spi_suspend(struct device *dev)
436+
{
437+
struct pci1xxxx_spi *spi_ptr = dev_get_drvdata(dev);
438+
struct pci1xxxx_spi_internal *spi_sub_ptr;
439+
u32 reg1 = SPI_SUSPEND_CONFIG;
440+
u8 iter;
441+
442+
for (iter = 0; iter < spi_ptr->total_hw_instances; iter++) {
443+
spi_sub_ptr = spi_ptr->spi_int[iter];
444+
445+
while (spi_sub_ptr->spi_xfer_in_progress)
446+
msleep(20);
447+
448+
/* Store existing config before suspend */
449+
store_restore_config(spi_ptr, spi_sub_ptr, iter, 1);
450+
spi_master_suspend(spi_sub_ptr->spi_host);
451+
writel(reg1, spi_ptr->reg_base +
452+
SPI_MST_EVENT_MASK_REG_OFFSET(iter));
453+
}
454+
455+
return 0;
456+
}
457+
458+
static DEFINE_SIMPLE_DEV_PM_OPS(spi_pm_ops, pci1xxxx_spi_suspend,
459+
pci1xxxx_spi_resume);
460+
386461
static struct pci_driver pci1xxxx_spi_driver = {
387462
.name = DRV_NAME,
388463
.id_table = pci1xxxx_spi_pci_id_table,
389464
.probe = pci1xxxx_spi_probe,
465+
.driver = {
466+
.pm = pm_sleep_ptr(&spi_pm_ops),
467+
},
390468
};
391469

392470
module_pci_driver(pci1xxxx_spi_driver);

0 commit comments

Comments
 (0)