Merge tag 'driver-core-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here's the "big" driver core update for 4.7-rc1.

  Mostly just debugfs changes, the long-known and messy races with
  removing debugfs files should be fixed thanks to the great work of
  Nicolai Stange.  We also have some isa updates in here (the x86
  maintainers told me to take it through this tree), a new warning when
  we run out of dynamic char major numbers, and a few other assorted
  changes, details in the shortlog.

  All have been in linux-next for some time with no reported issues"

* tag 'driver-core-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (32 commits)
  Revert "base: dd: don't remove driver_data in -EPROBE_DEFER case"
  gpio: ws16c48: Utilize the ISA bus driver
  gpio: 104-idio-16: Utilize the ISA bus driver
  gpio: 104-idi-48: Utilize the ISA bus driver
  gpio: 104-dio-48e: Utilize the ISA bus driver
  watchdog: ebc-c384_wdt: Utilize the ISA bus driver
  iio: stx104: Utilize the module_isa_driver and max_num_isa_dev macros
  iio: stx104: Add X86 dependency to STX104 Kconfig option
  Documentation: Add ISA bus driver documentation
  isa: Implement the max_num_isa_dev macro
  isa: Implement the module_isa_driver macro
  pnp: pnpbios: Add explicit X86_32 dependency to PNPBIOS
  isa: Decouple X86_32 dependency from the ISA Kconfig option
  driver-core: use 'dev' argument in dev_dbg_ratelimited stub
  base: dd: don't remove driver_data in -EPROBE_DEFER case
  kernfs: Move faulting copy_user operations outside of the mutex
  devcoredump: add scatterlist support
  debugfs: unproxify files created through debugfs_create_u32_array()
  debugfs: unproxify files created through debugfs_create_blob()
  debugfs: unproxify files created through debugfs_create_bool()
  ...
This commit is contained in:
Linus Torvalds
2016-05-20 21:26:15 -07:00
33 changed files with 1160 additions and 519 deletions

View File

@@ -530,30 +530,35 @@ menu "Port-mapped I/O GPIO drivers"
config GPIO_104_DIO_48E
tristate "ACCES 104-DIO-48E GPIO support"
depends on ISA
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES 104-DIO-48E family. The base port
address for the device may be configured via the dio_48e_base module
parameter. The interrupt line number for the device may be configured
via the dio_48e_irq module parameter.
Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
104-DIO-24E). The base port addresses for the devices may be
configured via the base module parameter. The interrupt line numbers
for the devices may be configured via the irq module parameter.
config GPIO_104_IDIO_16
tristate "ACCES 104-IDIO-16 GPIO support"
depends on ISA
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES 104-IDIO-16 family. The base port
address for the device may be set via the idio_16_base module
parameter. The interrupt line number for the device may be set via the
idio_16_irq module parameter.
Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, 104-IDO-8). The
base port addresses for the devices may be configured via the base
module parameter. The interrupt line numbers for the devices may be
configured via the irq module parameter.
config GPIO_104_IDI_48
tristate "ACCES 104-IDI-48 GPIO support"
depends on ISA
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the ACCES 104-IDI-48 family. The base port
address for the device may be configured via the idi_48_base module
parameter. The interrupt line number for the device may be configured
via the idi_48_irq module parameter.
Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for
the devices may be configured via the base module parameter. The
interrupt line numbers for the devices may be configured via the irq
module parameter.
config GPIO_F7188X
tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support"
@@ -622,12 +627,13 @@ config GPIO_TS5500
config GPIO_WS16C48
tristate "WinSystems WS16C48 GPIO support"
depends on ISA
select GPIOLIB_IRQCHIP
help
Enables GPIO support for the WinSystems WS16C48. The base port address
for the device may be configured via the ws16c48_base module
parameter. The interrupt line number for the device may be configured
via the ws16c48_irq module parameter.
Enables GPIO support for the WinSystems WS16C48. The base port
addresses for the devices may be configured via the base module
parameter. The interrupt line numbers for the devices may be
configured via the irq module parameter.
endmenu

View File

@@ -1,5 +1,5 @@
/*
* GPIO driver for the ACCES 104-DIO-48E
* GPIO driver for the ACCES 104-DIO-48E series
* Copyright (C) 2016 William Breathitt Gray
*
* This program is free software; you can redistribute it and/or modify
@@ -10,6 +10,9 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* This driver supports the following ACCES devices: 104-DIO-48E and
* 104-DIO-24E.
*/
#include <linux/bitops.h>
#include <linux/device.h>
@@ -19,18 +22,23 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irqdesc.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
static unsigned dio_48e_base;
module_param(dio_48e_base, uint, 0);
MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address");
static unsigned dio_48e_irq;
module_param(dio_48e_irq, uint, 0);
MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number");
#define DIO48E_EXTENT 16
#define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT)
static unsigned int base[MAX_NUM_DIO48E];
static unsigned int num_dio48e;
module_param_array(base, uint, &num_dio48e, 0);
MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses");
static unsigned int irq[MAX_NUM_DIO48E];
module_param_array(irq, uint, NULL, 0);
MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
/**
* struct dio48e_gpio - GPIO device private data structure
@@ -294,23 +302,19 @@ static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __init dio48e_probe(struct platform_device *pdev)
static int dio48e_probe(struct device *dev, unsigned int id)
{
struct device *dev = &pdev->dev;
struct dio48e_gpio *dio48egpio;
const unsigned base = dio_48e_base;
const unsigned extent = 16;
const char *const name = dev_name(dev);
int err;
const unsigned irq = dio_48e_irq;
dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
if (!dio48egpio)
return -ENOMEM;
if (!devm_request_region(dev, base, extent, name)) {
if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
base, base + extent);
base[id], base[id] + DIO48E_EXTENT);
return -EBUSY;
}
@@ -324,8 +328,8 @@ static int __init dio48e_probe(struct platform_device *pdev)
dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
dio48egpio->chip.get = dio48e_gpio_get;
dio48egpio->chip.set = dio48e_gpio_set;
dio48egpio->base = base;
dio48egpio->irq = irq;
dio48egpio->base = base[id];
dio48egpio->irq = irq[id];
spin_lock_init(&dio48egpio->lock);
@@ -338,19 +342,19 @@ static int __init dio48e_probe(struct platform_device *pdev)
}
/* initialize all GPIO as output */
outb(0x80, base + 3);
outb(0x00, base);
outb(0x00, base + 1);
outb(0x00, base + 2);
outb(0x00, base + 3);
outb(0x80, base + 7);
outb(0x00, base + 4);
outb(0x00, base + 5);
outb(0x00, base + 6);
outb(0x00, base + 7);
outb(0x80, base[id] + 3);
outb(0x00, base[id]);
outb(0x00, base[id] + 1);
outb(0x00, base[id] + 2);
outb(0x00, base[id] + 3);
outb(0x80, base[id] + 7);
outb(0x00, base[id] + 4);
outb(0x00, base[id] + 5);
outb(0x00, base[id] + 6);
outb(0x00, base[id] + 7);
/* disable IRQ by default */
inb(base + 0xB);
inb(base[id] + 0xB);
err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
@@ -359,7 +363,7 @@ static int __init dio48e_probe(struct platform_device *pdev)
goto err_gpiochip_remove;
}
err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio);
err = request_irq(irq[id], dio48e_irq_handler, 0, name, dio48egpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
goto err_gpiochip_remove;
@@ -372,9 +376,9 @@ err_gpiochip_remove:
return err;
}
static int dio48e_remove(struct platform_device *pdev)
static int dio48e_remove(struct device *dev, unsigned int id)
{
struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev);
struct dio48e_gpio *const dio48egpio = dev_get_drvdata(dev);
free_irq(dio48egpio->irq, dio48egpio);
gpiochip_remove(&dio48egpio->chip);
@@ -382,48 +386,14 @@ static int dio48e_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device *dio48e_device;
static struct platform_driver dio48e_driver = {
static struct isa_driver dio48e_driver = {
.probe = dio48e_probe,
.driver = {
.name = "104-dio-48e"
},
.remove = dio48e_remove
};
static void __exit dio48e_exit(void)
{
platform_device_unregister(dio48e_device);
platform_driver_unregister(&dio48e_driver);
}
static int __init dio48e_init(void)
{
int err;
dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1);
if (!dio48e_device)
return -ENOMEM;
err = platform_device_add(dio48e_device);
if (err)
goto err_platform_device;
err = platform_driver_probe(&dio48e_driver, dio48e_probe);
if (err)
goto err_platform_driver;
return 0;
err_platform_driver:
platform_device_del(dio48e_device);
err_platform_device:
platform_device_put(dio48e_device);
return err;
}
module_init(dio48e_init);
module_exit(dio48e_exit);
module_isa_driver(dio48e_driver, num_dio48e);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");

