DeviceDriver (three): GPIO subsystem

 

One: GPIO subsystem

         When the PIN is reused as gpio by the pinctrl subsystem, the gpio subsystem is needed. The main purpose of the gpio subsystem is to facilitate the use of gpio. Add gpio-related information to the device tree, and then you can use gpio in the driver The API function provided by the subsystem is used to operate gpio. The Linux kernel shields the gpio setting process, which greatly facilitates the use of gpio

 

Two: GPIO device tree information

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog_1>;
	imx6ul-evk {
		pinctrl_hog_1: hoggrp-1 {
			fsl,pins = <
				MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */
			>;
                };
        };
};

&usdhc1 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc1>;
	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
	keep-power-in-suspend;
	enable-sdio-wakeup;
	vmmc-supply = <&reg_sd1_vmmc>;
	status = "okay";
};

(1) The usdhc1 node is used as the total node of the SD card device. This node needs to describe all the information of the SD card. The reset pin GPIO1_IO19 that should be located under the &usdhc1 node describes that the node pinctrl_hog_1 is referenced by the &iomuxc node "pinctrl-0 = <&pinctrl_hog_1>;" so the iomuxc driver in the linux kernel will also automatically initialize the pins under the pinctrl_hog_1 node with the same effect.

(2) "cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;" describes that the CD pin of the SD card uses gpio1_19, and "GPIO_ACTIVE_LOW" means low level is active.

gpio1: gpio@0209c000 {
	compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
	reg = <0x0209c000 0x4000>;
	interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
		     <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
	gpio-controller;
	#gpio-cells = <2>;
	interrupt-controller;
	#interrupt-cells = <2>;
};

The gpio1 node describes all the information of the gpio1 controller.

"Gpio-controller" indicates that the gpio1 node is a gpio controller.

"#Gpio-cells = <2>" means there are two cells, the first cell is the gpio number, for example, "&gpio1 3" means GPIO1_IO03; the second cell means gpio polarity, if it is 0, it means high power Level is valid, if it is 1, it means low level is valid.

Three: GPIO driver framework

Find the gpio-mxc.c file by the compatible attribute of the gpio1 node

static struct platform_device_id mxc_gpio_devtype[] = {
	{
		.name = "imx1-gpio",
		.driver_data = IMX1_GPIO,
	}, {
		.name = "imx21-gpio",
		.driver_data = IMX21_GPIO,
	}, {
		.name = "imx31-gpio",
		.driver_data = IMX31_GPIO,
	}, {
		.name = "imx35-gpio",
		.driver_data = IMX35_GPIO,
	}, {
		/* sentinel */
	}
};

static const struct of_device_id mxc_gpio_dt_ids[] = {
	{ .compatible = "fsl,imx1-gpio", .data = &mxc_gpio_devtype[IMX1_GPIO], },
	{ .compatible = "fsl,imx21-gpio", .data = &mxc_gpio_devtype[IMX21_GPIO], },
	{ .compatible = "fsl,imx31-gpio", .data = &mxc_gpio_devtype[IMX31_GPIO], },
	{ .compatible = "fsl,imx35-gpio", .data = &mxc_gpio_devtype[IMX35_GPIO], },
	{ /* sentinel */ }
};

Reverse the structure "mxc_gpio_dt_ids"

static struct platform_driver mxc_gpio_driver = {
	.driver		= {
		.name	= "gpio-mxc",
		.of_match_table = mxc_gpio_dt_ids,
	},
	.probe		= mxc_gpio_probe,
	.id_table	= mxc_gpio_devtype,
};

It can be seen that the gpio system is also hung on the platform platform. If the device matches the driver ".of_match_table", the entry function probe is called:

static int mxc_gpio_probe(struct platform_device *pdev)

(1) Create the device tree node pointer and define the port pointer of the mxc_gpio_port structure, in which the variable bgc is very important:

struct device_node *np = pdev->dev.of_node;
struct mxc_gpio_port *port;

struct mxc_gpio_port {
	struct list_head node;
	void __iomem *base;
	int irq;
	int irq_high;
	struct irq_domain *domain;
	struct bgpio_chip bgc;
	u32 both_edges;
};

(2) Get the register set of gpio

static struct mxc_gpio_hwdata imx35_gpio_hwdata = {
	.dr_reg		= 0x00,
	.gdir_reg	= 0x04,
	.psr_reg	= 0x08,
	.icr1_reg	= 0x0c,
	.icr2_reg	= 0x10,
	.imr_reg	= 0x14,
	.isr_reg	= 0x18,
	.edge_sel_reg	= 0x1c,
	.low_level	= 0x00,
	.high_level	= 0x01,
	.rise_edge	= 0x02,
	.fall_edge	= 0x03,
};

static void mxc_gpio_get_hw(struct platform_device *pdev)
{
	const struct of_device_id *of_id =
			of_match_device(mxc_gpio_dt_ids, &pdev->dev);
	enum mxc_gpio_hwtype hwtype;
... ...
	if (hwtype == IMX35_GPIO)
		mxc_gpio_hwdata = &imx35_gpio_hwdata;
	else if (hwtype == IMX31_GPIO)
		mxc_gpio_hwdata = &imx31_gpio_hwdata;
... ...
	mxc_gpio_hwtype = hwtype;
}

