Message ID | 1447840582-19850-1-git-send-email-andy.yan@rock-chips.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi Andy,
[auto build test WARNING on rockchip/for-next]
[also build test WARNING on v4.4-rc1 next-20151118]
url: https://github.com/0day-ci/linux/commits/Andy-Yan/Add-reboot-notifier-driver-for-rockchip-platform/20151118-181000
base: https://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip.git for-next
config: arm64-allmodconfig (attached as .config)
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64
All warnings (new ones prefixed by >>):
>> WARNING: drivers/soc/built-in.o(.data+0x718): Section mismatch in reference from the variable rockchip_reboot_driver to the function .init.text:rockchip_reboot_probe()
The variable rockchip_reboot_driver references
the function __init rockchip_reboot_probe()
If the reference is valid then annotate the
variable with or __refdata (see linux/init.h) or name the variable:
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > rockchip platform have a protocol to pass the kernel reboot > mode to bootloader by some special registers when system reboot. > By this way the bootloader can take different action according > to the different kernel reboot mode, for example, command > "reboot loader" will reboot the board to rockusb mode, this is > a very convenient way to get the board enter download mode. > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> Adding John Stultz to Cc I just saw this thread pop up again, and had to think of John's recent patch to unify this across platforms. John, can you have a look at this driver too, and see how it fits in? I think this is yet another variant, using an MMIO register rather than RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise it conceptually fits in with what you had. The driver goes through an existing syscon regmap as far as I can tell, rather than a memory area or its own device. Arnd > --- > > Changes in v3: > - move from mach-rockchip to drivers/soc/rockchip, as the tegra does > - use dts pass the related register > > Changes in v2: > - check cpu dt node > - remove a unnecessary of_put_node in function rockchip_get_pmu_regmap > - fix a align issue > - use reboot_notifier instead of restart_handler > > drivers/soc/rockchip/Kconfig | 7 ++++ > drivers/soc/rockchip/Makefile | 1 + > drivers/soc/rockchip/loader.h | 22 ++++++++++ > drivers/soc/rockchip/reboot.c | 98 +++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 128 insertions(+) > create mode 100644 drivers/soc/rockchip/loader.h > create mode 100644 drivers/soc/rockchip/reboot.c > > diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig > index 7140ff8..4edbc44 100644 > --- a/drivers/soc/rockchip/Kconfig > +++ b/drivers/soc/rockchip/Kconfig > @@ -15,4 +15,11 @@ config ROCKCHIP_PM_DOMAINS > > If unsure, say N. > > +config ROCKCHIP_REBOOT > + bool "Rockchip reboot notifier driver" > + help > + Say y here will enable reboot notifier support. > + This will get reboot mode arguments from userspace and > + store it in special register. > + > endif > diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile > index 3d73d06..9817496 100644 > --- a/drivers/soc/rockchip/Makefile > +++ b/drivers/soc/rockchip/Makefile > @@ -2,3 +2,4 @@ > # Rockchip Soc drivers > # > obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o > +obj-$(CONFIG_ROCKCHIP_REBOOT) += reboot.o > diff --git a/drivers/soc/rockchip/loader.h b/drivers/soc/rockchip/loader.h > new file mode 100644 > index 0000000..bf51baa > --- /dev/null > +++ b/drivers/soc/rockchip/loader.h > @@ -0,0 +1,22 @@ > +#ifndef __MACH_ROCKCHIP_LOADER_H > +#define __MACH_ROCKCHIP_LOADER_H > + > +/*high 24 bits is tag, low 8 bits is type*/ > +#define SYS_LOADER_REBOOT_FLAG 0x5242C300 > + > +enum { > + BOOT_NORMAL = 0, /* normal boot */ > + BOOT_LOADER, /* enter loader rockusb mode */ > + BOOT_MASKROM, /* enter maskrom rockusb mode (not support now) */ > + BOOT_RECOVER, /* enter recover */ > + BOOT_NORECOVER, /* do not enter recover */ > + BOOT_SECONDOS, /* boot second OS (not support now)*/ > + BOOT_WIPEDATA, /* enter recover and wipe data. */ > + BOOT_WIPEALL, /* enter recover and wipe all data. */ > + BOOT_CHECKIMG, /* check firmware img with backup part*/ > + BOOT_FASTBOOT, /* enter fast boot mode */ > + BOOT_SECUREBOOT_DISABLE, > + BOOT_CHARGING, /* enter charge mode */ > + BOOT_MAX /* MAX VALID BOOT TYPE.*/ > +}; > +#endif > diff --git a/drivers/soc/rockchip/reboot.c b/drivers/soc/rockchip/reboot.c > new file mode 100644 > index 0000000..048aeb0b > --- /dev/null > +++ b/drivers/soc/rockchip/reboot.c > @@ -0,0 +1,98 @@ > +/* > + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + */ > +#include <linux/init.h> > +#include <linux/module.h> > +#include <linux/kernel.h> > +#include <linux/of.h> > +#include <linux/of_address.h> > +#include <linux/platform_device.h> > +#include <linux/reboot.h> > +#include <linux/regmap.h> > +#include <linux/mfd/syscon.h> > +#include "loader.h" > + > +struct rockchip_reboot { > + struct device *dev; > + struct regmap *map; > + u32 offset; > + struct notifier_block reboot_notifier; > +}; > + > +static void rockchip_get_reboot_flag(const char *cmd, u32 *flag) > +{ > + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_NORMAL; > + > + if (cmd) { > + if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader")) > + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER; > + else if (!strcmp(cmd, "recovery")) > + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER; > + else if (!strcmp(cmd, "charge")) > + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_CHARGING; > + else if (!strcmp(cmd, "fastboot")) > + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_FASTBOOT; > + } > +} > + > +static int rockchip_reboot_notify(struct notifier_block *this, > + unsigned long mode, void *cmd) > +{ > + struct rockchip_reboot *reboot; > + u32 flag; > + > + reboot = container_of(this, struct rockchip_reboot, reboot_notifier); > + rockchip_get_reboot_flag(cmd, &flag); > + regmap_write(reboot->map, reboot->offset, flag); > + > + return NOTIFY_DONE; > +} > + > +static int __init rockchip_reboot_probe(struct platform_device *pdev) > +{ > + struct rockchip_reboot *reboot; > + int ret; > + > + reboot = devm_kzalloc(&pdev->dev, sizeof(*reboot), GFP_KERNEL); > + if (!reboot) > + return -ENOMEM; > + > + reboot->dev = &pdev->dev; > + reboot->map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, > + "rockchip,regmap"); > + if (IS_ERR(reboot->map)) > + return PTR_ERR(reboot->map); > + > + if (of_property_read_u32(pdev->dev.of_node, "offset", &reboot->offset)) > + return -EINVAL; > + > + reboot->reboot_notifier.notifier_call = rockchip_reboot_notify; > + ret = register_reboot_notifier(&reboot->reboot_notifier); > + if (ret) > + dev_err(reboot->dev, "can't register reboot notifier\n"); > + > + return ret; > +} > + > +static const struct of_device_id rockchip_reboot_of_match[] = { > + { .compatible = "rockchip,reboot" }, > + {} > +}; > + > +static struct platform_driver rockchip_reboot_driver = { > + .probe = rockchip_reboot_probe, > + .driver = { > + .name = "rockchip-reboot", > + .of_match_table = rockchip_reboot_of_match, > + }, > +}; > +module_platform_driver(rockchip_reboot_driver); > + > +MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com"); > +MODULE_DESCRIPTION("Rockchip platform reboot notifier driver"); > +MODULE_LICENSE("GPL"); >
On Mon, Dec 14, 2015 at 12:39:44PM +0100, Arnd Bergmann wrote: > On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > > rockchip platform have a protocol to pass the kernel reboot > > mode to bootloader by some special registers when system reboot. > > By this way the bootloader can take different action according > > to the different kernel reboot mode, for example, command > > "reboot loader" will reboot the board to rockusb mode, this is > > a very convenient way to get the board enter download mode. > > > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > > Adding John Stultz to Cc > > I just saw this thread pop up again, and had to think of John's recent > patch to unify this across platforms. > > John, can you have a look at this driver too, and see how it fits in? > I think this is yet another variant, using an MMIO register rather than > RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise > it conceptually fits in with what you had. FWIW, Tegra typically does use an MMIO register as well. See drivers/soc/tegra/pmc.c:tegra_pmc_restart_notify(). I don't know what HTC does, but if it's writing somewhere in RAM it isn't using the standard way of resetting the SoC. There's early boot ROM code which I think evaluates the PMC_SCRATCH0 register on Tegra to determine which mode to boot into. That's before even any firmware gets the chance of doing anything. Thierry
On Tuesday 15 December 2015 17:31:22 Thierry Reding wrote: > On Mon, Dec 14, 2015 at 12:39:44PM +0100, Arnd Bergmann wrote: > > On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > > > rockchip platform have a protocol to pass the kernel reboot > > > mode to bootloader by some special registers when system reboot. > > > By this way the bootloader can take different action according > > > to the different kernel reboot mode, for example, command > > > "reboot loader" will reboot the board to rockusb mode, this is > > > a very convenient way to get the board enter download mode. > > > > > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > > > > Adding John Stultz to Cc > > > > I just saw this thread pop up again, and had to think of John's recent > > patch to unify this across platforms. > > > > John, can you have a look at this driver too, and see how it fits in? > > I think this is yet another variant, using an MMIO register rather than > > RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise > > it conceptually fits in with what you had. > > FWIW, Tegra typically does use an MMIO register as well. See > drivers/soc/tegra/pmc.c:tegra_pmc_restart_notify(). I don't know what > HTC does, but if it's writing somewhere in RAM it isn't using the > standard way of resetting the SoC. There's early boot ROM code which I > think evaluates the PMC_SCRATCH0 register on Tegra to determine which > mode to boot into. That's before even any firmware gets the chance of > doing anything. HTC apparently uses a separate RAM area to pass the reboot reason, and they have a driver to store that, which is separate from the driver that they use for actually rebooting the machine. Arnd
Am Dienstag, 15. Dezember 2015, 17:34:00 schrieb Arnd Bergmann: > On Tuesday 15 December 2015 17:31:22 Thierry Reding wrote: > > On Mon, Dec 14, 2015 at 12:39:44PM +0100, Arnd Bergmann wrote: > > > On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > > > > rockchip platform have a protocol to pass the kernel reboot > > > > mode to bootloader by some special registers when system reboot. > > > > By this way the bootloader can take different action according > > > > to the different kernel reboot mode, for example, command > > > > "reboot loader" will reboot the board to rockusb mode, this is > > > > a very convenient way to get the board enter download mode. > > > > > > > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > > > > > > Adding John Stultz to Cc > > > > > > I just saw this thread pop up again, and had to think of John's recent > > > patch to unify this across platforms. > > > > > > John, can you have a look at this driver too, and see how it fits in? > > > I think this is yet another variant, using an MMIO register rather than > > > RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise > > > it conceptually fits in with what you had. > > > > FWIW, Tegra typically does use an MMIO register as well. See > > drivers/soc/tegra/pmc.c:tegra_pmc_restart_notify(). I don't know what > > HTC does, but if it's writing somewhere in RAM it isn't using the > > standard way of resetting the SoC. There's early boot ROM code which I > > think evaluates the PMC_SCRATCH0 register on Tegra to determine which > > mode to boot into. That's before even any firmware gets the chance of > > doing anything. > > HTC apparently uses a separate RAM area to pass the reboot reason, > and they have a driver to store that, which is separate from the > driver that they use for actually rebooting the machine. same on Rockchip. The general restart handling doesn't care about any reason, it is merely an agreement between kernel and bootloader to store a reason value in some reboot-safe register of the soc. Heiko
On Tue, Dec 15, 2015 at 05:34:00PM +0100, Arnd Bergmann wrote: > On Tuesday 15 December 2015 17:31:22 Thierry Reding wrote: > > On Mon, Dec 14, 2015 at 12:39:44PM +0100, Arnd Bergmann wrote: > > > On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > > > > rockchip platform have a protocol to pass the kernel reboot > > > > mode to bootloader by some special registers when system reboot. > > > > By this way the bootloader can take different action according > > > > to the different kernel reboot mode, for example, command > > > > "reboot loader" will reboot the board to rockusb mode, this is > > > > a very convenient way to get the board enter download mode. > > > > > > > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > > > > > > Adding John Stultz to Cc > > > > > > I just saw this thread pop up again, and had to think of John's recent > > > patch to unify this across platforms. > > > > > > John, can you have a look at this driver too, and see how it fits in? > > > I think this is yet another variant, using an MMIO register rather than > > > RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise > > > it conceptually fits in with what you had. > > > > FWIW, Tegra typically does use an MMIO register as well. See > > drivers/soc/tegra/pmc.c:tegra_pmc_restart_notify(). I don't know what > > HTC does, but if it's writing somewhere in RAM it isn't using the > > standard way of resetting the SoC. There's early boot ROM code which I > > think evaluates the PMC_SCRATCH0 register on Tegra to determine which > > mode to boot into. That's before even any firmware gets the chance of > > doing anything. > > HTC apparently uses a separate RAM area to pass the reboot reason, > and they have a driver to store that, which is separate from the > driver that they use for actually rebooting the machine. I wasn't very clear, but the PMC_SCRATCH0 register is used to store the reset reason. It supports the recovery mode, which I think is really an Android thing, "bootloader" will typically cause the bootloader not to boot anything, and "forced-recovery" will go into a recovery mode that is used to bootstrap the device (usually by uploading a "miniloader" that initializes RAM, downloads a bootloader for booting or flashing an operating system, ...). The write that resets the SoC is to a different register. Thierry
On Tuesday 15 December 2015 18:42:36 Thierry Reding wrote: > On Tue, Dec 15, 2015 at 05:34:00PM +0100, Arnd Bergmann wrote: > > On Tuesday 15 December 2015 17:31:22 Thierry Reding wrote: > > > On Mon, Dec 14, 2015 at 12:39:44PM +0100, Arnd Bergmann wrote: > > > > On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > > > > > rockchip platform have a protocol to pass the kernel reboot > > > > > mode to bootloader by some special registers when system reboot. > > > > > By this way the bootloader can take different action according > > > > > to the different kernel reboot mode, for example, command > > > > > "reboot loader" will reboot the board to rockusb mode, this is > > > > > a very convenient way to get the board enter download mode. > > > > > > > > > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > > > > > > > > Adding John Stultz to Cc > > > > > > > > I just saw this thread pop up again, and had to think of John's recent > > > > patch to unify this across platforms. > > > > > > > > John, can you have a look at this driver too, and see how it fits in? > > > > I think this is yet another variant, using an MMIO register rather than > > > > RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise > > > > it conceptually fits in with what you had. > > > > > > FWIW, Tegra typically does use an MMIO register as well. See > > > drivers/soc/tegra/pmc.c:tegra_pmc_restart_notify(). I don't know what > > > HTC does, but if it's writing somewhere in RAM it isn't using the > > > standard way of resetting the SoC. There's early boot ROM code which I > > > think evaluates the PMC_SCRATCH0 register on Tegra to determine which > > > mode to boot into. That's before even any firmware gets the chance of > > > doing anything. I just checked the android lollipop tree, and I could not find a pmc_restart_notify function, only this file https://android.googlesource.com/kernel/tegra/+/android-tegra-flounder-3.10-lollipop-release/drivers/htc_debug/stability/reboot_params.c with the device that stores into RAM. It looks like HTC ported over a driver that they were already using on some Qualcomm MSM8960 device, as in https://gitlab.com/MaC/android_kernel_htc_msm8960/blob/859977fc723f59a6b707df1d70e80826ee1dccc4/arch/arm/mach-msm/htc/htc_restart_handler.c On Android marshmallow (Flounder), that file again does not exist, and I don't see how it's done. > > HTC apparently uses a separate RAM area to pass the reboot reason, > > and they have a driver to store that, which is separate from the > > driver that they use for actually rebooting the machine. > > I wasn't very clear, but the PMC_SCRATCH0 register is used to store the > reset reason. It supports the recovery mode, which I think is really an > Android thing, "bootloader" will typically cause the bootloader not to > boot anything, and "forced-recovery" will go into a recovery mode that > is used to bootstrap the device (usually by uploading a "miniloader" > that initializes RAM, downloads a bootloader for booting or flashing an > operating system, ...). > > The write that resets the SoC is to a different register. So is this scratch register interpreted by some maskrom code, or by code that can be provided by the OEM? Arnd
On Tue, Dec 15, 2015 at 09:38:41PM +0100, Arnd Bergmann wrote: > On Tuesday 15 December 2015 18:42:36 Thierry Reding wrote: > > On Tue, Dec 15, 2015 at 05:34:00PM +0100, Arnd Bergmann wrote: > > > On Tuesday 15 December 2015 17:31:22 Thierry Reding wrote: > > > > On Mon, Dec 14, 2015 at 12:39:44PM +0100, Arnd Bergmann wrote: > > > > > On Wednesday 18 November 2015 17:56:22 Andy Yan wrote: > > > > > > rockchip platform have a protocol to pass the kernel reboot > > > > > > mode to bootloader by some special registers when system reboot. > > > > > > By this way the bootloader can take different action according > > > > > > to the different kernel reboot mode, for example, command > > > > > > "reboot loader" will reboot the board to rockusb mode, this is > > > > > > a very convenient way to get the board enter download mode. > > > > > > > > > > > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > > > > > > > > > > Adding John Stultz to Cc > > > > > > > > > > I just saw this thread pop up again, and had to think of John's recent > > > > > patch to unify this across platforms. > > > > > > > > > > John, can you have a look at this driver too, and see how it fits in? > > > > > I think this is yet another variant, using an MMIO register rather than > > > > > RAM (as HTC / NVIDIA does) or SRAM (as Qualcomm does), but otherwise > > > > > it conceptually fits in with what you had. > > > > > > > > FWIW, Tegra typically does use an MMIO register as well. See > > > > drivers/soc/tegra/pmc.c:tegra_pmc_restart_notify(). I don't know what > > > > HTC does, but if it's writing somewhere in RAM it isn't using the > > > > standard way of resetting the SoC. There's early boot ROM code which I > > > > think evaluates the PMC_SCRATCH0 register on Tegra to determine which > > > > mode to boot into. That's before even any firmware gets the chance of > > > > doing anything. > > > I just checked the android lollipop tree, and I could not find a pmc_restart_notify > function, only this file > > https://android.googlesource.com/kernel/tegra/+/android-tegra-flounder-3.10-lollipop-release/drivers/htc_debug/stability/reboot_params.c > > with the device that stores into RAM. It looks like HTC ported over > a driver that they were already using on some Qualcomm MSM8960 device, > as in > > https://gitlab.com/MaC/android_kernel_htc_msm8960/blob/859977fc723f59a6b707df1d70e80826ee1dccc4/arch/arm/mach-msm/htc/htc_restart_handler.c > > On Android marshmallow (Flounder), that file again does not exist, and > I don't see how it's done. > > > > HTC apparently uses a separate RAM area to pass the reboot reason, > > > and they have a driver to store that, which is separate from the > > > driver that they use for actually rebooting the machine. > > > > I wasn't very clear, but the PMC_SCRATCH0 register is used to store the > > reset reason. It supports the recovery mode, which I think is really an > > Android thing, "bootloader" will typically cause the bootloader not to > > boot anything, and "forced-recovery" will go into a recovery mode that > > is used to bootstrap the device (usually by uploading a "miniloader" > > that initializes RAM, downloads a bootloader for booting or flashing an > > operating system, ...). > > > > The write that resets the SoC is to a different register. > > So is this scratch register interpreted by some maskrom code, or by code that > can be provided by the OEM? My understanding is that its interpreted both by what's called BootROM on Tegra (I guess that's what you call "maskrom code") and the system's bootloader. The BootROM cannot typically be replaced by the OEM, but it is quite typical for the bootloader to differ between devices. The BootROM will interpret a subset of the bits in that register. Most notable the "force recovery" bit. That will cause the BootROM to go into a mode which can be used to bootstrap the device. It implements a simple protocol (RCM) which can be used to upload a loader (usually referred to as mini-loader) to the device's IRAM which in turn will initialize the memory and which can download a proper bootloader (such as U-Boot) to memory using a slightly more complex protocol (the standard protocol is called nv3p, but the particular choice of protocol no longer matters at this point). The bootloader can also access this register and will interpret the "bootloader" and "recovery" bits. On the, argueably small, sample of Android devices I've worked with, the "bootloader" bit will make the bootloader go into fastboot mode, whereas the "recovery" bit will make it initiate the RCK mode, which is used to update through OTA. There are a couple of other bits in this register, but they are badly documented and don't seem to relate to reboot. Thierry
On Monday 28 December 2015 10:20:56 Thierry Reding wrote: > > > > HTC apparently uses a separate RAM area to pass the reboot reason, > > > > and they have a driver to store that, which is separate from the > > > > driver that they use for actually rebooting the machine. > > > > > > I wasn't very clear, but the PMC_SCRATCH0 register is used to store the > > > reset reason. It supports the recovery mode, which I think is really an > > > Android thing, "bootloader" will typically cause the bootloader not to > > > boot anything, and "forced-recovery" will go into a recovery mode that > > > is used to bootstrap the device (usually by uploading a "miniloader" > > > that initializes RAM, downloads a bootloader for booting or flashing an > > > operating system, ...). > > > > > > The write that resets the SoC is to a different register. > > > > So is this scratch register interpreted by some maskrom code, or by code that > > can be provided by the OEM? > > My understanding is that its interpreted both by what's called BootROM > on Tegra (I guess that's what you call "maskrom code") and the system's > bootloader. The BootROM cannot typically be replaced by the OEM, but it > is quite typical for the bootloader to differ between devices. Ok, so not maskrom (which would not be OEM specific, but hardcoded for the chip) but rather some form of PROM. This means we can only guess that all OEMs use the same protocol but in theory someone could have implemented an incompatible BootROM, but it's also possible that HTC just ignore the register entirely and implement the same thing separately. > The BootROM will interpret a subset of the bits in that register. Most > notable the "force recovery" bit. That will cause the BootROM to go into > a mode which can be used to bootstrap the device. It implements a simple > protocol (RCM) which can be used to upload a loader (usually referred to > as mini-loader) to the device's IRAM which in turn will initialize the > memory and which can download a proper bootloader (such as U-Boot) to > memory using a slightly more complex protocol (the standard protocol is > called nv3p, but the particular choice of protocol no longer matters at > this point). > > The bootloader can also access this register and will interpret the > "bootloader" and "recovery" bits. On the, argueably small, sample of > Android devices I've worked with, the "bootloader" bit will make the > bootloader go into fastboot mode, whereas the "recovery" bit will make > it initiate the RCK mode, which is used to update through OTA. > > There are a couple of other bits in this register, but they are badly > documented and don't seem to relate to reboot. Ok. Arnd
On Mon, Dec 28, 2015 at 04:35:46PM +0100, Arnd Bergmann wrote: > On Monday 28 December 2015 10:20:56 Thierry Reding wrote: > > > > > HTC apparently uses a separate RAM area to pass the reboot reason, > > > > > and they have a driver to store that, which is separate from the > > > > > driver that they use for actually rebooting the machine. > > > > > > > > I wasn't very clear, but the PMC_SCRATCH0 register is used to store the > > > > reset reason. It supports the recovery mode, which I think is really an > > > > Android thing, "bootloader" will typically cause the bootloader not to > > > > boot anything, and "forced-recovery" will go into a recovery mode that > > > > is used to bootstrap the device (usually by uploading a "miniloader" > > > > that initializes RAM, downloads a bootloader for booting or flashing an > > > > operating system, ...). > > > > > > > > The write that resets the SoC is to a different register. > > > > > > So is this scratch register interpreted by some maskrom code, or by code that > > > can be provided by the OEM? > > > > My understanding is that its interpreted both by what's called BootROM > > on Tegra (I guess that's what you call "maskrom code") and the system's > > bootloader. The BootROM cannot typically be replaced by the OEM, but it > > is quite typical for the bootloader to differ between devices. > > Ok, so not maskrom (which would not be OEM specific, but hardcoded for > the chip) but rather some form of PROM. This means we can only guess > that all OEMs use the same protocol but in theory someone could have > implemented an incompatible BootROM, but it's also possible that HTC > just ignore the register entirely and implement the same thing separately. I wasn't being clear, the BootROM is hardcoded for the chip, I'm not aware of a way to replace it once the chip's taped out. Thierry
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index 7140ff8..4edbc44 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -15,4 +15,11 @@ config ROCKCHIP_PM_DOMAINS If unsure, say N. +config ROCKCHIP_REBOOT + bool "Rockchip reboot notifier driver" + help + Say y here will enable reboot notifier support. + This will get reboot mode arguments from userspace and + store it in special register. + endif diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 3d73d06..9817496 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -2,3 +2,4 @@ # Rockchip Soc drivers # obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o +obj-$(CONFIG_ROCKCHIP_REBOOT) += reboot.o diff --git a/drivers/soc/rockchip/loader.h b/drivers/soc/rockchip/loader.h new file mode 100644 index 0000000..bf51baa --- /dev/null +++ b/drivers/soc/rockchip/loader.h @@ -0,0 +1,22 @@ +#ifndef __MACH_ROCKCHIP_LOADER_H +#define __MACH_ROCKCHIP_LOADER_H + +/*high 24 bits is tag, low 8 bits is type*/ +#define SYS_LOADER_REBOOT_FLAG 0x5242C300 + +enum { + BOOT_NORMAL = 0, /* normal boot */ + BOOT_LOADER, /* enter loader rockusb mode */ + BOOT_MASKROM, /* enter maskrom rockusb mode (not support now) */ + BOOT_RECOVER, /* enter recover */ + BOOT_NORECOVER, /* do not enter recover */ + BOOT_SECONDOS, /* boot second OS (not support now)*/ + BOOT_WIPEDATA, /* enter recover and wipe data. */ + BOOT_WIPEALL, /* enter recover and wipe all data. */ + BOOT_CHECKIMG, /* check firmware img with backup part*/ + BOOT_FASTBOOT, /* enter fast boot mode */ + BOOT_SECUREBOOT_DISABLE, + BOOT_CHARGING, /* enter charge mode */ + BOOT_MAX /* MAX VALID BOOT TYPE.*/ +}; +#endif diff --git a/drivers/soc/rockchip/reboot.c b/drivers/soc/rockchip/reboot.c new file mode 100644 index 0000000..048aeb0b --- /dev/null +++ b/drivers/soc/rockchip/reboot.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/reboot.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include "loader.h" + +struct rockchip_reboot { + struct device *dev; + struct regmap *map; + u32 offset; + struct notifier_block reboot_notifier; +}; + +static void rockchip_get_reboot_flag(const char *cmd, u32 *flag) +{ + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_NORMAL; + + if (cmd) { + if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader")) + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER; + else if (!strcmp(cmd, "recovery")) + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER; + else if (!strcmp(cmd, "charge")) + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_CHARGING; + else if (!strcmp(cmd, "fastboot")) + *flag = SYS_LOADER_REBOOT_FLAG + BOOT_FASTBOOT; + } +} + +static int rockchip_reboot_notify(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + struct rockchip_reboot *reboot; + u32 flag; + + reboot = container_of(this, struct rockchip_reboot, reboot_notifier); + rockchip_get_reboot_flag(cmd, &flag); + regmap_write(reboot->map, reboot->offset, flag); + + return NOTIFY_DONE; +} + +static int __init rockchip_reboot_probe(struct platform_device *pdev) +{ + struct rockchip_reboot *reboot; + int ret; + + reboot = devm_kzalloc(&pdev->dev, sizeof(*reboot), GFP_KERNEL); + if (!reboot) + return -ENOMEM; + + reboot->dev = &pdev->dev; + reboot->map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "rockchip,regmap"); + if (IS_ERR(reboot->map)) + return PTR_ERR(reboot->map); + + if (of_property_read_u32(pdev->dev.of_node, "offset", &reboot->offset)) + return -EINVAL; + + reboot->reboot_notifier.notifier_call = rockchip_reboot_notify; + ret = register_reboot_notifier(&reboot->reboot_notifier); + if (ret) + dev_err(reboot->dev, "can't register reboot notifier\n"); + + return ret; +} + +static const struct of_device_id rockchip_reboot_of_match[] = { + { .compatible = "rockchip,reboot" }, + {} +}; + +static struct platform_driver rockchip_reboot_driver = { + .probe = rockchip_reboot_probe, + .driver = { + .name = "rockchip-reboot", + .of_match_table = rockchip_reboot_of_match, + }, +}; +module_platform_driver(rockchip_reboot_driver); + +MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com"); +MODULE_DESCRIPTION("Rockchip platform reboot notifier driver"); +MODULE_LICENSE("GPL");
rockchip platform have a protocol to pass the kernel reboot mode to bootloader by some special registers when system reboot. By this way the bootloader can take different action according to the different kernel reboot mode, for example, command "reboot loader" will reboot the board to rockusb mode, this is a very convenient way to get the board enter download mode. Signed-off-by: Andy Yan <andy.yan@rock-chips.com> --- Changes in v3: - move from mach-rockchip to drivers/soc/rockchip, as the tegra does - use dts pass the related register Changes in v2: - check cpu dt node - remove a unnecessary of_put_node in function rockchip_get_pmu_regmap - fix a align issue - use reboot_notifier instead of restart_handler drivers/soc/rockchip/Kconfig | 7 ++++ drivers/soc/rockchip/Makefile | 1 + drivers/soc/rockchip/loader.h | 22 ++++++++++ drivers/soc/rockchip/reboot.c | 98 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 drivers/soc/rockchip/loader.h create mode 100644 drivers/soc/rockchip/reboot.c