Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 535cee42 authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'keystone-reset-driver' of...

Merge tag 'keystone-reset-driver' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into next/drivers

Merge "Keystone Reset driver for 3.16" from Santosh Shilimkar:

* tag 'keystone-reset-driver' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone

:
  power: reset: keystone-reset: introduce keystone reset driver
  Documentation: dt: add bindings for keystone pll control controller
  Documentation: dt: add bindings for keystone reset driver

Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 3a5e23cf a3e01e80
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
* Device tree bindings for Texas Instruments keystone pll controller

The main pll controller used to drive theC66x CorePacs, the switch fabric,
and a majority of the peripheral clocks (all but the ARM CorePacs, DDR3 and
the NETCP modules) requires a PLL Controller to manage the various clock
divisions, gating, and synchronization.

Required properties:

- compatible:		"ti,keystone-pllctrl", "syscon"

- reg:			contains offset/length value for pll controller
			registers space.

Example:

pllctrl: pll-controller@0x02310000 {
	compatible = "ti,keystone-pllctrl", "syscon";
	reg = <0x02310000 0x200>;
};
+67 −0
Original line number Diff line number Diff line
* Device tree bindings for Texas Instruments keystone reset

This node is intended to allow SoC reset in case of software reset
of selected watchdogs.

The Keystone SoCs can contain up to 4 watchdog timers to reset
SoC. Each watchdog timer event input is connected to the Reset Mux
block. The Reset Mux block can be configured to cause reset or not.

Additionally soft or hard reset can be configured.

Required properties:

- compatible:		ti,keystone-reset

- ti,syscon-pll:	phandle/offset pair. The phandle to syscon used to
			access pll controller registers and the offset to use
			reset control registers.

- ti,syscon-dev:	phandle/offset pair. The phandle to syscon used to
			access device state control registers and the offset
			in order to use mux block registers for all watchdogs.

Optional properties:

- ti,soft-reset:	Boolean option indicating soft reset.
			By default hard reset is used.

- ti,wdt-list:		WDT list that can cause SoC reset. It's not related
			to WDT driver, it's just needed to enable a SoC related
			reset that's triggered by one of WDTs. The list is
			in format: <0>, <2>; It can be in random order and
			begins from 0 to 3, as keystone can contain up to 4 SoC
			reset watchdogs and can be in random order.

Example 1:
Setup keystone reset so that in case software reset or
WDT0 is triggered it issues hard reset for SoC.

pllctrl: pll-controller@02310000 {
	compatible = "ti,keystone-pllctrl", "syscon";
	reg = <0x02310000 0x200>;
};

devctrl: device-state-control@02620000 {
	compatible = "ti,keystone-devctrl", "syscon";
	reg = <0x02620000 0x1000>;
};

rstctrl: reset-controller {
	compatible = "ti,keystone-reset";
	ti,syscon-pll = <&pllctrl 0xe4>;
	ti,syscon-dev = <&devctrl 0x328>;
	ti,wdt-list = <0>;
};

Example 2:
Setup keystone reset so that in case of software reset or
WDT0 or WDT2 is triggered it issues soft reset for SoC.

rstctrl: reset-controller {
	compatible = "ti,keystone-reset";
	ti,syscon-pll = <&pllctrl 0xe4>;
	ti,syscon-dev = <&devctrl 0x328>;
	ti,wdt-list = <0>, <2>;
	ti,soft-reset;
};
+8 −0
Original line number Diff line number Diff line
@@ -64,3 +64,11 @@ config POWER_RESET_XGENE
	depends on POWER_RESET
	help
	  Reboot support for the APM SoC X-Gene Eval boards.

config POWER_RESET_KEYSTONE
	bool "Keystone reset driver"
	depends on ARCH_KEYSTONE
	select MFD_SYSCON
	help
	  Reboot support for the KEYSTONE SoCs.
