1243789Sdim// SPDX-License-Identifier: GPL-2.0 2243789Sdim/* 3243789Sdim * Renesas R-Mobile Reset Driver 4243789Sdim * 5243789Sdim * Copyright (C) 2014 Glider bvba 6243789Sdim */ 7243789Sdim 8243789Sdim#include <linux/io.h> 9243789Sdim#include <linux/module.h> 10243789Sdim#include <linux/notifier.h> 11243789Sdim#include <linux/of_address.h> 12243789Sdim#include <linux/platform_device.h> 13243789Sdim#include <linux/printk.h> 14243789Sdim#include <linux/reboot.h> 15243789Sdim 16243789Sdim/* SYSC Register Bank 2 */ 17243789Sdim#define RESCNT2 0x20 /* Reset Control Register 2 */ 18249423Sdim 19243789Sdim/* Reset Control Register 2 */ 20249423Sdim#define RESCNT2_PRES 0x80000000 /* Soft power-on reset */ 21249423Sdim 22249423Sdimstatic int rmobile_reset_handler(struct sys_off_data *data) 23243789Sdim{ 24243789Sdim void __iomem *sysc_base2 = (void __iomem *)data->cb_data; 25243789Sdim 26276479Sdim /* Let's assume we have acquired the HPB semaphore */ 27276479Sdim writel(RESCNT2_PRES, sysc_base2 + RESCNT2); 28243789Sdim 29243789Sdim return NOTIFY_DONE; 30243789Sdim} 31243789Sdim 32243789Sdimstatic int rmobile_reset_probe(struct platform_device *pdev) 33243789Sdim{ 34243789Sdim void __iomem *sysc_base2; 35243789Sdim int error; 36243789Sdim 37243789Sdim sysc_base2 = devm_platform_ioremap_resource(pdev, 1); 38243789Sdim if (IS_ERR(sysc_base2)) 39243789Sdim return PTR_ERR(sysc_base2); 40243789Sdim 41243789Sdim error = devm_register_sys_off_handler(&pdev->dev, 42243789Sdim SYS_OFF_MODE_RESTART, 43243789Sdim SYS_OFF_PRIO_HIGH, 44243789Sdim rmobile_reset_handler, 45243789Sdim (__force void *)sysc_base2); 46243789Sdim if (error) { 47243789Sdim dev_err(&pdev->dev, 48243789Sdim "cannot register restart handler (err=%d)\n", error); 49243789Sdim return error; 50243789Sdim } 51243789Sdim 52243789Sdim return 0; 53243789Sdim} 54243789Sdim 55243789Sdimstatic const struct of_device_id rmobile_reset_of_match[] = { 56243789Sdim { .compatible = "renesas,sysc-rmobile", }, 57276479Sdim { /* sentinel */ } 58243789Sdim}; 59243789SdimMODULE_DEVICE_TABLE(of, rmobile_reset_of_match); 60243789Sdim 61276479Sdimstatic struct platform_driver rmobile_reset_driver = { 62243789Sdim .probe = rmobile_reset_probe, 63243789Sdim .driver = { 64243789Sdim .name = "rmobile_reset", 65243789Sdim .of_match_table = rmobile_reset_of_match, 66243789Sdim }, 67243789Sdim}; 68243789Sdim 69243789Sdimmodule_platform_driver(rmobile_reset_driver); 70243789Sdim 71243789SdimMODULE_DESCRIPTION("Renesas R-Mobile Reset Driver"); 72243789SdimMODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>"); 73243789SdimMODULE_LICENSE("GPL v2"); 74243789Sdim