View File

@@ -10,6 +10,9 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* This driver supports the following ACCES devices: 104-IDI-48A,
* 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
*/
#include <linux/bitops.h>
#include <linux/device.h>
@@ -19,18 +22,23 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irqdesc.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
static unsigned idi_48_base;
module_param(idi_48_base, uint, 0);
MODULE_PARM_DESC(idi_48_base, "ACCES 104-IDI-48 base address");
static unsigned idi_48_irq;
module_param(idi_48_irq, uint, 0);
MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number");
#define IDI_48_EXTENT 8
#define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
static unsigned int base[MAX_NUM_IDI_48];
static unsigned int num_idi_48;
module_param_array(base, uint, &num_idi_48, 0);
MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
static unsigned int irq[MAX_NUM_IDI_48];
module_param_array(irq, uint, NULL, 0);
MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
/**
* struct idi_48_gpio - GPIO device private data structure
@@ -211,23 +219,19 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __init idi_48_probe(struct platform_device *pdev)
static int idi_48_probe(struct device *dev, unsigned int id)
{
struct device *dev = &pdev->dev;
struct idi_48_gpio *idi48gpio;
const unsigned base = idi_48_base;
const unsigned extent = 8;
const char *const name = dev_name(dev);
int err;
const unsigned irq = idi_48_irq;
idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
if (!idi48gpio)
return -ENOMEM;
if (!devm_request_region(dev, base, extent, name)) {
if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
base, base + extent);
base[id], base[id] + IDI_48_EXTENT);
return -EBUSY;
}
@@ -239,8 +243,8 @@ static int __init idi_48_probe(struct platform_device *pdev)
idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
idi48gpio->chip.get = idi_48_gpio_get;
idi48gpio->base = base;
idi48gpio->irq = irq;
idi48gpio->base = base[id];
idi48gpio->irq = irq[id];
spin_lock_init(&idi48gpio->lock);
@@ -253,8 +257,8 @@ static int __init idi_48_probe(struct platform_device *pdev)
}
/* Disable IRQ by default */
outb(0, base + 7);
inb(base + 7);
outb(0, base[id] + 7);
inb(base[id] + 7);
err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
@@ -263,7 +267,7 @@ static int __init idi_48_probe(struct platform_device *pdev)
goto err_gpiochip_remove;
}
err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name,
err = request_irq(irq[id], idi_48_irq_handler, IRQF_SHARED, name,
idi48gpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
@@ -277,9 +281,9 @@ err_gpiochip_remove:
return err;
}
static int idi_48_remove(struct platform_device *pdev)
static int idi_48_remove(struct device *dev, unsigned int id)
{
struct idi_48_gpio *const idi48gpio = platform_get_drvdata(pdev);
struct idi_48_gpio *const idi48gpio = dev_get_drvdata(dev);
free_irq(idi48gpio->irq, idi48gpio);
gpiochip_remove(&idi48gpio->chip);
@@ -287,48 +291,14 @@ static int idi_48_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device *idi_48_device;
static struct platform_driver idi_48_driver = {
static struct isa_driver idi_48_driver = {
.probe = idi_48_probe,
.driver = {
.name = "104-idi-48"
},
.remove = idi_48_remove
};
static void __exit idi_48_exit(void)
{
platform_device_unregister(idi_48_device);
platform_driver_unregister(&idi_48_driver);
}
static int __init idi_48_init(void)
{
int err;
idi_48_device = platform_device_alloc(idi_48_driver.driver.name, -1);
if (!idi_48_device)
return -ENOMEM;
err = platform_device_add(idi_48_device);
if (err)
goto err_platform_device;
err = platform_driver_probe(&idi_48_driver, idi_48_probe);
if (err)
goto err_platform_driver;
return 0;
err_platform_driver:
platform_device_del(idi_48_device);
err_platform_device:
platform_device_put(idi_48_device);
return err;
}
module_init(idi_48_init);
module_exit(idi_48_exit);
module_isa_driver(idi_48_driver, num_idi_48);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");

View File

@@ -10,6 +10,9 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* This driver supports the following ACCES devices: 104-IDIO-16,
* 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
*/
#include <linux/bitops.h>
#include <linux/device.h>
@@ -19,18 +22,23 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irqdesc.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
static unsigned idio_16_base;
module_param(idio_16_base, uint, 0);
MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address");
static unsigned idio_16_irq;
module_param(idio_16_irq, uint, 0);
MODULE_PARM_DESC(idio_16_irq, "ACCES 104-IDIO-16 interrupt line number");
#define IDIO_16_EXTENT 8
#define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
static unsigned int base[MAX_NUM_IDIO_16];
static unsigned int num_idio_16;
module_param_array(base, uint, &num_idio_16, 0);
MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
static unsigned int irq[MAX_NUM_IDIO_16];
module_param_array(irq, uint, NULL, 0);
MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
/**
* struct idio_16_gpio - GPIO device private data structure
@@ -185,23 +193,19 @@ static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __init idio_16_probe(struct platform_device *pdev)
static int idio_16_probe(struct device *dev, unsigned int id)
{
struct device *dev = &pdev->dev;
struct idio_16_gpio *idio16gpio;
const unsigned base = idio_16_base;
const unsigned extent = 8;
const char *const name = dev_name(dev);
int err;
const unsigned irq = idio_16_irq;
idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
if (!idio16gpio)
return -ENOMEM;
if (!devm_request_region(dev, base, extent, name)) {
if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
base, base + extent);
base[id], base[id] + IDIO_16_EXTENT);
return -EBUSY;
}
@@ -215,8 +219,8 @@ static int __init idio_16_probe(struct platform_device *pdev)
idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
idio16gpio->chip.get = idio_16_gpio_get;
idio16gpio->chip.set = idio_16_gpio_set;
idio16gpio->base = base;
idio16gpio->irq = irq;
idio16gpio->base = base[id];
idio16gpio->irq = irq[id];
idio16gpio->out_state = 0xFFFF;
spin_lock_init(&idio16gpio->lock);
@@ -230,8 +234,8 @@ static int __init idio_16_probe(struct platform_device *pdev)
}
/* Disable IRQ by default */
outb(0, base + 2);
outb(0, base + 1);
outb(0, base[id] + 2);
outb(0, base[id] + 1);
err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
@@ -240,7 +244,7 @@ static int __init idio_16_probe(struct platform_device *pdev)
goto err_gpiochip_remove;
}
err = request_irq(irq, idio_16_irq_handler, 0, name, idio16gpio);
err = request_irq(irq[id], idio_16_irq_handler, 0, name, idio16gpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
goto err_gpiochip_remove;
@@ -253,9 +257,9 @@ err_gpiochip_remove:
return err;
}
static int idio_16_remove(struct platform_device *pdev)
static int idio_16_remove(struct device *dev, unsigned int id)
{
struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev);
struct idio_16_gpio *const idio16gpio = dev_get_drvdata(dev);
free_irq(idio16gpio->irq, idio16gpio);
gpiochip_remove(&idio16gpio->chip);
@@ -263,48 +267,15 @@ static int idio_16_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device *idio_16_device;
static struct platform_driver idio_16_driver = {
static struct isa_driver idio_16_driver = {
.probe = idio_16_probe,
.driver = {
.name = "104-idio-16"
},
.remove = idio_16_remove
};
static void __exit idio_16_exit(void)
{
platform_device_unregister(idio_16_device);
platform_driver_unregister(&idio_16_driver);
}
static int __init idio_16_init(void)
{
int err;
idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1);
if (!idio_16_device)
return -ENOMEM;
err = platform_device_add(idio_16_device);
if (err)
goto err_platform_device;
err = platform_driver_probe(&idio_16_driver, idio_16_probe);
if (err)
goto err_platform_driver;
return 0;
err_platform_driver:
platform_device_del(idio_16_device);
err_platform_device:
platform_device_put(idio_16_device);
return err;
}
module_init(idio_16_init);
module_exit(idio_16_exit);
module_isa_driver(idio_16_driver, num_idio_16);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");

View File

@@ -19,18 +19,23 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irqdesc.h>
#include <linux/isa.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
static unsigned ws16c48_base;
module_param(ws16c48_base, uint, 0);
MODULE_PARM_DESC(ws16c48_base, "WinSystems WS16C48 base address");
static unsigned ws16c48_irq;
module_param(ws16c48_irq, uint, 0);
MODULE_PARM_DESC(ws16c48_irq, "WinSystems WS16C48 interrupt line number");
#define WS16C48_EXTENT 16
#define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT)
static unsigned int base[MAX_NUM_WS16C48];
static unsigned int num_ws16c48;
module_param_array(base, uint, &num_ws16c48, 0);
MODULE_PARM_DESC(base, "WinSystems WS16C48 base addresses");
static unsigned int irq[MAX_NUM_WS16C48];
module_param_array(irq, uint, NULL, 0);
MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers");
/**
* struct ws16c48_gpio - GPIO device private data structure
@@ -298,23 +303,19 @@ static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __init ws16c48_probe(struct platform_device *pdev)
static int ws16c48_probe(struct device *dev, unsigned int id)
{
struct device *dev = &pdev->dev;
struct ws16c48_gpio *ws16c48gpio;
const unsigned base = ws16c48_base;
const unsigned extent = 16;
const char *const name = dev_name(dev);
int err;
const unsigned irq = ws16c48_irq;
ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL);
if (!ws16c48gpio)
return -ENOMEM;
if (!devm_request_region(dev, base, extent, name)) {
if (!devm_request_region(dev, base[id], WS16C48_EXTENT, name)) {
dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
base, base + extent);
base[id], base[id] + WS16C48_EXTENT);
return -EBUSY;
}
@@ -328,8 +329,8 @@ static int __init ws16c48_probe(struct platform_device *pdev)
ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output;
ws16c48gpio->chip.get = ws16c48_gpio_get;
ws16c48gpio->chip.set = ws16c48_gpio_set;
ws16c48gpio->base = base;
ws16c48gpio->irq = irq;
ws16c48gpio->base = base[id];
ws16c48gpio->irq = irq[id];
spin_lock_init(&ws16c48gpio->lock);
@@ -342,11 +343,11 @@ static int __init ws16c48_probe(struct platform_device *pdev)
}
/* Disable IRQ by default */
outb(0x80, base + 7);
outb(0, base + 8);
outb(0, base + 9);
outb(0, base + 10);
outb(0xC0, base + 7);
outb(0x80, base[id] + 7);
outb(0, base[id] + 8);
outb(0, base[id] + 9);
outb(0, base[id] + 10);
outb(0xC0, base[id] + 7);
err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0,
handle_edge_irq, IRQ_TYPE_NONE);
@@ -355,7 +356,7 @@ static int __init ws16c48_probe(struct platform_device *pdev)
goto err_gpiochip_remove;
}
err = request_irq(irq, ws16c48_irq_handler, IRQF_SHARED, name,
err = request_irq(irq[id], ws16c48_irq_handler, IRQF_SHARED, name,
ws16c48gpio);
if (err) {
dev_err(dev, "IRQ handler registering failed (%d)\n", err);
@@ -369,9 +370,9 @@ err_gpiochip_remove:
return err;
}
static int ws16c48_remove(struct platform_device *pdev)
static int ws16c48_remove(struct device *dev, unsigned int id)
{
struct ws16c48_gpio *const ws16c48gpio = platform_get_drvdata(pdev);
struct ws16c48_gpio *const ws16c48gpio = dev_get_drvdata(dev);
free_irq(ws16c48gpio->irq, ws16c48gpio);
gpiochip_remove(&ws16c48gpio->chip);
@@ -379,48 +380,15 @@ static int ws16c48_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device *ws16c48_device;
static struct platform_driver ws16c48_driver = {
static struct isa_driver ws16c48_driver = {
.probe = ws16c48_probe,
.driver = {
.name = "ws16c48"
},
.remove = ws16c48_remove
};
static void __exit ws16c48_exit(void)
{
platform_device_unregister(ws16c48_device);
platform_driver_unregister(&ws16c48_driver);
}
static int __init ws16c48_init(void)
{
int err;
ws16c48_device = platform_device_alloc(ws16c48_driver.driver.name, -1);
if (!ws16c48_device)
return -ENOMEM;
err = platform_device_add(ws16c48_device);
if (err)
goto err_platform_device;
err = platform_driver_probe(&ws16c48_driver, ws16c48_probe);
if (err)
goto err_platform_driver;
return 0;
err_platform_driver:
platform_device_del(ws16c48_device);
err_platform_device:
platform_device_put(ws16c48_device);
return err;
}
module_init(ws16c48_init);
module_exit(ws16c48_exit);
module_isa_driver(ws16c48_driver, num_ws16c48);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver");