Slide_tGPIO_driver_binding - Real
Download
Report
Transcript Slide_tGPIO_driver_binding - Real
GPIO Driver and Driver Binding
Computer Science & Engineering Department
Arizona State University
Tempe, AZ 85287
Dr. Yann-Hang Lee
[email protected]
(480) 727-7507
CSE 530 EOSI Fall 2016
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
GPIO[….]
CSE 530 EOSI Fall 2016
Quark GIP
controller
GPIO[9:0]
Quark legacy
GPIO
GPIO
chip
drivers
GPIO_SUS[5:0]
1
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
CSE 530 EOSI Fall 2016
2
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).
CSE 530 EOSI Fall 2016
3
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
CSE 530 EOSI Fall 2016
4
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, ®_val) to read input reg
check the bit and return 1 or 0
CSE 530 EOSI Fall 2016
5
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);
CSE 530 EOSI Fall 2016
6
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);
• driver_register
}
• bus_add_driver
then invoke i2c_register_driver and eventually
• driver_attach
pca953x_probe () if found matching devices
• __driver_attach for each
In the probe function
device on bus
pca953x_setup_gpio
• driver_probe_device if
matches
device_pca953x_init
• really_probe
gpiochip_add
• dev->bus->probe (i.e.
i2c_device_probe)
• pca953x_probe
CSE 530 EOSI Fall 2016
7
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
CSE 530 EOSI Fall 2016
8
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
CSE 530 EOSI Fall 2016
9
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.
CSE 530 EOSI Fall 2016
10
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
1. irq_no = gpio_to_irq(GPIO_X); // get the irq number from Linux gpio
number
2. request_irq(irq_no, isr_handler, TRIGGER_FLAG, “name", NULL);
3. Use irq_set_irq_type() to reset flags
CSE 530 EOSI Fall 2016
11
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 ()
CSE 530 EOSI Fall 2016
12
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);
CSE 530 EOSI Fall 2016
13
Platform Devices
platform_device
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)
struct platform_device {
const char
u32
struct device
u32
struct resource
};
*name;
id;
dev;
num_resources;
*resource;
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)
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
return platform_device_add(pdev);
}
CSE 530 EOSI Fall 2016
14
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 */
return 1;
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, },
…}
CSE 530 EOSI Fall 2016
15
I2C Devices and Drivers of Galileo Board
CSE 530 EOSI Fall 2016
set 4 -- 16
Platform Devices and Drivers of Galileo
Board
CSE 530 EOSI Fall 2016
set 4 -- 17