xref: /rk3399_rockchip-uboot/drivers/gpio/altera_pio.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
103d67e12SJoachim Foerster /*
288d5ecf4SThomas Chou  * Copyright (C) 2015  Thomas Chou <thomas@wytron.com.tw>
303d67e12SJoachim Foerster  * Copyright (C) 2011  Missing Link Electronics
403d67e12SJoachim Foerster  *                     Joachim Foerster <joachim@missinglinkelectronics.com>
503d67e12SJoachim Foerster  *
61a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
703d67e12SJoachim Foerster  */
803d67e12SJoachim Foerster #include <common.h>
988d5ecf4SThomas Chou #include <dm.h>
1088d5ecf4SThomas Chou #include <errno.h>
1188d5ecf4SThomas Chou #include <malloc.h>
1288d5ecf4SThomas Chou #include <fdtdec.h>
1303d67e12SJoachim Foerster #include <asm/io.h>
1403d67e12SJoachim Foerster #include <asm/gpio.h>
1503d67e12SJoachim Foerster 
1688d5ecf4SThomas Chou DECLARE_GLOBAL_DATA_PTR;
1703d67e12SJoachim Foerster 
1888d5ecf4SThomas Chou struct altera_pio_regs {
1988d5ecf4SThomas Chou 	u32	data;			/* Data register */
2088d5ecf4SThomas Chou 	u32	direction;		/* Direction register */
2188d5ecf4SThomas Chou };
2203d67e12SJoachim Foerster 
2388d5ecf4SThomas Chou struct altera_pio_platdata {
2488d5ecf4SThomas Chou 	struct altera_pio_regs *regs;
2588d5ecf4SThomas Chou 	int gpio_count;
2688d5ecf4SThomas Chou 	const char *bank_name;
2788d5ecf4SThomas Chou };
2803d67e12SJoachim Foerster 
altera_pio_direction_input(struct udevice * dev,unsigned pin)2988d5ecf4SThomas Chou static int altera_pio_direction_input(struct udevice *dev, unsigned pin)
3003d67e12SJoachim Foerster {
3188d5ecf4SThomas Chou 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
3288d5ecf4SThomas Chou 	struct altera_pio_regs *const regs = plat->regs;
3303d67e12SJoachim Foerster 
3488d5ecf4SThomas Chou 	clrbits_le32(&regs->direction, 1 << pin);
3503d67e12SJoachim Foerster 
3603d67e12SJoachim Foerster 	return 0;
3703d67e12SJoachim Foerster }
3803d67e12SJoachim Foerster 
altera_pio_direction_output(struct udevice * dev,unsigned pin,int val)3988d5ecf4SThomas Chou static int altera_pio_direction_output(struct udevice *dev, unsigned pin,
4088d5ecf4SThomas Chou 				     int val)
4103d67e12SJoachim Foerster {
4288d5ecf4SThomas Chou 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
4388d5ecf4SThomas Chou 	struct altera_pio_regs *const regs = plat->regs;
4403d67e12SJoachim Foerster 
4588d5ecf4SThomas Chou 	if (val)
4688d5ecf4SThomas Chou 		setbits_le32(&regs->data, 1 << pin);
4703d67e12SJoachim Foerster 	else
4888d5ecf4SThomas Chou 		clrbits_le32(&regs->data, 1 << pin);
4988d5ecf4SThomas Chou 	/* change the data first, then the direction. to avoid glitch */
5088d5ecf4SThomas Chou 	setbits_le32(&regs->direction, 1 << pin);
5188d5ecf4SThomas Chou 
5203d67e12SJoachim Foerster 	return 0;
5303d67e12SJoachim Foerster }
5403d67e12SJoachim Foerster 
altera_pio_get_value(struct udevice * dev,unsigned pin)5588d5ecf4SThomas Chou static int altera_pio_get_value(struct udevice *dev, unsigned pin)
5603d67e12SJoachim Foerster {
5788d5ecf4SThomas Chou 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
5888d5ecf4SThomas Chou 	struct altera_pio_regs *const regs = plat->regs;
5903d67e12SJoachim Foerster 
6088d5ecf4SThomas Chou 	return readl(&regs->data) & (1 << pin);
6103d67e12SJoachim Foerster }
6203d67e12SJoachim Foerster 
6388d5ecf4SThomas Chou 
altera_pio_set_value(struct udevice * dev,unsigned pin,int val)6488d5ecf4SThomas Chou static int altera_pio_set_value(struct udevice *dev, unsigned pin, int val)
6503d67e12SJoachim Foerster {
6688d5ecf4SThomas Chou 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
6788d5ecf4SThomas Chou 	struct altera_pio_regs *const regs = plat->regs;
6803d67e12SJoachim Foerster 
6988d5ecf4SThomas Chou 	if (val)
7088d5ecf4SThomas Chou 		setbits_le32(&regs->data, 1 << pin);
7103d67e12SJoachim Foerster 	else
7288d5ecf4SThomas Chou 		clrbits_le32(&regs->data, 1 << pin);
7303d67e12SJoachim Foerster 
7403d67e12SJoachim Foerster 	return 0;
7503d67e12SJoachim Foerster }
7688d5ecf4SThomas Chou 
altera_pio_probe(struct udevice * dev)7788d5ecf4SThomas Chou static int altera_pio_probe(struct udevice *dev)
7888d5ecf4SThomas Chou {
7988d5ecf4SThomas Chou 	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
8088d5ecf4SThomas Chou 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
8188d5ecf4SThomas Chou 
8288d5ecf4SThomas Chou 	uc_priv->gpio_count = plat->gpio_count;
8388d5ecf4SThomas Chou 	uc_priv->bank_name = plat->bank_name;
8488d5ecf4SThomas Chou 
8588d5ecf4SThomas Chou 	return 0;
8688d5ecf4SThomas Chou }
8788d5ecf4SThomas Chou 
altera_pio_ofdata_to_platdata(struct udevice * dev)8888d5ecf4SThomas Chou static int altera_pio_ofdata_to_platdata(struct udevice *dev)
8988d5ecf4SThomas Chou {
9088d5ecf4SThomas Chou 	struct altera_pio_platdata *plat = dev_get_platdata(dev);
9188d5ecf4SThomas Chou 
92*a821c4afSSimon Glass 	plat->regs = map_physmem(devfdt_get_addr(dev),
93079bfc5dSThomas Chou 				 sizeof(struct altera_pio_regs),
94079bfc5dSThomas Chou 				 MAP_NOCACHE);
95e160f7d4SSimon Glass 	plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
9688d5ecf4SThomas Chou 		"altr,gpio-bank-width", 32);
97e160f7d4SSimon Glass 	plat->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
9888d5ecf4SThomas Chou 		"gpio-bank-name", NULL);
9988d5ecf4SThomas Chou 
10088d5ecf4SThomas Chou 	return 0;
10188d5ecf4SThomas Chou }
10288d5ecf4SThomas Chou 
10388d5ecf4SThomas Chou static const struct dm_gpio_ops altera_pio_ops = {
10488d5ecf4SThomas Chou 	.direction_input	= altera_pio_direction_input,
10588d5ecf4SThomas Chou 	.direction_output	= altera_pio_direction_output,
10688d5ecf4SThomas Chou 	.get_value		= altera_pio_get_value,
10788d5ecf4SThomas Chou 	.set_value		= altera_pio_set_value,
10888d5ecf4SThomas Chou };
10988d5ecf4SThomas Chou 
11088d5ecf4SThomas Chou static const struct udevice_id altera_pio_ids[] = {
11188d5ecf4SThomas Chou 	{ .compatible = "altr,pio-1.0" },
11288d5ecf4SThomas Chou 	{ }
11388d5ecf4SThomas Chou };
11488d5ecf4SThomas Chou 
11588d5ecf4SThomas Chou U_BOOT_DRIVER(altera_pio) = {
11688d5ecf4SThomas Chou 	.name		= "altera_pio",
11788d5ecf4SThomas Chou 	.id		= UCLASS_GPIO,
11888d5ecf4SThomas Chou 	.of_match	= altera_pio_ids,
11988d5ecf4SThomas Chou 	.ops		= &altera_pio_ops,
12088d5ecf4SThomas Chou 	.ofdata_to_platdata = altera_pio_ofdata_to_platdata,
12188d5ecf4SThomas Chou 	.platdata_auto_alloc_size = sizeof(struct altera_pio_platdata),
12288d5ecf4SThomas Chou 	.probe		= altera_pio_probe,
12388d5ecf4SThomas Chou };
124