Commit 7582eb9b authored by Jonathan Corbet's avatar Jonathan Corbet

viafb: Turn GPIO and i2c into proper platform devices

Another step toward making this thing a real multifunction device driver.

Cc: ScottFang@viatech.com.cn
Cc: JosephChan@via.com.tw
Cc: Harald Welte <laforge@gnumonks.org>
Acked-by: default avatarFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>
Signed-off-by: default avatarJonathan Corbet <corbet@lwn.net>
parent 75b035ac
...@@ -190,6 +190,70 @@ static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) ...@@ -190,6 +190,70 @@ static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev)
iounmap(vdev->engine_mmio); iounmap(vdev->engine_mmio);
} }
/*
* Create our subsidiary devices.
*/
static struct viafb_subdev_info {
char *name;
struct platform_device *platdev;
} viafb_subdevs[] = {
{
.name = "viafb-gpio",
},
{
.name = "viafb-i2c",
}
};
#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
static int __devinit via_create_subdev(struct viafb_dev *vdev,
struct viafb_subdev_info *info)
{
int ret;
info->platdev = platform_device_alloc(info->name, -1);
if (!info->platdev) {
dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
info->name);
return -ENOMEM;
}
info->platdev->dev.parent = &vdev->pdev->dev;
info->platdev->dev.platform_data = vdev;
ret = platform_device_add(info->platdev);
if (ret) {
dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
info->name);
platform_device_put(info->platdev);
info->platdev = NULL;
}
return ret;
}
static int __devinit via_setup_subdevs(struct viafb_dev *vdev)
{
int i;
/*
* Ignore return values. Even if some of the devices
* fail to be created, we'll still be able to use some
* of the rest.
*/
for (i = 0; i < N_SUBDEVS; i++)
via_create_subdev(vdev, viafb_subdevs + i);
return 0;
}
static void __devexit via_teardown_subdevs(void)
{
int i;
for (i = 0; i < N_SUBDEVS; i++)
if (viafb_subdevs[i].platdev) {
viafb_subdevs[i].platdev->dev.platform_data = NULL;
platform_device_unregister(viafb_subdevs[i].platdev);
}
}
static int __devinit via_pci_probe(struct pci_dev *pdev, static int __devinit via_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
...@@ -205,33 +269,25 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ...@@ -205,33 +269,25 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
memset(&global_dev, 0, sizeof(global_dev)); memset(&global_dev, 0, sizeof(global_dev));
global_dev.pdev = pdev; global_dev.pdev = pdev;
global_dev.chip_type = ent->driver_data; global_dev.chip_type = ent->driver_data;
global_dev.port_cfg = adap_configs;
spin_lock_init(&global_dev.reg_lock); spin_lock_init(&global_dev.reg_lock);
ret = via_pci_setup_mmio(&global_dev); ret = via_pci_setup_mmio(&global_dev);
if (ret) if (ret)
goto out_disable; goto out_disable;
/* /*
* Create the I2C busses. Bailing out on failure seems extreme, * Create our subdevices. Continue even if some things fail.
* but that's what the code did before.
*/ */
ret = viafb_create_i2c_busses(&global_dev, adap_configs); via_setup_subdevs(&global_dev);
if (ret)
goto out_teardown;
/* /*
* Set up the framebuffer. * Set up the framebuffer.
*/ */
ret = via_fb_pci_probe(&global_dev); ret = via_fb_pci_probe(&global_dev);
if (ret) if (ret)
goto out_i2c; goto out_subdevs;
/*
* Create the GPIOs. We continue whether or not this succeeds;
* the framebuffer might be useful even without GPIO ports.
*/
ret = viafb_create_gpios(&global_dev, adap_configs);
return 0; return 0;
out_i2c: out_subdevs:
viafb_delete_i2c_busses(); via_teardown_subdevs();
out_teardown:
via_pci_teardown_mmio(&global_dev); via_pci_teardown_mmio(&global_dev);
out_disable: out_disable:
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -240,8 +296,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ...@@ -240,8 +296,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev,
static void __devexit via_pci_remove(struct pci_dev *pdev) static void __devexit via_pci_remove(struct pci_dev *pdev)
{ {
viafb_destroy_gpios(); via_teardown_subdevs();
viafb_delete_i2c_busses();
via_fb_pci_remove(pdev); via_fb_pci_remove(pdev);
via_pci_teardown_mmio(&global_dev); via_pci_teardown_mmio(&global_dev);
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -289,12 +344,16 @@ static int __init via_core_init(void) ...@@ -289,12 +344,16 @@ static int __init via_core_init(void)
ret = viafb_init(); ret = viafb_init();
if (ret) if (ret)
return ret; return ret;
viafb_i2c_init();
viafb_gpio_init();
return pci_register_driver(&via_driver); return pci_register_driver(&via_driver);
} }
static void __exit via_core_exit(void) static void __exit via_core_exit(void)
{ {
pci_unregister_driver(&via_driver); pci_unregister_driver(&via_driver);
viafb_gpio_exit();
viafb_i2c_exit();
viafb_exit(); viafb_exit();
} }
......
...@@ -63,6 +63,7 @@ struct via_port_cfg { ...@@ -63,6 +63,7 @@ struct via_port_cfg {
struct viafb_dev { struct viafb_dev {
struct pci_dev *pdev; struct pci_dev *pdev;
int chip_type; int chip_type;
struct via_port_cfg *port_cfg;
/* /*
* Spinlock for access to device registers. Not yet * Spinlock for access to device registers. Not yet
* globally used. * globally used.
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/platform_device.h>
#include "via-core.h" #include "via-core.h"
#include "via-gpio.h" #include "via-gpio.h"
#include "global.h" #include "global.h"
...@@ -172,12 +173,27 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio) ...@@ -172,12 +173,27 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio)
via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
} }
/*
* Look up a specific gpio and return the number it was assigned.
*/
int viafb_gpio_lookup(const char *name)
{
int i;
for (i = 0; i < gpio_config.gpio_chip.ngpio; i++)
if (!strcmp(name, gpio_config.active_gpios[i]->vg_name))
return gpio_config.gpio_chip.base + i;
return -1;
}
EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
/*
int viafb_create_gpios(struct viafb_dev *vdev, * Platform device stuff.
const struct via_port_cfg *port_cfg) */
static __devinit int viafb_gpio_probe(struct platform_device *platdev)
{ {
struct viafb_dev *vdev = platdev->dev.platform_data;
struct via_port_cfg *port_cfg = vdev->port_cfg;
int i, ngpio = 0, ret; int i, ngpio = 0, ret;
struct viafb_gpio *gpio; struct viafb_gpio *gpio;
unsigned long flags; unsigned long flags;
...@@ -222,11 +238,10 @@ int viafb_create_gpios(struct viafb_dev *vdev, ...@@ -222,11 +238,10 @@ int viafb_create_gpios(struct viafb_dev *vdev,
gpio_config.gpio_chip.ngpio = 0; gpio_config.gpio_chip.ngpio = 0;
} }
return ret; return ret;
/* Port enable ? */
} }
int viafb_destroy_gpios(void) static int viafb_gpio_remove(struct platform_device *platdev)
{ {
unsigned long flags; unsigned long flags;
int ret = 0, i; int ret = 0, i;
...@@ -253,16 +268,20 @@ int viafb_destroy_gpios(void) ...@@ -253,16 +268,20 @@ int viafb_destroy_gpios(void)
return ret; return ret;
} }
/* static struct platform_driver via_gpio_driver = {
* Look up a specific gpio and return the number it was assigned. .driver = {
*/ .name = "viafb-gpio",
int viafb_gpio_lookup(const char *name) },
.probe = viafb_gpio_probe,
.remove = viafb_gpio_remove,
};
int viafb_gpio_init(void)
{ {
int i; return platform_driver_register(&via_gpio_driver);
}
for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) void viafb_gpio_exit(void)
if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) {
return gpio_config.gpio_chip.base + i; platform_driver_unregister(&via_gpio_driver);
return -1;
} }
EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
...@@ -8,8 +8,7 @@ ...@@ -8,8 +8,7 @@
#ifndef __VIA_GPIO_H__ #ifndef __VIA_GPIO_H__
#define __VIA_GPIO_H__ #define __VIA_GPIO_H__
extern int viafb_create_gpios(struct viafb_dev *vdev,
const struct via_port_cfg *port_cfg);
extern int viafb_destroy_gpios(void);
extern int viafb_gpio_lookup(const char *name); extern int viafb_gpio_lookup(const char *name);
extern int viafb_gpio_init(void);
extern void viafb_gpio_exit(void);
#endif #endif
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <linux/platform_device.h>
#include "via-core.h" #include "via-core.h"
#include "via_i2c.h" #include "via_i2c.h"
#include "global.h" #include "global.h"
...@@ -185,11 +186,14 @@ static int create_i2c_bus(struct i2c_adapter *adapter, ...@@ -185,11 +186,14 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
return i2c_bit_add_bus(adapter); return i2c_bit_add_bus(adapter);
} }
int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs) static int viafb_i2c_probe(struct platform_device *platdev)
{ {
int i, ret; int i, ret;
struct via_port_cfg *configs;
i2c_vdev = platdev->dev.platform_data;
configs = i2c_vdev->port_cfg;
i2c_vdev = dev;
for (i = 0; i < VIAFB_NUM_PORTS; i++) { for (i = 0; i < VIAFB_NUM_PORTS; i++) {
struct via_port_cfg *adap_cfg = configs++; struct via_port_cfg *adap_cfg = configs++;
struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
...@@ -211,7 +215,7 @@ int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs) ...@@ -211,7 +215,7 @@ int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs)
return 0; return 0;
} }
void viafb_delete_i2c_busses(void) static int viafb_i2c_remove(struct platform_device *platdev)
{ {
int i; int i;
...@@ -224,4 +228,23 @@ void viafb_delete_i2c_busses(void) ...@@ -224,4 +228,23 @@ void viafb_delete_i2c_busses(void)
if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo) if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo)
i2c_del_adapter(&i2c_stuff->adapter); i2c_del_adapter(&i2c_stuff->adapter);
} }
return 0;
}
static struct platform_driver via_i2c_driver = {
.driver = {
.name = "viafb-i2c",
},
.probe = viafb_i2c_probe,
.remove = viafb_i2c_remove,
};
int viafb_i2c_init(void)
{
return platform_driver_register(&via_i2c_driver);
}
void viafb_i2c_exit(void)
{
platform_driver_unregister(&via_i2c_driver);
} }
...@@ -35,8 +35,6 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); ...@@ -35,8 +35,6 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata);
int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data);
int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len);
struct viafb_par; extern int viafb_i2c_init(void);
int viafb_create_i2c_busses(struct viafb_dev *vdev, struct via_port_cfg *cfg); extern void viafb_i2c_exit(void);
void viafb_delete_i2c_busses(void);
struct i2c_adapter *viafb_find_adapter(enum viafb_i2c_adap which);
#endif /* __VIA_I2C_H__ */ #endif /* __VIA_I2C_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment