cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sc27xx-poweroff.c (1974B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2018 Spreadtrum Communications Inc.
      4 * Copyright (C) 2018 Linaro Ltd.
      5 */
      6
      7#include <linux/cpu.h>
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/platform_device.h>
     11#include <linux/pm.h>
     12#include <linux/regmap.h>
     13#include <linux/syscore_ops.h>
     14
     15#define SC27XX_PWR_PD_HW	0xc2c
     16#define SC27XX_PWR_OFF_EN	BIT(0)
     17#define SC27XX_SLP_CTRL		0xdf0
     18#define SC27XX_LDO_XTL_EN	BIT(3)
     19
     20static struct regmap *regmap;
     21
     22/*
     23 * On Spreadtrum platform, we need power off system through external SC27xx
     24 * series PMICs, and it is one similar SPI bus mapped by regmap to access PMIC,
     25 * which is not fast io access.
     26 *
     27 * So before stopping other cores, we need release other cores' resource by
     28 * taking cpus down to avoid racing regmap or spi mutex lock when poweroff
     29 * system through PMIC.
     30 */
     31static void sc27xx_poweroff_shutdown(void)
     32{
     33#ifdef CONFIG_HOTPLUG_CPU
     34	int cpu;
     35
     36	for_each_online_cpu(cpu) {
     37		if (cpu != smp_processor_id())
     38			remove_cpu(cpu);
     39	}
     40#endif
     41}
     42
     43static struct syscore_ops poweroff_syscore_ops = {
     44	.shutdown = sc27xx_poweroff_shutdown,
     45};
     46
     47static void sc27xx_poweroff_do_poweroff(void)
     48{
     49	/* Disable the external subsys connection's power firstly */
     50	regmap_write(regmap, SC27XX_SLP_CTRL, SC27XX_LDO_XTL_EN);
     51
     52	regmap_write(regmap, SC27XX_PWR_PD_HW, SC27XX_PWR_OFF_EN);
     53}
     54
     55static int sc27xx_poweroff_probe(struct platform_device *pdev)
     56{
     57	if (regmap)
     58		return -EINVAL;
     59
     60	regmap = dev_get_regmap(pdev->dev.parent, NULL);
     61	if (!regmap)
     62		return -ENODEV;
     63
     64	pm_power_off = sc27xx_poweroff_do_poweroff;
     65	register_syscore_ops(&poweroff_syscore_ops);
     66	return 0;
     67}
     68
     69static struct platform_driver sc27xx_poweroff_driver = {
     70	.probe = sc27xx_poweroff_probe,
     71	.driver = {
     72		.name = "sc27xx-poweroff",
     73	},
     74};
     75module_platform_driver(sc27xx_poweroff_driver);
     76
     77MODULE_DESCRIPTION("Power off driver for SC27XX PMIC Device");
     78MODULE_AUTHOR("Baolin Wang <baolin.wang@unisoc.com>");
     79MODULE_LICENSE("GPL v2");