(3) Get the reg attribute value of the memory resource information in the device tree

iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);

struct resource *platform_get_resource(struct platform_device *dev,
				       unsigned int type, unsigned int num)
{
	int i;

	for (i = 0; i < dev->num_resources; i++) {
		struct resource *r = &dev->resource[i];

		if (type == resource_type(r) && num-- == 0)
			return r;
	}
	return NULL;
}

(4) Map the memory address to get the virtual address corresponding to the physical address in the Linux kernel

port->base = devm_ioremap_resource(&pdev->dev, iores);

(5) Get the interrupt number

port->irq_high = platform_get_irq(pdev, 1);
port->irq = platform_get_irq(pdev, 0);

(6) Close all IO interrupts of GPIO1 and clear the status register

/* disable the interrupt and clear the status */
writel(0, port->base + GPIO_IMR);
writel(~0, port->base + GPIO_ISR);

(7) Set the interrupt service function corresponding to GPIO.

/* setup one handler for each entry */
irq_set_chained_handler(port->irq, mx3_gpio_irq_handler);
irq_set_handler_data(port->irq, port);
if (port->irq_high > 0) {
    /* setup handler for GPIO 16 to 31 */
    irq_set_chained_handler(port->irq_high,
    mx3_gpio_irq_handler);
    irq_set_handler_data(port->irq_high, port);
}

(8) Initialize the member gc of the variable bgc

Variable bgc structure: struct bgpio_chip *bgc

struct bgpio_chip {
	struct gpio_chip gc;

	unsigned long (*read_reg)(void __iomem *reg);
	void (*write_reg)(void __iomem *reg, unsigned long data);

	void __iomem *reg_dat;
	void __iomem *reg_set;
	void __iomem *reg_clr;
	void __iomem *reg_dir;

	/* Number of bits (GPIOs): <register width> * 8. */
	int bits;

	/*
	 * Some GPIO controllers work with the big-endian bits notation,
	 * e.g. in a 8-bits register, GPIO7 is the least significant bit.
	 */
	unsigned long (*pin2mask)(struct bgpio_chip *bgc, unsigned int pin);

	/*
	 * Used to lock bgpio_chip->data. Also, this is needed to keep
	 * shadowed and real data registers writes together.
	 */
	spinlock_t lock;

	/* Shadowed data register to clear/set bits safely. */
	unsigned long data;

	/* Shadowed direction registers to clear/set direction safely. */
	unsigned long dir;
};

Variable gc structure: struct gpio_chip gc

struct gpio_chip {
	const char		*label;
	struct device		*dev;
	struct module		*owner;
	struct list_head        list;

	int			(*request)(struct gpio_chip *chip,
						unsigned offset);
	void			(*free)(struct gpio_chip *chip,
						unsigned offset);
	int			(*get_direction)(struct gpio_chip *chip,
						unsigned offset);
	int			(*direction_input)(struct gpio_chip *chip,
						unsigned offset);
	int			(*direction_output)(struct gpio_chip *chip,
						unsigned offset, int value);
	int			(*get)(struct gpio_chip *chip,
						unsigned offset);
	void			(*set)(struct gpio_chip *chip,
						unsigned offset, int value);
	void			(*set_multiple)(struct gpio_chip *chip,
						unsigned long *mask,
						unsigned long *bits);
	int			(*set_debounce)(struct gpio_chip *chip,
						unsigned offset,
						unsigned debounce);

	int			(*to_irq)(struct gpio_chip *chip,
						unsigned offset);

	void			(*dbg_show)(struct seq_file *s,
						struct gpio_chip *chip);
	int			base;
	u16			ngpio;
	struct gpio_desc	*desc;
	const char		*const *names;
	bool			can_sleep;
	bool			irq_not_threaded;
	bool			exported;

#ifdef CONFIG_GPIOLIB_IRQCHIP
	/*
	 * With CONFIG_GPIOLIB_IRQCHIP we get an irqchip inside the gpiolib
	 * to handle IRQs for most practical cases.
	 */
	struct irq_chip		*irqchip;
	struct irq_domain	*irqdomain;
	unsigned int		irq_base;
	irq_flow_handler_t	irq_handler;
	unsigned int		irq_default_type;
#endif

#if defined(CONFIG_OF_GPIO)
	/*
	 * If CONFIG_OF is enabled, then all GPIO controllers described in the
	 * device tree automatically may have an OF translation
	 */
	struct device_node *of_node;
	int of_gpio_n_cells;
	int (*of_xlate)(struct gpio_chip *gc,
			const struct of_phandle_args *gpiospec, u32 *flags);
#endif
#ifdef CONFIG_PINCTRL
	/*
	 * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
	 * describe the actual pin range which they serve in an SoC. This
	 * information would be used by pinctrl subsystem to configure
	 * corresponding pins for gpio usage.
	 */
	struct list_head pin_ranges;
#endif
};

Initialize various GPIO operation functions in bgc->gc, assign the GPIO register address to the parameter reg_dat of bgc, etc.:

