3 * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de
5 * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is
7 * Copyright 2010 eXMeritus, A Boeing Company
9 * SPDX-License-Identifier: GPL-2.0+
17 DECLARE_GLOBAL_DATA_PTR
;
28 struct mpc85xx_gpio_data
{
29 /* The bank's register base in memory */
30 struct ccsr_gpio __iomem
*base
;
31 /* The address of the registers; used to identify the bank */
33 /* The GPIO count of the bank */
35 /* The GPDAT register cannot be used to determine the value of output
36 * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
41 inline u32
gpio_mask(unsigned gpio
) {
42 return (1U << (31 - (gpio
)));
45 static inline u32
mpc85xx_gpio_get_val(struct ccsr_gpio
*base
, u32 mask
)
47 return in_be32(&base
->gpdat
) & mask
;
50 static inline u32
mpc85xx_gpio_get_dir(struct ccsr_gpio
*base
, u32 mask
)
52 return in_be32(&base
->gpdir
) & mask
;
55 static inline void mpc85xx_gpio_set_in(struct ccsr_gpio
*base
, u32 gpios
)
57 clrbits_be32(&base
->gpdat
, gpios
);
58 /* GPDIR register 0 -> input */
59 clrbits_be32(&base
->gpdir
, gpios
);
62 static inline void mpc85xx_gpio_set_low(struct ccsr_gpio
*base
, u32 gpios
)
64 clrbits_be32(&base
->gpdat
, gpios
);
65 /* GPDIR register 1 -> output */
66 setbits_be32(&base
->gpdir
, gpios
);
69 static inline void mpc85xx_gpio_set_high(struct ccsr_gpio
*base
, u32 gpios
)
71 setbits_be32(&base
->gpdat
, gpios
);
72 /* GPDIR register 1 -> output */
73 setbits_be32(&base
->gpdir
, gpios
);
76 static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio
*base
, u32 mask
)
78 return in_be32(&base
->gpodr
) & mask
;
81 static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio
*base
, u32
84 /* GPODR register 1 -> open drain on */
85 setbits_be32(&base
->gpodr
, gpios
);
88 static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio
*base
,
91 /* GPODR register 0 -> open drain off (actively driven) */
92 clrbits_be32(&base
->gpodr
, gpios
);
95 static int mpc85xx_gpio_direction_input(struct udevice
*dev
, unsigned gpio
)
97 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
99 mpc85xx_gpio_set_in(data
->base
, gpio_mask(gpio
));
103 static int mpc85xx_gpio_set_value(struct udevice
*dev
, unsigned gpio
,
106 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
109 data
->dat_shadow
|= gpio_mask(gpio
);
110 mpc85xx_gpio_set_high(data
->base
, gpio_mask(gpio
));
112 data
->dat_shadow
&= ~gpio_mask(gpio
);
113 mpc85xx_gpio_set_low(data
->base
, gpio_mask(gpio
));
118 static int mpc85xx_gpio_direction_output(struct udevice
*dev
, unsigned gpio
,
121 return mpc85xx_gpio_set_value(dev
, gpio
, value
);
124 static int mpc85xx_gpio_get_value(struct udevice
*dev
, unsigned gpio
)
126 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
128 if (!!mpc85xx_gpio_get_dir(data
->base
, gpio_mask(gpio
))) {
129 /* Output -> use shadowed value */
130 return !!(data
->dat_shadow
& gpio_mask(gpio
));
132 /* Input -> read value from GPDAT register */
133 return !!mpc85xx_gpio_get_val(data
->base
, gpio_mask(gpio
));
137 static int mpc85xx_gpio_get_open_drain(struct udevice
*dev
, unsigned gpio
)
139 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
141 return !!mpc85xx_gpio_open_drain_val(data
->base
, gpio_mask(gpio
));
144 static int mpc85xx_gpio_set_open_drain(struct udevice
*dev
, unsigned gpio
,
147 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
150 mpc85xx_gpio_open_drain_on(data
->base
, gpio_mask(gpio
));
152 mpc85xx_gpio_open_drain_off(data
->base
, gpio_mask(gpio
));
157 static int mpc85xx_gpio_get_function(struct udevice
*dev
, unsigned gpio
)
159 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
162 dir
= !!mpc85xx_gpio_get_dir(data
->base
, gpio_mask(gpio
));
163 return dir
? GPIOF_OUTPUT
: GPIOF_INPUT
;
166 #if CONFIG_IS_ENABLED(OF_CONTROL)
167 static int mpc85xx_gpio_ofdata_to_platdata(struct udevice
*dev
) {
168 struct mpc85xx_gpio_plat
*plat
= dev_get_platdata(dev
);
172 addr
= fdtdec_get_addr_size_auto_noparent(gd
->fdt_blob
, dev
->of_offset
,
173 "reg", 0, &size
, false);
177 plat
->ngpios
= fdtdec_get_int(gd
->fdt_blob
, dev
->of_offset
,
184 static int mpc85xx_gpio_platdata_to_priv(struct udevice
*dev
)
186 struct mpc85xx_gpio_data
*priv
= dev_get_priv(dev
);
187 struct mpc85xx_gpio_plat
*plat
= dev_get_platdata(dev
);
188 unsigned long size
= plat
->size
;
193 priv
->addr
= plat
->addr
;
194 priv
->base
= map_sysmem(CONFIG_SYS_IMMR
+ plat
->addr
, size
);
199 priv
->gpio_count
= plat
->ngpios
;
200 priv
->dat_shadow
= 0;
205 static int mpc85xx_gpio_probe(struct udevice
*dev
)
207 struct gpio_dev_priv
*uc_priv
= dev_get_uclass_priv(dev
);
208 struct mpc85xx_gpio_data
*data
= dev_get_priv(dev
);
211 mpc85xx_gpio_platdata_to_priv(dev
);
213 snprintf(name
, sizeof(name
), "MPC@%lx_", data
->addr
);
219 uc_priv
->bank_name
= str
;
220 uc_priv
->gpio_count
= data
->gpio_count
;
225 static const struct dm_gpio_ops gpio_mpc85xx_ops
= {
226 .direction_input
= mpc85xx_gpio_direction_input
,
227 .direction_output
= mpc85xx_gpio_direction_output
,
228 .get_value
= mpc85xx_gpio_get_value
,
229 .set_value
= mpc85xx_gpio_set_value
,
230 .get_open_drain
= mpc85xx_gpio_get_open_drain
,
231 .set_open_drain
= mpc85xx_gpio_set_open_drain
,
232 .get_function
= mpc85xx_gpio_get_function
,
235 static const struct udevice_id mpc85xx_gpio_ids
[] = {
236 { .compatible
= "fsl,pq3-gpio" },
240 U_BOOT_DRIVER(gpio_mpc85xx
) = {
241 .name
= "gpio_mpc85xx",
243 .ops
= &gpio_mpc85xx_ops
,
244 #if CONFIG_IS_ENABLED(OF_CONTROL)
245 .ofdata_to_platdata
= mpc85xx_gpio_ofdata_to_platdata
,
246 .platdata_auto_alloc_size
= sizeof(struct mpc85xx_gpio_plat
),
247 .of_match
= mpc85xx_gpio_ids
,
249 .probe
= mpc85xx_gpio_probe
,
250 .priv_auto_alloc_size
= sizeof(struct mpc85xx_gpio_data
),