xref: /openbmc/linux/drivers/reset/reset-pistachio.c (revision 8a56736a2f53abe6edd1c67acc4f6161d5c16c07)
1*8a56736aSDamien Horsley /*
2*8a56736aSDamien Horsley  * Pistachio SoC Reset Controller driver
3*8a56736aSDamien Horsley  *
4*8a56736aSDamien Horsley  * Copyright (C) 2015 Imagination Technologies Ltd.
5*8a56736aSDamien Horsley  *
6*8a56736aSDamien Horsley  * Author: Damien Horsley <Damien.Horsley@imgtec.com>
7*8a56736aSDamien Horsley  *
8*8a56736aSDamien Horsley  * This program is free software; you can redistribute it and/or modify it
9*8a56736aSDamien Horsley  * under the terms and conditions of the GNU General Public License,
10*8a56736aSDamien Horsley  * version 2, as published by the Free Software Foundation.
11*8a56736aSDamien Horsley  */
12*8a56736aSDamien Horsley 
13*8a56736aSDamien Horsley #include <linux/module.h>
14*8a56736aSDamien Horsley #include <linux/of.h>
15*8a56736aSDamien Horsley #include <linux/platform_device.h>
16*8a56736aSDamien Horsley #include <linux/regmap.h>
17*8a56736aSDamien Horsley #include <linux/reset-controller.h>
18*8a56736aSDamien Horsley #include <linux/slab.h>
19*8a56736aSDamien Horsley #include <linux/mfd/syscon.h>
20*8a56736aSDamien Horsley 
21*8a56736aSDamien Horsley #include <dt-bindings/reset/pistachio-resets.h>
22*8a56736aSDamien Horsley 
23*8a56736aSDamien Horsley #define	PISTACHIO_SOFT_RESET		0
24*8a56736aSDamien Horsley 
25*8a56736aSDamien Horsley struct pistachio_reset_data {
26*8a56736aSDamien Horsley 	struct reset_controller_dev	rcdev;
27*8a56736aSDamien Horsley 	struct regmap			*periph_regs;
28*8a56736aSDamien Horsley };
29*8a56736aSDamien Horsley 
30*8a56736aSDamien Horsley static inline int pistachio_reset_shift(unsigned long id)
31*8a56736aSDamien Horsley {
32*8a56736aSDamien Horsley 	switch (id) {
33*8a56736aSDamien Horsley 	case PISTACHIO_RESET_I2C0:
34*8a56736aSDamien Horsley 	case PISTACHIO_RESET_I2C1:
35*8a56736aSDamien Horsley 	case PISTACHIO_RESET_I2C2:
36*8a56736aSDamien Horsley 	case PISTACHIO_RESET_I2C3:
37*8a56736aSDamien Horsley 	case PISTACHIO_RESET_I2S_IN:
38*8a56736aSDamien Horsley 	case PISTACHIO_RESET_PRL_OUT:
39*8a56736aSDamien Horsley 	case PISTACHIO_RESET_SPDIF_OUT:
40*8a56736aSDamien Horsley 	case PISTACHIO_RESET_SPI:
41*8a56736aSDamien Horsley 	case PISTACHIO_RESET_PWM_PDM:
42*8a56736aSDamien Horsley 	case PISTACHIO_RESET_UART0:
43*8a56736aSDamien Horsley 	case PISTACHIO_RESET_UART1:
44*8a56736aSDamien Horsley 	case PISTACHIO_RESET_QSPI:
45*8a56736aSDamien Horsley 	case PISTACHIO_RESET_MDC:
46*8a56736aSDamien Horsley 	case PISTACHIO_RESET_SDHOST:
47*8a56736aSDamien Horsley 	case PISTACHIO_RESET_ETHERNET:
48*8a56736aSDamien Horsley 	case PISTACHIO_RESET_IR:
49*8a56736aSDamien Horsley 	case PISTACHIO_RESET_HASH:
50*8a56736aSDamien Horsley 	case PISTACHIO_RESET_TIMER:
51*8a56736aSDamien Horsley 		return id;
52*8a56736aSDamien Horsley 	case PISTACHIO_RESET_I2S_OUT:
53*8a56736aSDamien Horsley 	case PISTACHIO_RESET_SPDIF_IN:
54*8a56736aSDamien Horsley 	case PISTACHIO_RESET_EVT:
55*8a56736aSDamien Horsley 		return id + 6;
56*8a56736aSDamien Horsley 	case PISTACHIO_RESET_USB_H:
57*8a56736aSDamien Horsley 	case PISTACHIO_RESET_USB_PR:
58*8a56736aSDamien Horsley 	case PISTACHIO_RESET_USB_PHY_PR:
59*8a56736aSDamien Horsley 	case PISTACHIO_RESET_USB_PHY_PON:
60*8a56736aSDamien Horsley 		return id + 7;
61*8a56736aSDamien Horsley 	default:
62*8a56736aSDamien Horsley 		return -EINVAL;
63*8a56736aSDamien Horsley 	}
64*8a56736aSDamien Horsley }
65*8a56736aSDamien Horsley 
66*8a56736aSDamien Horsley static int pistachio_reset_assert(struct reset_controller_dev *rcdev,
67*8a56736aSDamien Horsley 				  unsigned long id)
68*8a56736aSDamien Horsley {
69*8a56736aSDamien Horsley 	struct pistachio_reset_data *rd;
70*8a56736aSDamien Horsley 	u32 mask;
71*8a56736aSDamien Horsley 	int shift;
72*8a56736aSDamien Horsley 
73*8a56736aSDamien Horsley 	rd = container_of(rcdev, struct pistachio_reset_data, rcdev);
74*8a56736aSDamien Horsley 	shift = pistachio_reset_shift(id);
75*8a56736aSDamien Horsley 	if (shift < 0)
76*8a56736aSDamien Horsley 		return shift;
77*8a56736aSDamien Horsley 	mask = BIT(shift);
78*8a56736aSDamien Horsley 
79*8a56736aSDamien Horsley 	return regmap_update_bits(rd->periph_regs, PISTACHIO_SOFT_RESET,
80*8a56736aSDamien Horsley 				  mask, mask);
81*8a56736aSDamien Horsley }
82*8a56736aSDamien Horsley 
83*8a56736aSDamien Horsley static int pistachio_reset_deassert(struct reset_controller_dev *rcdev,
84*8a56736aSDamien Horsley 				    unsigned long id)
85*8a56736aSDamien Horsley {
86*8a56736aSDamien Horsley 	struct pistachio_reset_data *rd;
87*8a56736aSDamien Horsley 	u32 mask;
88*8a56736aSDamien Horsley 	int shift;
89*8a56736aSDamien Horsley 
90*8a56736aSDamien Horsley 	rd = container_of(rcdev, struct pistachio_reset_data, rcdev);
91*8a56736aSDamien Horsley 	shift = pistachio_reset_shift(id);
92*8a56736aSDamien Horsley 	if (shift < 0)
93*8a56736aSDamien Horsley 		return shift;
94*8a56736aSDamien Horsley 	mask = BIT(shift);
95*8a56736aSDamien Horsley 
96*8a56736aSDamien Horsley 	return regmap_update_bits(rd->periph_regs, PISTACHIO_SOFT_RESET,
97*8a56736aSDamien Horsley 				  mask, 0);
98*8a56736aSDamien Horsley }
99*8a56736aSDamien Horsley 
100*8a56736aSDamien Horsley static struct reset_control_ops pistachio_reset_ops = {
101*8a56736aSDamien Horsley 	.assert		= pistachio_reset_assert,
102*8a56736aSDamien Horsley 	.deassert	= pistachio_reset_deassert,
103*8a56736aSDamien Horsley };
104*8a56736aSDamien Horsley 
105*8a56736aSDamien Horsley static int pistachio_reset_probe(struct platform_device *pdev)
106*8a56736aSDamien Horsley {
107*8a56736aSDamien Horsley 	struct pistachio_reset_data *rd;
108*8a56736aSDamien Horsley 	struct device *dev = &pdev->dev;
109*8a56736aSDamien Horsley 	struct device_node *np = pdev->dev.of_node;
110*8a56736aSDamien Horsley 
111*8a56736aSDamien Horsley 	rd = devm_kzalloc(dev, sizeof(*rd), GFP_KERNEL);
112*8a56736aSDamien Horsley 	if (!rd)
113*8a56736aSDamien Horsley 		return -ENOMEM;
114*8a56736aSDamien Horsley 
115*8a56736aSDamien Horsley 	rd->periph_regs = syscon_node_to_regmap(np->parent);
116*8a56736aSDamien Horsley 	if (IS_ERR(rd->periph_regs))
117*8a56736aSDamien Horsley 		return PTR_ERR(rd->periph_regs);
118*8a56736aSDamien Horsley 
119*8a56736aSDamien Horsley 	rd->rcdev.owner = THIS_MODULE;
120*8a56736aSDamien Horsley 	rd->rcdev.nr_resets = PISTACHIO_RESET_MAX + 1;
121*8a56736aSDamien Horsley 	rd->rcdev.ops = &pistachio_reset_ops;
122*8a56736aSDamien Horsley 	rd->rcdev.of_node = np;
123*8a56736aSDamien Horsley 
124*8a56736aSDamien Horsley 	return reset_controller_register(&rd->rcdev);
125*8a56736aSDamien Horsley }
126*8a56736aSDamien Horsley 
127*8a56736aSDamien Horsley static int pistachio_reset_remove(struct platform_device *pdev)
128*8a56736aSDamien Horsley {
129*8a56736aSDamien Horsley 	struct pistachio_reset_data *data = platform_get_drvdata(pdev);
130*8a56736aSDamien Horsley 
131*8a56736aSDamien Horsley 	reset_controller_unregister(&data->rcdev);
132*8a56736aSDamien Horsley 
133*8a56736aSDamien Horsley 	return 0;
134*8a56736aSDamien Horsley }
135*8a56736aSDamien Horsley 
136*8a56736aSDamien Horsley static const struct of_device_id pistachio_reset_dt_ids[] = {
137*8a56736aSDamien Horsley 	 { .compatible = "img,pistachio-reset", },
138*8a56736aSDamien Horsley 	 { /* sentinel */ },
139*8a56736aSDamien Horsley };
140*8a56736aSDamien Horsley MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
141*8a56736aSDamien Horsley 
142*8a56736aSDamien Horsley static struct platform_driver pistachio_reset_driver = {
143*8a56736aSDamien Horsley 	.probe	= pistachio_reset_probe,
144*8a56736aSDamien Horsley 	.remove	= pistachio_reset_remove,
145*8a56736aSDamien Horsley 	.driver = {
146*8a56736aSDamien Horsley 		.name		= "pistachio-reset",
147*8a56736aSDamien Horsley 		.of_match_table	= pistachio_reset_dt_ids,
148*8a56736aSDamien Horsley 	},
149*8a56736aSDamien Horsley };
150*8a56736aSDamien Horsley module_platform_driver(pistachio_reset_driver);
151*8a56736aSDamien Horsley 
152*8a56736aSDamien Horsley MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
153*8a56736aSDamien Horsley MODULE_DESCRIPTION("Pistacho Reset Controller Driver");
154*8a56736aSDamien Horsley MODULE_LICENSE("GPL v2");
155