2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
4 * SPDX-License-Identifier: GPL-2.0+
10 #include <linux/err.h>
11 #include <dm/device.h>
12 #include <dm/pinctrl.h>
14 #include "pinctrl-uniphier.h"
16 DECLARE_GLOBAL_DATA_PTR
;
18 static int uniphier_pinctrl_get_groups_count(struct udevice
*dev
)
20 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
22 return priv
->socdata
->groups_count
;
25 static const char *uniphier_pinctrl_get_group_name(struct udevice
*dev
,
28 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
30 return priv
->socdata
->groups
[selector
].name
;
33 static int uniphier_pinmux_get_functions_count(struct udevice
*dev
)
35 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
37 return priv
->socdata
->functions_count
;
40 static const char *uniphier_pinmux_get_function_name(struct udevice
*dev
,
43 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
45 return priv
->socdata
->functions
[selector
];
48 static void uniphier_pinconf_input_enable(struct udevice
*dev
, unsigned pin
)
50 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
51 int pins_count
= priv
->socdata
->pins_count
;
52 const struct uniphier_pinctrl_pin
*pins
= priv
->socdata
->pins
;
55 for (i
= 0; i
< pins_count
; i
++) {
56 if (pins
[i
].number
== pin
) {
60 iectrl
= uniphier_pin_get_iectrl(pins
[i
].data
);
61 tmp
= readl(priv
->base
+ UNIPHIER_PINCTRL_IECTRL
);
63 writel(tmp
, priv
->base
+ UNIPHIER_PINCTRL_IECTRL
);
68 static void uniphier_pinmux_set_one(struct udevice
*dev
, unsigned pin
,
71 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
72 unsigned mux_bits
= priv
->socdata
->mux_bits
;
73 unsigned reg_stride
= priv
->socdata
->reg_stride
;
74 unsigned reg
, reg_end
, shift
, mask
;
77 /* some pins need input-enabling */
78 uniphier_pinconf_input_enable(dev
, pin
);
80 reg
= UNIPHIER_PINCTRL_PINMUX_BASE
+ pin
* mux_bits
/ 32 * reg_stride
;
81 reg_end
= reg
+ reg_stride
;
82 shift
= pin
* mux_bits
% 32;
83 mask
= (1U << mux_bits
) - 1;
86 * If reg_stride is greater than 4, the MSB of each pinsel shall be
87 * stored in the offset+4.
89 for (; reg
< reg_end
; reg
+= 4) {
90 tmp
= readl(priv
->base
+ reg
);
91 tmp
&= ~(mask
<< shift
);
92 tmp
|= (mask
& muxval
) << shift
;
93 writel(tmp
, priv
->base
+ reg
);
98 if (priv
->socdata
->load_pinctrl
)
99 writel(1, priv
->base
+ UNIPHIER_PINCTRL_LOAD_PINMUX
);
102 static int uniphier_pinmux_group_set(struct udevice
*dev
,
103 unsigned group_selector
,
104 unsigned func_selector
)
106 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
107 const struct uniphier_pinctrl_group
*grp
=
108 &priv
->socdata
->groups
[group_selector
];
111 for (i
= 0; i
< grp
->num_pins
; i
++)
112 uniphier_pinmux_set_one(dev
, grp
->pins
[i
], grp
->muxvals
[i
]);
117 const struct pinctrl_ops uniphier_pinctrl_ops
= {
118 .get_groups_count
= uniphier_pinctrl_get_groups_count
,
119 .get_group_name
= uniphier_pinctrl_get_group_name
,
120 .get_functions_count
= uniphier_pinmux_get_functions_count
,
121 .get_function_name
= uniphier_pinmux_get_function_name
,
122 .pinmux_group_set
= uniphier_pinmux_group_set
,
123 .set_state
= pinctrl_generic_set_state
,
126 int uniphier_pinctrl_probe(struct udevice
*dev
,
127 struct uniphier_pinctrl_socdata
*socdata
)
129 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
133 addr
= fdtdec_get_addr_size(gd
->fdt_blob
, dev
->of_offset
, "reg",
135 if (addr
== FDT_ADDR_T_NONE
)
138 priv
->base
= map_sysmem(addr
, size
);
142 priv
->socdata
= socdata
;
147 int uniphier_pinctrl_remove(struct udevice
*dev
)
149 struct uniphier_pinctrl_priv
*priv
= dev_get_priv(dev
);
151 unmap_sysmem(priv
->base
);