Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/stat.h>
#include <linux/hwmon-sysfs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>

#define I2C_RW_RETRY_COUNT 10
#define I2C_RW_RETRY_INTERVAL 60 /* ms */
Expand Down Expand Up @@ -64,6 +65,8 @@ enum as4610_product_id_e {
struct as4610_54_cpld_data {
enum cpld_type type;
struct device *hwmon_dev;
struct platform_device *fan_pdev;
struct platform_device *led_pdev;
struct mutex update_lock;
};

Expand Down Expand Up @@ -443,13 +446,16 @@ static ssize_t show_version(struct device *dev, struct device_attribute *attr, c
return sprintf(buf, "%d", val);
}

int as4610_product_id(void);

/* I2C init/probing/exit functions */
static int as4610_54_cpld_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
struct as4610_54_cpld_data *data;
int ret = -ENODEV;
int pid;

if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
goto exit;
Expand All @@ -472,8 +478,41 @@ static int as4610_54_cpld_probe(struct i2c_client *client,
}

as4610_54_cpld_add_client(client);

pid = as4610_product_id();

switch (pid) {
case PID_AS4610_30P:
case PID_AS4610_54P:
case PID_AS4610_54T_B:
data->fan_pdev = platform_device_register_simple("as4610_fan", -1, NULL, 0);
if (IS_ERR(data->fan_pdev)) {
ret = PTR_ERR(data->fan_pdev);
goto exit_unregister;
}
break;
default:
/* no fan */
break;
}

if (pid != PID_UNKNOWN) {
data->led_pdev = platform_device_register_simple("as4610_led", -1, NULL, 0);
if (IS_ERR(data->led_pdev)) {
ret = PTR_ERR(data->led_pdev);
goto exit_unregister_fan;
}
}

return 0;

exit_unregister_fan:
platform_device_unregister(data->fan_pdev);

exit_unregister:
as4610_54_cpld_remove_client(client);
/* Remove sysfs hooks */
sysfs_remove_group(&client->dev.kobj, &as4610_54_cpld_group);
exit_free:
kfree(data);
exit:
Expand All @@ -484,6 +523,12 @@ static int as4610_54_cpld_remove(struct i2c_client *client)
{
struct as4610_54_cpld_data *data = i2c_get_clientdata(client);

if (data->led_pdev)
platform_device_unregister(data->led_pdev);

if (data->fan_pdev)
platform_device_unregister(data->fan_pdev);

as4610_54_cpld_remove_client(client);

/* Remove sysfs hooks */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,19 @@ static int as4610_fan_probe(struct platform_device *pdev)
{
int status = -1;

fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL);
if (!fan_data) {
status = -ENOMEM;
goto exit;
}

mutex_init(&fan_data->update_lock);
fan_data->valid = 0;

/* Register sysfs hooks */
status = sysfs_create_group(&pdev->dev.kobj, &as4610_fan_group);
if (status) {
goto exit;

goto exit_free;
}

fan_data->hwmon_dev = hwmon_device_register_with_info(&pdev->dev, "as4610_fan",
Expand All @@ -275,6 +283,8 @@ static int as4610_fan_probe(struct platform_device *pdev)

exit_remove:
sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group);
exit_free:
kfree(fan_data);
exit:
return status;
}
Expand All @@ -284,93 +294,28 @@ static int as4610_fan_remove(struct platform_device *pdev)
hwmon_device_unregister(fan_data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group);

kfree(fan_data);

return 0;
}