+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@ obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
obj-$(CONFIG_POWER_RESET_SUN6I) += sun6i-reboot.o
obj-$(CONFIG_POWER_RESET_VEXPRESS) += vexpress-poweroff.o
obj-$(CONFIG_POWER_RESET_XGENE) += xgene-reboot.o
obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o
+166 −0
Original line number Diff line number Diff line
/*
 * TI keystone reboot driver
 *
 * Copyright (C) 2014 Texas Instruments Incorporated. http://www.ti.com/
 *
 * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/io.h>
#include <linux/module.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <asm/system_misc.h>
#include <linux/mfd/syscon.h>
#include <linux/of_platform.h>

#define RSTYPE_RG			0x0
#define RSCTRL_RG			0x4
#define RSCFG_RG			0x8
#define RSISO_RG			0xc

#define RSCTRL_KEY_MASK			0x0000ffff
#define RSCTRL_RESET_MASK		BIT(16)
#define RSCTRL_KEY			0x5a69

#define RSMUX_OMODE_MASK		0xe
#define RSMUX_OMODE_RESET_ON		0xa
#define RSMUX_OMODE_RESET_OFF		0x0
#define RSMUX_LOCK_MASK			0x1
#define RSMUX_LOCK_SET			0x1

#define RSCFG_RSTYPE_SOFT		0x300f
#define RSCFG_RSTYPE_HARD		0x0

#define WDT_MUX_NUMBER			0x4

static int rspll_offset;
static struct regmap *pllctrl_regs;

/**
 * rsctrl_enable_rspll_write - enable access to RSCTRL, RSCFG
 * To be able to access to RSCTRL, RSCFG registers
 * we have to write a key before
 */
static inline int rsctrl_enable_rspll_write(void)
{
	return regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
				  RSCTRL_KEY_MASK, RSCTRL_KEY);
}

static void rsctrl_restart(enum reboot_mode mode, const char *cmd)
{
	/* enable write access to RSTCTRL */
	rsctrl_enable_rspll_write();

	/* reset the SOC */
	regmap_update_bits(pllctrl_regs, rspll_offset + RSCTRL_RG,
			   RSCTRL_RESET_MASK, 0);
}

static struct of_device_id rsctrl_of_match[] = {
	{.compatible = "ti,keystone-reset", },
	{},
};

static int rsctrl_probe(struct platform_device *pdev)
{
	int i;
	int ret;
	u32 val;
	unsigned int rg;
	u32 rsmux_offset;
	struct regmap *devctrl_regs;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;

	if (!np)
		return -ENODEV;

	/* get regmaps */
	pllctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-pll");
	if (IS_ERR(pllctrl_regs))
		return PTR_ERR(pllctrl_regs);

	devctrl_regs = syscon_regmap_lookup_by_phandle(np, "ti,syscon-dev");
	if (IS_ERR(devctrl_regs))
		return PTR_ERR(devctrl_regs);

	ret = of_property_read_u32_index(np, "ti,syscon-pll", 1, &rspll_offset);
	if (ret) {
		dev_err(dev, "couldn't read the reset pll offset!\n");
		return -EINVAL;
	}

	ret = of_property_read_u32_index(np, "ti,syscon-dev", 1, &rsmux_offset);
	if (ret) {
		dev_err(dev, "couldn't read the rsmux offset!\n");
		return -EINVAL;
	}

	/* set soft/hard reset */
	val = of_property_read_bool(np, "ti,soft-reset");
	val = val ? RSCFG_RSTYPE_SOFT : RSCFG_RSTYPE_HARD;

	ret = rsctrl_enable_rspll_write();
	if (ret)
		return ret;

	ret = regmap_write(pllctrl_regs, rspll_offset + RSCFG_RG, val);
	if (ret)
		return ret;

	arm_pm_restart = rsctrl_restart;

	/* disable a reset isolation for all module clocks */
	ret = regmap_write(pllctrl_regs, rspll_offset + RSISO_RG, 0);
	if (ret)
		return ret;

	/* enable a reset for watchdogs from wdt-list */
	for (i = 0; i < WDT_MUX_NUMBER; i++) {
		ret = of_property_read_u32_index(np, "ti,wdt-list", i, &val);
		if (ret == -EOVERFLOW && !i) {
			dev_err(dev, "ti,wdt-list property has to contain at"
				"least one entry\n");
			return -EINVAL;
		} else if (ret) {
			break;
		}

		if (val >= WDT_MUX_NUMBER) {
			dev_err(dev, "ti,wdt-list property can contain"
				"only numbers < 4\n");
			return -EINVAL;
		}

		rg = rsmux_offset + val * 4;

		ret = regmap_update_bits(devctrl_regs, rg, RSMUX_OMODE_MASK,
					 RSMUX_OMODE_RESET_ON |
					 RSMUX_LOCK_SET);
		if (ret)
			return ret;
	}

	return 0;
}

static struct platform_driver rsctrl_driver = {
	.probe = rsctrl_probe,
	.driver = {
		.owner = THIS_MODULE,
		.name = KBUILD_MODNAME,
		.of_match_table = rsctrl_of_match,
	},
};
module_platform_driver(rsctrl_driver);

MODULE_AUTHOR("Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>");
MODULE_DESCRIPTION("Texas Instruments keystone reset driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" KBUILD_MODNAME);