blob: 9b3b5aec07adce51e6220db6edb822f460fbc39c [file] [log] [blame]
Peng Fane84d11f2018-10-18 14:28:28 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 NXP
4 */
5
Marek Vasut4182de52025-01-24 15:50:58 +01006#include <dm.h>
7#include <errno.h>
8#include <linux/bitops.h>
9#include <asm/io.h>
10#include <firmware/imx/sci/sci.h>
11#include <misc.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060012#include <asm/global_data.h>
Peng Fane84d11f2018-10-18 14:28:28 +020013#include <dm/device.h>
14#include <dm/pinctrl.h>
15
16#include "pinctrl-imx.h"
17
18DECLARE_GLOBAL_DATA_PTR;
19
Marek Vasut4182de52025-01-24 15:50:58 +010020#define PADRING_IFMUX_EN_SHIFT 31
21#define PADRING_IFMUX_EN_MASK BIT(31)
22#define PADRING_GP_EN_SHIFT 30
23#define PADRING_GP_EN_MASK BIT(30)
24#define PADRING_IFMUX_SHIFT 27
25#define PADRING_IFMUX_MASK GENMASK(29, 27)
26
27static int imx_pinconf_scu_set(struct imx_pinctrl_soc_info *info, u32 pad,
28 u32 mux, u32 val)
29{
30 int ret;
31
32 /*
33 * Mux should be done in pmx set, but we do not have a good api
34 * to handle that in scfw, so config it in pad conf func
35 */
36
37 if (!sc_rm_is_pad_owned(-1, pad)) {
38 debug("Pad[%u] is not owned by curr partition\n", pad);
39 return -EPERM;
40 }
41
42 val |= PADRING_IFMUX_EN_MASK;
43 val |= PADRING_GP_EN_MASK;
44 val |= (mux << PADRING_IFMUX_SHIFT) & PADRING_IFMUX_MASK;
45
46 ret = sc_pad_set(-1, pad, val);
47 if (ret)
48 printf("%s %d\n", __func__, ret);
49
50 return 0;
51}
52
53int imx_pinctrl_set_state_scu(struct udevice *dev, struct udevice *config)
54{
55 struct imx_pinctrl_priv *priv = dev_get_priv(dev);
56 struct imx_pinctrl_soc_info *info = priv->info;
57 int pin_id, mux, config_val;
58 u32 *pin_data;
59 int i, j = 0;
60 int npins;
61 int ret;
62
63 ret = imx_pinctrl_set_state_common(dev, config, SHARE_IMX8_PIN_SIZE,
64 &pin_data, &npins);
65 if (ret)
66 return ret;
67
68 /*
69 * Refer to linux documentation for details:
70 * Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt
71 */
72 for (i = 0; i < npins; i++) {
73 pin_id = pin_data[j++];
74 mux = pin_data[j++];
75 config_val = pin_data[j++];
76
77 ret = imx_pinconf_scu_set(info, pin_id, mux, config_val);
78 if (ret && ret != -EPERM)
79 printf("Set pin %d, mux %d, val %d, error\n", pin_id,
80 mux, config_val);
81 }
82
83 return 0;
84}
Peng Fane84d11f2018-10-18 14:28:28 +020085static struct imx_pinctrl_soc_info imx8_pinctrl_soc_info = {
86 .flags = IMX8_USE_SCU,
87};
88
Peng Fane84d11f2018-10-18 14:28:28 +020089static const struct udevice_id imx8_pinctrl_match[] = {
90 { .compatible = "fsl,imx8qxp-iomuxc", .data = (ulong)&imx8_pinctrl_soc_info },
Peng Fanef867732019-03-05 02:32:13 +000091 { .compatible = "fsl,imx8qm-iomuxc", .data = (ulong)&imx8_pinctrl_soc_info },
Peng Fane84d11f2018-10-18 14:28:28 +020092 { /* sentinel */ }
93};
94
Marek Vasut5b213c32025-01-24 15:50:51 +010095static const struct pinctrl_ops imx8_pinctrl_ops = {
Marek Vasut964c52b2025-01-24 15:50:57 +010096 .set_state = imx_pinctrl_set_state_scu,
Marek Vasut4646bd92025-01-24 15:50:50 +010097};
98
Peng Fane84d11f2018-10-18 14:28:28 +020099U_BOOT_DRIVER(imx8_pinctrl) = {
100 .name = "imx8_pinctrl",
101 .id = UCLASS_PINCTRL,
102 .of_match = of_match_ptr(imx8_pinctrl_match),
Marek Vasutf19a47f2025-01-24 15:50:54 +0100103 .probe = imx_pinctrl_probe_common,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700104 .priv_auto = sizeof(struct imx_pinctrl_priv),
Marek Vasut5b213c32025-01-24 15:50:51 +0100105 .ops = &imx8_pinctrl_ops,
Peng Fane84d11f2018-10-18 14:28:28 +0200106 .flags = DM_FLAG_PRE_RELOC,
107};