static const struct i2c_device_id as4610_fan_id[] = {
static const struct platform_device_id as4610_fan_id[] = {
{ "as4610_fan", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, as4610_fan_id);
MODULE_DEVICE_TABLE(platform, as4610_fan_id);

static struct platform_driver as4610_fan_driver = {
.probe = as4610_fan_probe,
.remove = as4610_fan_remove,
.id_table = as4610_fan_id,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};

static int as4610_number_of_system_fan(void)
{
int nFan = 0;
int pid = as4610_product_id();

switch (pid) {
case PID_AS4610_30P:
case PID_AS4610_54P:
nFan = 1;
break;
case PID_AS4610_54T_B:
nFan = 2;
break;
default:
nFan = 0;
break;
}

return nFan;
}

static int __init as4610_fan_init(void)
{
int ret;

if (as4610_number_of_system_fan() == 0) {
return 0;
}

ret = platform_driver_register(&as4610_fan_driver);
if (ret < 0) {
goto exit;
}

fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL);
if (!fan_data) {
ret = -ENOMEM;
platform_driver_unregister(&as4610_fan_driver);
goto exit;
}

mutex_init(&fan_data->update_lock);
fan_data->valid = 0;

fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(fan_data->pdev)) {
ret = PTR_ERR(fan_data->pdev);
platform_driver_unregister(&as4610_fan_driver);
kfree(fan_data);
goto exit;
}

exit:
return ret;
}

static void __exit as4610_fan_exit(void)
{
if (!fan_data) {
return;
}

platform_device_unregister(fan_data->pdev);
platform_driver_unregister(&as4610_fan_driver);
kfree(fan_data);
}

late_initcall(as4610_fan_init);
module_exit(as4610_fan_exit);
module_platform_driver(as4610_fan_driver);

MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as4610_fan driver");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
/*#define DEBUG*/

#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
Expand Down Expand Up @@ -575,6 +576,19 @@ static int as4610_led_probe(struct platform_device *pdev)
{
int ret = 0, i;

int pid = as4610_product_id();
if (pid == PID_UNKNOWN) {
return -ENODEV;
}

ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL);
if (!ledctl) {
return -ENOMEM;
}

ledctl->led_map = as4610_ledmaps[pid];
mutex_init(&ledctl->update_lock);

for (i = 0; i < NUM_OF_LED; i++) {
if (!(ledctl->led_map & BIT(i))) {
continue;
Expand All @@ -597,6 +611,7 @@ static int as4610_led_probe(struct platform_device *pdev)

led_classdev_unregister(&as4610_leds[i]);
}
kfree(ledctl);

return ret;
}
Expand All @@ -612,72 +627,28 @@ static int as4610_led_remove(struct platform_device *pdev)

led_classdev_unregister(&as4610_leds[i]);
}
kfree(ledctl);

return 0;
}

static const struct platform_device_id as4610_led_id[] = {
{ "as4610_led", 0 },
{}
};
MODULE_DEVICE_TABLE(platform, as4610_led_id);

static struct platform_driver as4610_led_driver = {
.probe = as4610_led_probe,
.remove = as4610_led_remove,
.id_table = as4610_led_id,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};

static int __init as4610_led_init(void)
{
int ret, pid;

if (as4610_product_id() == PID_UNKNOWN) {
return -ENODEV;
}

ret = platform_driver_register(&as4610_led_driver);
if (ret < 0) {
goto exit;
}

ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL);
if (!ledctl) {
ret = -ENOMEM;
platform_driver_unregister(&as4610_led_driver);
goto exit;
}

pid = as4610_product_id();
if (pid == PID_UNKNOWN) {
return -ENODEV;
}

ledctl->led_map = as4610_ledmaps[pid];
mutex_init(&ledctl->update_lock);

ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(ledctl->pdev)) {
ret = PTR_ERR(ledctl->pdev);
platform_driver_unregister(&as4610_led_driver);
kfree(ledctl);
goto exit;
}

exit:
return ret;
}

static void __exit as4610_led_exit(void)
{
if (!ledctl) {
return;
}

platform_device_unregister(ledctl->pdev);
platform_driver_unregister(&as4610_led_driver);
kfree(ledctl);
}

late_initcall(as4610_led_init);
module_exit(as4610_led_exit);
module_platform_driver(as4610_led_driver);

MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as4610_led driver");
Expand Down