Home | History | Annotate | Download | only in reset
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2016 Socionext Inc.
      4  *   Author: Masahiro Yamada <yamada.masahiro (at) socionext.com>
      5  */
      6 
      7 #include <common.h>
      8 #include <dm.h>
      9 #include <reset-uclass.h>
     10 #include <linux/bitops.h>
     11 #include <linux/io.h>
     12 #include <linux/sizes.h>
     13 
     14 struct uniphier_reset_data {
     15 	unsigned int id;
     16 	unsigned int reg;
     17 	unsigned int bit;
     18 	unsigned int flags;
     19 #define UNIPHIER_RESET_ACTIVE_LOW		BIT(0)
     20 };
     21 
     22 #define UNIPHIER_RESET_ID_END		(unsigned int)(-1)
     23 
     24 #define UNIPHIER_RESET_END				\
     25 	{ .id = UNIPHIER_RESET_ID_END }
     26 
     27 #define UNIPHIER_RESET(_id, _reg, _bit)			\
     28 	{						\
     29 		.id = (_id),				\
     30 		.reg = (_reg),				\
     31 		.bit = (_bit),				\
     32 	}
     33 
     34 #define UNIPHIER_RESETX(_id, _reg, _bit)		\
     35 	{						\
     36 		.id = (_id),				\
     37 		.reg = (_reg),				\
     38 		.bit = (_bit),				\
     39 		.flags = UNIPHIER_RESET_ACTIVE_LOW,	\
     40 	}
     41 
     42 /* System reset data */
     43 static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
     44 	UNIPHIER_RESETX(2, 0x2000, 2),		/* NAND */
     45 	UNIPHIER_RESETX(6, 0x2000, 12),		/* ETHER */
     46 	UNIPHIER_RESETX(8, 0x2000, 10),		/* STDMAC */
     47 	UNIPHIER_RESETX(12, 0x2000, 6),		/* GIO */
     48 	UNIPHIER_RESETX(14, 0x2000, 17),	/* USB30 */
     49 	UNIPHIER_RESETX(15, 0x2004, 17),	/* USB31 */
     50 	UNIPHIER_RESET_END,
     51 };
     52 
     53 static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
     54 	UNIPHIER_RESETX(2, 0x2000, 2),		/* NAND */
     55 	UNIPHIER_RESETX(6, 0x2000, 12),		/* ETHER */
     56 	UNIPHIER_RESETX(8, 0x2000, 10),		/* STDMAC */
     57 	UNIPHIER_RESETX(14, 0x2000, 17),	/* USB30 */
     58 	UNIPHIER_RESETX(15, 0x2004, 17),	/* USB31 */
     59 	UNIPHIER_RESETX(16, 0x2014, 4),		/* USB30-PHY0 */
     60 	UNIPHIER_RESETX(17, 0x2014, 0),		/* USB30-PHY1 */
     61 	UNIPHIER_RESETX(18, 0x2014, 2),		/* USB30-PHY2 */
     62 	UNIPHIER_RESETX(20, 0x2014, 5),		/* USB31-PHY0 */
     63 	UNIPHIER_RESETX(21, 0x2014, 1),		/* USB31-PHY1 */
     64 	UNIPHIER_RESETX(28, 0x2014, 12),	/* SATA */
     65 	UNIPHIER_RESET(29, 0x2014, 8),		/* SATA-PHY (active high) */
     66 	UNIPHIER_RESET_END,
     67 };
     68 
     69 static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
     70 	UNIPHIER_RESETX(2, 0x200c, 0),		/* NAND */
     71 	UNIPHIER_RESETX(4, 0x200c, 2),		/* eMMC */
     72 	UNIPHIER_RESETX(6, 0x200c, 6),		/* ETHER */
     73 	UNIPHIER_RESETX(8, 0x200c, 8),		/* STDMAC */
     74 	UNIPHIER_RESETX(14, 0x200c, 5),		/* USB30 */
     75 	UNIPHIER_RESETX(16, 0x200c, 12),	/* USB30-PHY0 */
     76 	UNIPHIER_RESETX(17, 0x200c, 13),	/* USB30-PHY1 */
     77 	UNIPHIER_RESETX(18, 0x200c, 14),	/* USB30-PHY2 */
     78 	UNIPHIER_RESETX(19, 0x200c, 15),	/* USB30-PHY3 */
     79 	UNIPHIER_RESET_END,
     80 };
     81 
     82 static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
     83 	UNIPHIER_RESETX(2, 0x200c, 0),		/* NAND */
     84 	UNIPHIER_RESETX(4, 0x200c, 2),		/* eMMC */
     85 	UNIPHIER_RESETX(6, 0x200c, 9),		/* ETHER0 */
     86 	UNIPHIER_RESETX(7, 0x200c, 10),		/* ETHER1 */
     87 	UNIPHIER_RESETX(8, 0x200c, 12),		/* STDMAC */
     88 	UNIPHIER_RESETX(12, 0x200c, 4),		/* USB30 link */
     89 	UNIPHIER_RESETX(13, 0x200c, 5),		/* USB31 link */
     90 	UNIPHIER_RESETX(16, 0x200c, 16),	/* USB30-PHY0 */
     91 	UNIPHIER_RESETX(17, 0x200c, 18),	/* USB30-PHY1 */
     92 	UNIPHIER_RESETX(18, 0x200c, 20),	/* USB30-PHY2 */
     93 	UNIPHIER_RESETX(20, 0x200c, 17),	/* USB31-PHY0 */
     94 	UNIPHIER_RESETX(21, 0x200c, 19),	/* USB31-PHY1 */
     95 	UNIPHIER_RESET_END,
     96 };
     97 
     98 /* Media I/O reset data */
     99 #define UNIPHIER_MIO_RESET_SD(id, ch)			\
    100 	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0)
    101 
    102 #define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch)		\
    103 	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26)
    104 
    105 #define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch)	\
    106 	UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0)
    107 
    108 #define UNIPHIER_MIO_RESET_USB2(id, ch)			\
    109 	UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0)
    110 
    111 #define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch)		\
    112 	UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24)
    113 
    114 #define UNIPHIER_MIO_RESET_DMAC(id)			\
    115 	UNIPHIER_RESETX((id), 0x110, 17)
    116 
    117 static const struct uniphier_reset_data uniphier_mio_reset_data[] = {
    118 	UNIPHIER_MIO_RESET_SD(0, 0),
    119 	UNIPHIER_MIO_RESET_SD(1, 1),
    120 	UNIPHIER_MIO_RESET_SD(2, 2),
    121 	UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0),
    122 	UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1),
    123 	UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2),
    124 	UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
    125 	UNIPHIER_MIO_RESET_DMAC(7),
    126 	UNIPHIER_MIO_RESET_USB2(8, 0),
    127 	UNIPHIER_MIO_RESET_USB2(9, 1),
    128 	UNIPHIER_MIO_RESET_USB2(10, 2),
    129 	UNIPHIER_MIO_RESET_USB2(11, 3),
    130 	UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
    131 	UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
    132 	UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
    133 	UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
    134 	UNIPHIER_RESET_END,
    135 };
    136 
    137 /* Peripheral reset data */
    138 #define UNIPHIER_PERI_RESET_UART(id, ch)		\
    139 	UNIPHIER_RESETX((id), 0x114, 19 + (ch))
    140 
    141 #define UNIPHIER_PERI_RESET_I2C(id, ch)			\
    142 	UNIPHIER_RESETX((id), 0x114, 5 + (ch))
    143 
    144 #define UNIPHIER_PERI_RESET_FI2C(id, ch)		\
    145 	UNIPHIER_RESETX((id), 0x114, 24 + (ch))
    146 
    147 static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
    148 	UNIPHIER_PERI_RESET_UART(0, 0),
    149 	UNIPHIER_PERI_RESET_UART(1, 1),
    150 	UNIPHIER_PERI_RESET_UART(2, 2),
    151 	UNIPHIER_PERI_RESET_UART(3, 3),
    152 	UNIPHIER_PERI_RESET_I2C(4, 0),
    153 	UNIPHIER_PERI_RESET_I2C(5, 1),
    154 	UNIPHIER_PERI_RESET_I2C(6, 2),
    155 	UNIPHIER_PERI_RESET_I2C(7, 3),
    156 	UNIPHIER_PERI_RESET_I2C(8, 4),
    157 	UNIPHIER_RESET_END,
    158 };
    159 
    160 static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
    161 	UNIPHIER_PERI_RESET_UART(0, 0),
    162 	UNIPHIER_PERI_RESET_UART(1, 1),
    163 	UNIPHIER_PERI_RESET_UART(2, 2),
    164 	UNIPHIER_PERI_RESET_UART(3, 3),
    165 	UNIPHIER_PERI_RESET_FI2C(4, 0),
    166 	UNIPHIER_PERI_RESET_FI2C(5, 1),
    167 	UNIPHIER_PERI_RESET_FI2C(6, 2),
    168 	UNIPHIER_PERI_RESET_FI2C(7, 3),
    169 	UNIPHIER_PERI_RESET_FI2C(8, 4),
    170 	UNIPHIER_PERI_RESET_FI2C(9, 5),
    171 	UNIPHIER_PERI_RESET_FI2C(10, 6),
    172 	UNIPHIER_RESET_END,
    173 };
    174 
    175 /* core implementaton */
    176 struct uniphier_reset_priv {
    177 	void __iomem *base;
    178 	const struct uniphier_reset_data *data;
    179 };
    180 
    181 static int uniphier_reset_request(struct reset_ctl *reset_ctl)
    182 {
    183 	return 0;
    184 }
    185 
    186 static int uniphier_reset_free(struct reset_ctl *reset_ctl)
    187 {
    188 	return 0;
    189 }
    190 
    191 static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert)
    192 {
    193 	struct uniphier_reset_priv *priv = dev_get_priv(reset_ctl->dev);
    194 	unsigned long id = reset_ctl->id;
    195 	const struct uniphier_reset_data *p;
    196 
    197 	for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) {
    198 		u32 mask, val;
    199 
    200 		if (p->id != id)
    201 			continue;
    202 
    203 		val = readl(priv->base + p->reg);
    204 
    205 		if (p->flags & UNIPHIER_RESET_ACTIVE_LOW)
    206 			assert = !assert;
    207 
    208 		mask = BIT(p->bit);
    209 
    210 		if (assert)
    211 			val |= mask;
    212 		else
    213 			val &= ~mask;
    214 
    215 		writel(val, priv->base + p->reg);
    216 
    217 		return 0;
    218 	}
    219 
    220 	dev_err(reset_ctl->dev, "reset_id=%lu was not handled\n", id);
    221 
    222 	return -EINVAL;
    223 }
    224 
    225 static int uniphier_reset_assert(struct reset_ctl *reset_ctl)
    226 {
    227 	return uniphier_reset_update(reset_ctl, 1);
    228 }
    229 
    230 static int uniphier_reset_deassert(struct reset_ctl *reset_ctl)
    231 {
    232 	return uniphier_reset_update(reset_ctl, 0);
    233 }
    234 
    235 static const struct reset_ops uniphier_reset_ops = {
    236 	.request = uniphier_reset_request,
    237 	.free = uniphier_reset_free,
    238 	.rst_assert = uniphier_reset_assert,
    239 	.rst_deassert = uniphier_reset_deassert,
    240 };
    241 
    242 static int uniphier_reset_probe(struct udevice *dev)
    243 {
    244 	struct uniphier_reset_priv *priv = dev_get_priv(dev);
    245 	fdt_addr_t addr;
    246 
    247 	addr = devfdt_get_addr(dev->parent);
    248 	if (addr == FDT_ADDR_T_NONE)
    249 		return -EINVAL;
    250 
    251 	priv->base = devm_ioremap(dev, addr, SZ_4K);
    252 	if (!priv->base)
    253 		return -ENOMEM;
    254 
    255 	priv->data = (void *)dev_get_driver_data(dev);
    256 
    257 	return 0;
    258 }
    259 
    260 static const struct udevice_id uniphier_reset_match[] = {
    261 	/* System reset */
    262 	{
    263 		.compatible = "socionext,uniphier-ld4-reset",
    264 		.data = (ulong)uniphier_pro4_sys_reset_data,
    265 	},
    266 	{
    267 		.compatible = "socionext,uniphier-pro4-reset",
    268 		.data = (ulong)uniphier_pro4_sys_reset_data,
    269 	},
    270 	{
    271 		.compatible = "socionext,uniphier-sld8-reset",
    272 		.data = (ulong)uniphier_pro4_sys_reset_data,
    273 	},
    274 	{
    275 		.compatible = "socionext,uniphier-pro5-reset",
    276 		.data = (ulong)uniphier_pro4_sys_reset_data,
    277 	},
    278 	{
    279 		.compatible = "socionext,uniphier-pxs2-reset",
    280 		.data = (ulong)uniphier_pxs2_sys_reset_data,
    281 	},
    282 	{
    283 		.compatible = "socionext,uniphier-ld11-reset",
    284 		.data = (ulong)uniphier_ld20_sys_reset_data,
    285 	},
    286 	{
    287 		.compatible = "socionext,uniphier-ld20-reset",
    288 		.data = (ulong)uniphier_ld20_sys_reset_data,
    289 	},
    290 	{
    291 		.compatible = "socionext,uniphier-pxs3-reset",
    292 		.data = (ulong)uniphier_pxs3_sys_reset_data,
    293 	},
    294 	/* Media I/O reset */
    295 	{
    296 		.compatible = "socionext,uniphier-ld4-mio-reset",
    297 		.data = (ulong)uniphier_mio_reset_data,
    298 	},
    299 	{
    300 		.compatible = "socionext,uniphier-pro4-mio-reset",
    301 		.data = (ulong)uniphier_mio_reset_data,
    302 	},
    303 	{
    304 		.compatible = "socionext,uniphier-sld8-mio-reset",
    305 		.data = (ulong)uniphier_mio_reset_data,
    306 	},
    307 	{
    308 		.compatible = "socionext,uniphier-pro5-mio-reset",
    309 		.data = (ulong)uniphier_mio_reset_data,
    310 	},
    311 	{
    312 		.compatible = "socionext,uniphier-pxs2-mio-reset",
    313 		.data = (ulong)uniphier_mio_reset_data,
    314 	},
    315 	{
    316 		.compatible = "socionext,uniphier-ld11-mio-reset",
    317 		.data = (ulong)uniphier_mio_reset_data,
    318 	},
    319 	{
    320 		.compatible = "socionext,uniphier-ld11-sd-reset",
    321 		.data = (ulong)uniphier_mio_reset_data,
    322 	},
    323 	{
    324 		.compatible = "socionext,uniphier-ld20-sd-reset",
    325 		.data = (ulong)uniphier_mio_reset_data,
    326 	},
    327 	{
    328 		.compatible = "socionext,uniphier-pxs3-sd-reset",
    329 		.data = (ulong)uniphier_mio_reset_data,
    330 	},
    331 	/* Peripheral reset */
    332 	{
    333 		.compatible = "socionext,uniphier-ld4-peri-reset",
    334 		.data = (ulong)uniphier_ld4_peri_reset_data,
    335 	},
    336 	{
    337 		.compatible = "socionext,uniphier-pro4-peri-reset",
    338 		.data = (ulong)uniphier_pro4_peri_reset_data,
    339 	},
    340 	{
    341 		.compatible = "socionext,uniphier-sld8-peri-reset",
    342 		.data = (ulong)uniphier_ld4_peri_reset_data,
    343 	},
    344 	{
    345 		.compatible = "socionext,uniphier-pro5-peri-reset",
    346 		.data = (ulong)uniphier_pro4_peri_reset_data,
    347 	},
    348 	{
    349 		.compatible = "socionext,uniphier-pxs2-peri-reset",
    350 		.data = (ulong)uniphier_pro4_peri_reset_data,
    351 	},
    352 	{
    353 		.compatible = "socionext,uniphier-ld11-peri-reset",
    354 		.data = (ulong)uniphier_pro4_peri_reset_data,
    355 	},
    356 	{
    357 		.compatible = "socionext,uniphier-ld20-peri-reset",
    358 		.data = (ulong)uniphier_pro4_peri_reset_data,
    359 	},
    360 	{
    361 		.compatible = "socionext,uniphier-pxs3-peri-reset",
    362 		.data = (ulong)uniphier_pro4_peri_reset_data,
    363 	},
    364 	{ /* sentinel */ }
    365 };
    366 
    367 U_BOOT_DRIVER(uniphier_reset) = {
    368 	.name = "uniphier-reset",
    369 	.id = UCLASS_RESET,
    370 	.of_match = uniphier_reset_match,
    371 	.probe = uniphier_reset_probe,
    372 	.priv_auto_alloc_size = sizeof(struct uniphier_reset_priv),
    373 	.ops = &uniphier_reset_ops,
    374 };
    375