Presentation is loading. Please wait.

Presentation is loading. Please wait.

GPIO Driver and Driver Binding

Similar presentations


Presentation on theme: "GPIO Driver and Driver Binding"— Presentation transcript:

1 GPIO Driver and Driver Binding
Computer Science & Engineering Department Arizona State University Tempe, AZ 85287 Dr. Yann-Hang Lee (480)

2 Linux GPIO Driver A GPIO (General Purpose Input/Output) pin can be configured, set up its direction, and value if it is an output pin A SoC chip may have several GPIO components Multiple “gpio chips” A global number in the integrated GPIO namespace, i.e., 0, 1, 2,…,n sysfs interface to user space GPIO framework (gpiolib.c) IO expanders Quark GIP controller Quark legacy GPIO GPIO_SUS[5:0] GPIO[9:0] GPIO[….] chip drivers

3 Software Components for Galileo Gen2 GPIO
/linux/driver/gpio/gpiolib.c the core program for gpio subsystem (framework) /linux/driver/mfd/intel_qrk_gip_core.c the dontroller for gip device on PCI bus /linux/driver/mfd/intel_qrk_gip_gpio.c gpio chip controller for gip_gpio /linux/driver/gpio/gpio-pca953x.c gpio chip controller for I2c expander pca9535 /linux/driver/i2c/busses/i2c-designware-core.c i2c bus controller for designware i2c controller /linux/driver/mfd/intel-qrk-gip_i2c.c a warpper to connect to i2c_designware_core.c /linux/driver/gpio/gpio-sch.c gpio chip controller for gpio port in Poulsbo SCH (system control hub) /linux/driver/platform/x86/quark/intel_qrk_board_data.c /linux/driver/platform/x86/quark/intel_qrk_plat_galileo_gen2.c

4 GPIO Chip Driver(1) A driver for each type of GPIO controller to provide methods to establish GPIO direction and to access GPIO values method to return the IRQ number associated to a given GPIO flag saying whether calls to its methods may sleep optional base number In intel_qrk_gip_gpio.c /* The base GPIO number under GPIOLIB framework */ #define INTEL_QRK_GIP_GPIO_BASE 8 /* The default number of South-Cluster GPIO on Quark. */ #define INTEL_QRK_GIP_NGPIO 8 In /include/asm-generic/gpio.h, “gpio_chip” is defined, including base: identifies the first GPIO number handled by this chip. ngpio: the number of GPIOs handled by this controller; the last GPIO handled is (base + ngpio - 1).

5 GPIO Chip Driver(2) gpio_chip includes function pointers to operate a gpio chip int (*get)(struct gpio_chip *chip, unsigned offset); void (*set)(struct gpio_chip *chip, unsigned offset, int value); int (*direction_input)(struct gpio_chip *chip, unsigned offset); ……. So, we can invoke operations at each pin of a gpio chip When a gpio chip driver is installed register itself to the bus it attached (e.g. PCI or i2c) The callback “probe” function is invoked to initialize struct gpio_chip, then to add gpio_chip /driver/mfd/intel_qrk_gip_gpio.c for gip_gpio /driver/gpio/gpio_pca953x.c for pca9535 chips

6 Binding of GPIOs to Pins
Example: gpio 26 is bit 10 of the 1st PCAL9535 chip Each GPIO chip is represented by “struct gpio_chip” standard methods such as get, set, etc. “int base;” and “u16 ngpio;” When a gpio chip is added, use “base” and “ngpio” to determine “pin range” of the chip In intel_qrk_plt_galileo_gen2.c, define gpio_base When pca953x_setup_gpio() is invoked, ngpio is set, When pca953x_gpio_get_value() is called, an input argument: gpio=26 use container_of to find the chip (there are 3 PCAL9535) invoke pca953x_read_reg(chip, offset, &reg_val) to read input reg check the bit and return 1 or 0

7 IO Expenders in Galileo Gen 1 & 2
Gen 1 – CY8C9540A Gen 2 – 3 PCAL9535 Both connected to quark processor via I2C bus How does the Linux know board configuration Read BIOS DMI data to identify the board Then, register the board (platform_device_register() in linux/drivers/platform/x86/quark/intel_qrk_board_data.c) Once the board is registered, find the platform_driver for "GalileoGen2“, i.e., intel_qrk_plat_galileo_gen2.c In the platform (board) driver, 3 PCA9535 chips are defined and then probed. strlcpy(probed_i2c_pcal9555a_exp0.type, "pcal9555a", I2C_NAME_SIZE); client = i2c_new_probed_device(i2c_adap, &probed_i2c_pcal9555a_exp0, pcal9555a_exp0_i2c_addr, i2c_probe);

8 Binding of GPIO Adapter and Driver (1)
Case 1: pca9535 instantiate the devices --- add 3 pca9535 devices as i2c clients in intel_qrk_plat_galileo_gen2.c (call to i2c_new_device()) initiate pca953x driver – static int __init pca953x_init(void) { return i2c_add_driver(&pca953x_driver); } then invoke i2c_register_driver and eventually pca953x_probe () if found matching devices In the probe function pca953x_setup_gpio device_pca953x_init gpiochip_add driver_register bus_add_driver driver_attach __driver_attach for each device on bus driver_probe_device if matches really_probe dev->bus->probe (i.e. i2c_device_probe) pca953x_probe

