PCI子系統(三)- PCI裝置驅動
阿新 • • 發佈:2019-01-11
這裡拿linux/drivers/leds/leds-ss4200.c來做模板參考學習
註冊struct pci_driver
static struct pci_driver nas_gpio_pci_driver = { .name = KBUILD_MODNAME, .id_table = ich7_lpc_pci_id, .probe = ich7_lpc_probe, .remove = ich7_lpc_remove, }; static int __init nas_gpio_init(void) { ret = pci_register_driver(&nas_gpio_pci_driver); } static void __exit nas_gpio_exit(void) { pci_unregister_driver(&nas_gpio_pci_driver); } module_init(nas_gpio_init); module_exit(nas_gpio_exit);
probe
使能PCI裝置,讀取PCI裝置對應在CPU總線上的暫存器地址
/* ICH7 LPC/GPIO PCI Config register offsets */ #define PMBASE 0x040 #define GPIO_BASE 0x048 #define GPIO_CTRL 0x04c #define GPIO_EN 0x010 /* The ICH7 GPIO register block is 64 bytes in size. */ #define ICH7_GPIO_SIZE 64 static int ich7_lpc_probe(struct pci_dev *dev, const struct pci_device_id *id) { status = pci_enable_device(dev); status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base); status = pci_read_config_dword(dev, GPIO_CTRL, &gc); status = pci_read_config_dword(dev, GPIO_BASE, &nas_gpio_io_base); gp_gpio_resource = request_region(nas_gpio_io_base, ICH7_GPIO_SIZE, KBUILD_MODNAME); }
除了可以用pci_read_config_word讀取pci裝置的訪問地址之外,一般是通過pci_resource_start(pci_dev, 0),然後再通過request_region申請訪問這塊地址。
操作PCI裝置
通過從PCI裝置配置資訊中讀取的nas_gpio_io_base暫存器地址操作led
static void __nasgpio_led_set_attr(struct led_classdev *led_cdev, u32 port, u32 value) { struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev); u32 gpio_out; gpio_out = inl(nas_gpio_io_base + port); if (value) gpio_out |= (1<<led->gpio_bit); else gpio_out &= ~(1<<led->gpio_bit); outl(gpio_out, nas_gpio_io_base + port); }