2 * Copyright (c) 2015 Microchip Technology Inc
3 * Purna Chandra Mandal <purna.mandal@microchip.com>
5 * SPDX-License-Identifier: GPL-2.0+
14 #include <linux/compat.h>
15 #include <mach/pic32.h>
17 DECLARE_GLOBAL_DATA_PTR
;
19 /* Peripheral Pin Control */
20 struct pic32_reg_port
{
21 struct pic32_reg_atomic ansel
;
22 struct pic32_reg_atomic tris
;
23 struct pic32_reg_atomic port
;
24 struct pic32_reg_atomic lat
;
25 struct pic32_reg_atomic open_drain
;
26 struct pic32_reg_atomic cnpu
;
27 struct pic32_reg_atomic cnpd
;
28 struct pic32_reg_atomic cncon
;
32 MICROCHIP_GPIO_DIR_OUT
,
33 MICROCHIP_GPIO_DIR_IN
,
34 MICROCHIP_GPIOS_PER_BANK
= 16,
37 struct pic32_gpio_priv
{
38 struct pic32_reg_port
*regs
;
42 static int pic32_gpio_get_value(struct udevice
*dev
, unsigned offset
)
44 struct pic32_gpio_priv
*priv
= dev_get_priv(dev
);
46 return !!(readl(&priv
->regs
->port
.raw
) & BIT(offset
));
49 static int pic32_gpio_set_value(struct udevice
*dev
, unsigned offset
,
52 struct pic32_gpio_priv
*priv
= dev_get_priv(dev
);
53 int mask
= BIT(offset
);
56 writel(mask
, &priv
->regs
->port
.set
);
58 writel(mask
, &priv
->regs
->port
.clr
);
63 static int pic32_gpio_direction(struct udevice
*dev
, unsigned offset
)
65 struct pic32_gpio_priv
*priv
= dev_get_priv(dev
);
67 /* pin in analog mode ? */
68 if (readl(&priv
->regs
->ansel
.raw
) & BIT(offset
))
71 if (readl(&priv
->regs
->tris
.raw
) & BIT(offset
))
72 return MICROCHIP_GPIO_DIR_IN
;
74 return MICROCHIP_GPIO_DIR_OUT
;
77 static int pic32_gpio_direction_input(struct udevice
*dev
, unsigned offset
)
79 struct pic32_gpio_priv
*priv
= dev_get_priv(dev
);
80 int mask
= BIT(offset
);
82 writel(mask
, &priv
->regs
->ansel
.clr
);
83 writel(mask
, &priv
->regs
->tris
.set
);
88 static int pic32_gpio_direction_output(struct udevice
*dev
,
89 unsigned offset
, int value
)
91 struct pic32_gpio_priv
*priv
= dev_get_priv(dev
);
92 int mask
= BIT(offset
);
94 writel(mask
, &priv
->regs
->ansel
.clr
);
95 writel(mask
, &priv
->regs
->tris
.clr
);
97 pic32_gpio_set_value(dev
, offset
, value
);
101 static int pic32_gpio_get_function(struct udevice
*dev
, unsigned offset
)
103 int ret
= GPIOF_UNUSED
;
105 switch (pic32_gpio_direction(dev
, offset
)) {
106 case MICROCHIP_GPIO_DIR_OUT
:
109 case MICROCHIP_GPIO_DIR_IN
:
119 static const struct dm_gpio_ops gpio_pic32_ops
= {
120 .direction_input
= pic32_gpio_direction_input
,
121 .direction_output
= pic32_gpio_direction_output
,
122 .get_value
= pic32_gpio_get_value
,
123 .set_value
= pic32_gpio_set_value
,
124 .get_function
= pic32_gpio_get_function
,
127 static int pic32_gpio_probe(struct udevice
*dev
)
129 struct gpio_dev_priv
*uc_priv
= dev_get_uclass_priv(dev
);
130 struct pic32_gpio_priv
*priv
= dev_get_priv(dev
);
136 addr
= fdtdec_get_addr_size(gd
->fdt_blob
, dev_of_offset(dev
), "reg",
138 if (addr
== FDT_ADDR_T_NONE
)
141 priv
->regs
= ioremap(addr
, size
);
143 uc_priv
->gpio_count
= MICROCHIP_GPIOS_PER_BANK
;
144 /* extract bank name */
145 end
= strrchr(dev
->name
, '@');
146 bank
= trailing_strtoln(dev
->name
, end
);
147 priv
->name
[0] = 'A' + bank
;
148 uc_priv
->bank_name
= priv
->name
;
153 static const struct udevice_id pic32_gpio_ids
[] = {
154 { .compatible
= "microchip,pic32mzda-gpio" },
158 U_BOOT_DRIVER(gpio_pic32
) = {
159 .name
= "gpio_pic32",
161 .of_match
= pic32_gpio_ids
,
162 .ops
= &gpio_pic32_ops
,
163 .probe
= pic32_gpio_probe
,
164 .priv_auto_alloc_size
= sizeof(struct pic32_gpio_priv
),