err = bgpio_init(&port->bgc, &pdev->dev, 4,
		 port->base + GPIO_PSR,
		 port->base + GPIO_DR, NULL,
		 port->base + GPIO_GDIR, NULL, 0);

int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
	       unsigned long sz, void __iomem *dat, void __iomem *set,
	       void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
	       unsigned long flags)
{
	int ret;

	if (!is_power_of_2(sz))
		return -EINVAL;

	bgc->bits = sz * 8;
	if (bgc->bits > BITS_PER_LONG)
		return -EINVAL;

	spin_lock_init(&bgc->lock);
	bgc->gc.dev = dev;
	bgc->gc.label = dev_name(dev);
	bgc->gc.base = -1;
	bgc->gc.ngpio = bgc->bits;
	bgc->gc.request = bgpio_request;

	ret = bgpio_setup_io(bgc, dat, set, clr);
	if (ret)
		return ret;

	ret = bgpio_setup_accessors(dev, bgc, flags & BGPIOF_BIG_ENDIAN,
				    flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
	if (ret)
		return ret;

	ret = bgpio_setup_direction(bgc, dirout, dirin);
	if (ret)
		return ret;

	bgc->data = bgc->read_reg(bgc->reg_dat);
	if (bgc->gc.set == bgpio_set_set &&
			!(flags & BGPIOF_UNREADABLE_REG_SET))
		bgc->data = bgc->read_reg(bgc->reg_set);
	if (bgc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR))
		bgc->dir = bgc->read_reg(bgc->reg_dir);

	return ret;
}

(9) Register the variable port->bgc.gc of the gpio_chip structure with the Linux kernel so that the provided API function can be used

err = gpiochip_add(&port->bgc.gc);

Four: GPIO subsystem API function

1: The gpio_request function is used to apply for a GPIO pin, and the of_get_named_gpio function is used to obtain the specified GPIO attribute information from the device tree

int gpio_request(unsigned gpio, const char *label)
{
	struct gpio_desc *desc = gpio_to_desc(gpio);

	/* Compatibility: assume unavailable "valid" GPIOs will appear later */
	if (!desc && gpio_is_valid(gpio))
		return -EPROBE_DEFER;

	return gpiod_request(desc, label);
}

2: gpio_free function is used to release GPIO pins

void gpio_free(unsigned gpio)
{
	gpiod_free(gpio_to_desc(gpio));
}

3: The gpio_direction_input function is used to set GPIO as input

static inline int gpio_direction_input(unsigned gpio)
{
	return gpiod_direction_input(gpio_to_desc(gpio));
}

4: gpio_direction_output function is used to set GPIO as output

static inline int gpio_direction_output(unsigned gpio, int value)
{
	return gpiod_direction_output_raw(gpio_to_desc(gpio), value);
}

5: Set/get GPIO pin value

#define gpio_get_value  __gpio_get_value
#define gpio_set_value  __gpio_set_value

static inline int __gpio_get_value(unsigned gpio)
{
	return gpiod_get_raw_value(gpio_to_desc(gpio));
}

static inline void __gpio_set_value(unsigned gpio, int value)
{
	return gpiod_set_raw_value(gpio_to_desc(gpio), value);
}

Five: add gpio node template

1. Create a device node

test {
    /* 节点内容 */
}

2. Add the pinctrl node information from the previous section, refer to section 4: https://blog.csdn.net/qq_34968572/article/details/103275579

test {
    /* 节点内容 */
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_test>;
}

3. Add gpio attribute information

test {
    /* 节点内容 */
    ... ...
    gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
}

The three values ​​of the attribute "gpio" are expressed as follows:

"&Gpio1": The IO used by this pin belongs to the GPIO1 group.

"0": Represents the 0th IO of the GPIO1 group.

"GPIO_ACTIVE_LOW": means low level is active.

Comprehensive example:

/ {
    model = "Freescale i.MX6 ULL 14x14 EVK Board";
    compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
... ...
    beep {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "my-beep";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_beep>;
        beep-gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
        status = "okay";
    };
};


&iomuxc {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_hog_1>;
    imx6ul-evk {

        pinctrl_beep: beepgrp {
            fsl,pins = <
                MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01   0x10b0
            >;
        };
    };
};

If it is modified on the public device tree, you need to check whether the GPIO pin is used for other functions, and if so, you need to delete the corresponding setting.

Six: OF functions related to GPIO

1. of_gpio_named_count is used to obtain several GPIO information defined in an attribute of the device tree

static inline int of_gpio_named_count(struct device_node *np, const char* propname)
{
	return of_count_phandle_with_args(np, propname, "#gpio-cells");
}

2. of_gpio_count is used to obtain the GPIO information in the specific attribute "gpios"

static inline int of_gpio_count(struct device_node *np)
{
	return of_gpio_named_count(np, "gpios");
}

3. of_get_named_gpio is used to get the GPIO number

static inline int of_get_named_gpio(struct device_node *np,
                                   const char *propname, int index)
{
	return of_get_named_gpio_flags(np, propname, index, NULL);
}

 

Guess you like

Origin blog.csdn.net/qq_34968572/article/details/103295793