brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · dbc4ff6 Raw
174 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI keystone reboot driver4 *5 * Copyright (C) 2014 Texas Instruments Incorporated. https://www.ti.com/6 *7 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>8 */9 10#include <linux/io.h>11#include <linux/module.h>12#include <linux/notifier.h>13#include <linux/platform_device.h>14#include <linux/reboot.h>15#include <linux/regmap.h>16#include <linux/mfd/syscon.h>17#include <linux/of.h>18 19#define RSTYPE_RG			0x020#define RSCTRL_RG			0x421#define RSCFG_RG			0x822#define RSISO_RG			0xc23 24#define RSCTRL_KEY_MASK			0x0000ffff25#define RSCTRL_RESET_MASK		BIT(16)26#define RSCTRL_KEY			0x5a6927 28#define RSMUX_OMODE_MASK		0xe29#define RSMUX_OMODE_RESET_ON		0xa30#define RSMUX_OMODE_RESET_OFF		0x031#define RSMUX_LOCK_MASK			0x132#define RSMUX_LOCK_SET			0x133 34#define RSCFG_RSTYPE_SOFT		0x300f35#define RSCFG_RSTYPE_HARD		0x036 37#define WDT_MUX_NUMBER			0x438 39static int rspll_offset;40static struct regmap *pllctrl_regs;41 42/**43 * rsctrl_enable_rspll_write - enable access to RSCTRL, RSCFG44 * To be able to access to RSCTRL, RSCFG registers45 * we have to write a key before46 */47static inline int rsctrl_enable_rspll_write(void)48{49	return regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,50				  RSCTRL_KEY_MASK, RSCTRL_KEY);51}52 53static int rsctrl_restart_handler(struct notifier_block *this,54				  unsigned long mode, void *cmd)55{56	/* enable write access to RSTCTRL */57	rsctrl_enable_rspll_write();58 59	/* reset the SOC */60	regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,61			   RSCTRL_RESET_MASK, 0);62 63	return NOTIFY_DONE;64}65 66static struct notifier_block rsctrl_restart_nb = {67	.notifier_call = rsctrl_restart_handler,68	.priority = 128,69};70 71static const struct of_device_id rsctrl_of_match[] = {72	{.compatible = "ti,keystone-reset", },73	{},74};75MODULE_DEVICE_TABLE(of, rsctrl_of_match);76 77static int rsctrl_probe(struct platform_device *pdev)78{79	int i;80	int ret;81	u32 val;82	unsigned int rg;83	u32 rsmux_offset;84	struct regmap *devctrl_regs;85	struct device *dev = &pdev->dev;86	struct device_node *np = dev->of_node;87 88	if (!np)89		return -ENODEV;90 91	/* get regmaps */92	pllctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pll");93	if (IS_ERR(pllctrl_regs))94		return PTR_ERR(pllctrl_regs);95 96	devctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev");97	if (IS_ERR(devctrl_regs))98		return PTR_ERR(devctrl_regs);99 100	ret = of_property_read_u32_index(np, "ti,syscon-pll", 1, &rspll_offset);101	if (ret) {102		dev_err(dev, "couldn't read the reset pll offset!\n");103		return -EINVAL;104	}105 106	ret = of_property_read_u32_index(np, "ti,syscon-dev", 1, &rsmux_offset);107	if (ret) {108		dev_err(dev, "couldn't read the rsmux offset!\n");109		return -EINVAL;110	}111 112	/* set soft/hard reset */113	val = of_property_read_bool(np, "ti,soft-reset");114	val = val ? RSCFG_RSTYPE_SOFT : RSCFG_RSTYPE_HARD;115 116	ret = rsctrl_enable_rspll_write();117	if (ret)118		return ret;119 120	ret = regmap_write(pllctrl_regs, rspll_offset + RSCFG_RG, val);121	if (ret)122		return ret;123 124	/* disable a reset isolation for all module clocks */125	ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0);126	if (ret)127		return ret;128 129	/* enable a reset for watchdogs from wdt-list */130	for (i = 0; i < WDT_MUX_NUMBER; i++) {131		ret = of_property_read_u32_index(np, "ti,wdt-list", i, &val);132		if (ret == -EOVERFLOW && !i) {133			dev_err(dev, "ti,wdt-list property has to contain at"134				"least one entry\n");135			return -EINVAL;136		} else if (ret) {137			break;138		}139 140		if (val >= WDT_MUX_NUMBER) {141			dev_err(dev, "ti,wdt-list property can contain "142				"only numbers < 4\n");143			return -EINVAL;144		}145 146		rg = rsmux_offset + val * 4;147 148		ret = regmap_update_bits(devctrl_regs, rg, RSMUX_OMODE_MASK,149					 RSMUX_OMODE_RESET_ON |150					 RSMUX_LOCK_SET);151		if (ret)152			return ret;153	}154 155	ret = register_restart_handler(&rsctrl_restart_nb);156	if (ret)157		dev_err(dev, "cannot register restart handler (err=%d)\n", ret);158 159	return ret;160}161 162static struct platform_driver rsctrl_driver = {163	.probe = rsctrl_probe,164	.driver = {165		.name = KBUILD_MODNAME,166		.of_match_table = rsctrl_of_match,167	},168};169module_platform_driver(rsctrl_driver);170 171MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");172MODULE_DESCRIPTION("Texas Instruments keystone reset driver");173MODULE_ALIAS("platform:" KBUILD_MODNAME);174