brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · df58dec Raw
212 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2/*3 * SP7021 reset driver4 *5 * Copyright (C) Sunplus Technology Co., Ltd.6 *       All rights reserved.7 */8 9#include <linux/io.h>10#include <linux/init.h>11#include <linux/mod_devicetable.h>12#include <linux/platform_device.h>13#include <linux/reset-controller.h>14#include <linux/reboot.h>15 16/* HIWORD_MASK_REG BITS */17#define BITS_PER_HWM_REG	1618 19/* resets HW info: reg_index_shift */20static const u32 sp_resets[] = {21/* SP7021: mo_reset0 ~ mo_reset9 */22	0x00,23	0x02,24	0x03,25	0x04,26	0x05,27	0x06,28	0x07,29	0x08,30	0x09,31	0x0a,32	0x0b,33	0x0d,34	0x0e,35	0x0f,36	0x10,37	0x12,38	0x14,39	0x15,40	0x16,41	0x17,42	0x18,43	0x19,44	0x1a,45	0x1b,46	0x1c,47	0x1d,48	0x1e,49	0x1f,50	0x20,51	0x21,52	0x22,53	0x23,54	0x24,55	0x25,56	0x26,57	0x2a,58	0x2b,59	0x2d,60	0x2e,61	0x30,62	0x31,63	0x32,64	0x33,65	0x3d,66	0x3e,67	0x3f,68	0x42,69	0x44,70	0x4b,71	0x4c,72	0x4d,73	0x4e,74	0x4f,75	0x50,76	0x55,77	0x60,78	0x61,79	0x6a,80	0x6f,81	0x70,82	0x73,83	0x74,84	0x86,85	0x8a,86	0x8b,87	0x8d,88	0x8e,89	0x8f,90	0x90,91	0x92,92	0x93,93	0x94,94	0x95,95	0x96,96	0x97,97	0x98,98	0x99,99};100 101struct sp_reset {102	struct reset_controller_dev rcdev;103	struct notifier_block notifier;104	void __iomem *base;105};106 107static inline struct sp_reset *to_sp_reset(struct reset_controller_dev *rcdev)108{109	return container_of(rcdev, struct sp_reset, rcdev);110}111 112static int sp_reset_update(struct reset_controller_dev *rcdev,113			   unsigned long id, bool assert)114{115	struct sp_reset *reset = to_sp_reset(rcdev);116	int index = sp_resets[id] / BITS_PER_HWM_REG;117	int shift = sp_resets[id] % BITS_PER_HWM_REG;118	u32 val;119 120	val = (1 << (16 + shift)) | (assert << shift);121	writel(val, reset->base + (index * 4));122 123	return 0;124}125 126static int sp_reset_assert(struct reset_controller_dev *rcdev,127			   unsigned long id)128{129	return sp_reset_update(rcdev, id, true);130}131 132static int sp_reset_deassert(struct reset_controller_dev *rcdev,133			     unsigned long id)134{135	return sp_reset_update(rcdev, id, false);136}137 138static int sp_reset_status(struct reset_controller_dev *rcdev,139			   unsigned long id)140{141	struct sp_reset *reset = to_sp_reset(rcdev);142	int index = sp_resets[id] / BITS_PER_HWM_REG;143	int shift = sp_resets[id] % BITS_PER_HWM_REG;144	u32 reg;145 146	reg = readl(reset->base + (index * 4));147 148	return !!(reg & BIT(shift));149}150 151static const struct reset_control_ops sp_reset_ops = {152	.assert   = sp_reset_assert,153	.deassert = sp_reset_deassert,154	.status   = sp_reset_status,155};156 157static int sp_restart(struct notifier_block *nb, unsigned long mode,158		      void *cmd)159{160	struct sp_reset *reset = container_of(nb, struct sp_reset, notifier);161 162	sp_reset_assert(&reset->rcdev, 0);163	sp_reset_deassert(&reset->rcdev, 0);164 165	return NOTIFY_DONE;166}167 168static int sp_reset_probe(struct platform_device *pdev)169{170	struct device *dev = &pdev->dev;171	struct sp_reset *reset;172	struct resource *res;173	int ret;174 175	reset = devm_kzalloc(dev, sizeof(*reset), GFP_KERNEL);176	if (!reset)177		return -ENOMEM;178 179	reset->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);180	if (IS_ERR(reset->base))181		return PTR_ERR(reset->base);182 183	reset->rcdev.ops = &sp_reset_ops;184	reset->rcdev.owner = THIS_MODULE;185	reset->rcdev.of_node = dev->of_node;186	reset->rcdev.nr_resets = resource_size(res) / 4 * BITS_PER_HWM_REG;187 188	ret = devm_reset_controller_register(dev, &reset->rcdev);189	if (ret)190		return ret;191 192	reset->notifier.notifier_call = sp_restart;193	reset->notifier.priority = 192;194 195	return register_restart_handler(&reset->notifier);196}197 198static const struct of_device_id sp_reset_dt_ids[] = {199	{.compatible = "sunplus,sp7021-reset",},200	{ /* sentinel */ },201};202 203static struct platform_driver sp_reset_driver = {204	.probe = sp_reset_probe,205	.driver = {206		.name			= "sunplus-reset",207		.of_match_table		= sp_reset_dt_ids,208		.suppress_bind_attrs	= true,209	},210};211builtin_platform_driver(sp_reset_driver);212