9 Binding of GPIO Adapter and Driver (2)
Case 2: gip_gpio instantiate the devices --- pci device initialization initiate intel_qrk_gip_core driver – static int intel_qrk_gip_init(void) { return pci_register_driver(&intel_qrk_gip_driver); } then invoke pci_register_driver and eventually intel_qrk_gip_probe () and then pci_enable_device (for gip) and intel_qrk_gpio_probe In the probe function set up a gpio_chip struct gpiochip_add

10 GPIO Driver Operation in gpio core
GPIO chip driver request to add “gpio_chip” to the platform gc->base = pdata->gpio_base; gc->ngpio = NGPIO; ret = gpiochip_add(&dev->gpio_chip); gpiolib.c exports methods to work on GPIO pins from GPIO # to find chip and to invoke the corresponding methods provided by the chip gpio_request_one(LED1, GPIOF_OUT_INIT_LOW, "led1"); gpio_desc desc1 = gpio_to_desc(LED1); gpio_set_value(desc1, data); sysfs gpio interfaces, such as gpiod_export, gpio_unexport, gpiod_set_value, gpio_direction_input

11 GPIO Interrupts (1) Interrupts from gip_gpio
One interrupt source from gip controller GIP ISR is requested in intel_qrk_gip_probe() request_irq(pdev->irq, intel_qrk_gip_handler, IRQF_SHARED, "intel_qrk_gip", gip_drvdata); The handler calls i2c_dw_isr() and intel_qrk_gpio_isr() In intel_qrk_gpio_isr(), Check any pending interrupts (triggered) pin  gpio  irq  desc  desc->handle_irq(desc); irq_desc to keep track of interrupt request source and manage IRQ flow. A list of irq actions and an action may be called when the irq occurs gpio_chip: include irq_chip as the driver for interrupt controller (to manage hardware) To receive a gpio interrupt, an isr (action) must be registered for the irq with proper triggering flag.

12 GPIO Interrupts (2) In gpio sysfs interface, setting an edge type enables interrupt gpio_edge_store()  gpio_setup_irq()  request_any_context_irq(irq, gpio_sysfs_irq, irq_flags, "gpiolib", value_sd);  request_threaded_irq(irq, NULL, handler, flags, name, dev_id); (or request_irq(…))  an action is allocated  __setup_irq(irq, desc, action); The handler static irqreturn_t gpio_sysfs_irq(int irq, void *priv)  to wake up threads in polling list (of sysfs dir) A similar approach irq_no = gpio_to_irq(GPIO_X); // get the irq number from Linux gpio number request_irq(irq_no, isr_handler, TRIGGER_FLAG, “name", NULL); Use irq_set_irq_type() to reset flags

13 Linux Kernel Thread A way to implement background tasks inside the kernel static struct task_struct *tsk; static int thread_function(void *data) { int time_count = 0; do { printk(KERN_INFO "thread_function: %d times", ++time_count); msleep(1000); }while(!kthread_should_stop() && time_count<=30); return time_count; } static int hello_init(void) { tsk = kthread_run(thread_function, NULL, "mythread%d", 1); if (IS_ERR(tsk)) { …. } kthread_run()  kthread_create() + wake_up_process()  create a kthread_create_info wake_up kthreadd_task  kthreadd_task calls create_kthread()  kernel_thread()  do_fork ()

14 Platform Drivers platform_driver_register(&my_pdevice_of_driver );
The driver’s probe function invoked when a platform device is registered and it's device name matches the name specified on the device driver. Initializes and registers the device(s) static const struct platform_device_id my_pdevice_id_table[] = { { "basic-mmio-gpio", }, { "basic-mmio-gpio-be", }, {}, }; MODULE_DEVICE_TABLE(platform, my_pdevice_id_table); static struct platform_driver my_pdevice_driver = { .driver = { .name = "my_pdevice”, .owner = THIS_MODULE, .of_match_table = of_match_ptr(my_pdevice_of_match), }, ,id_table = my_pdevice_id_table, .probe = my_pdevice_probe, .remove = my_pdevice_remove, }; module_platform_driver(my_pdevice_of_driver);

15 Platform Devices platform_device Once a platform device is declared,
name, used in driver binding, a list of resources Once a platform device is declared, init device structure after attached to platform_bus (a virtual bus) device_add(&pdev->dev)  bus_probe_device(dev)  device_attach(dev)  bus_for_each_drv(dev->bus, NULL, dev, __device_attach)  driver_match_device(drv, dev)  drv->bus->match(dev, drv)  given “platform_bus_type”,  platform_match(dev, drv)  driver_probe_device(drv, dev) struct platform_device { const char *name; u32 id; struct device dev; u32 num_resources; struct resource *resource; }; int platform_device_register(struct platform_device *pdev) { device_initialize(&pdev->dev); return platform_device_add(pdev); }

16 Platform_match if (pdev->driver_override)
return !strcmp(pdev->driver_override, drv->name); if (of_driver_match_device(dev, drv)) /* an OF style match first */ return 1; if (acpi_driver_match_device(dev, drv)) /* ACPI style match */ if (pdrv->id_table) /* match against the id table */ return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0); static const struct i2c_device_id pca953x_id[] = { { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, { "pca9555", 16 | PCA953X_TYPE | PCA_INT, }, { "pcal9555a", 16 | PCAL953X_TYPE | PCA_INT, }, … }

17 I2C Devices and Drivers of Galileo Board

18 Platform Devices and Drivers of Galileo Board


Download ppt "GPIO Driver and Driver Binding"

Similar presentations


Ads by Google