Skip to content

Commit

Permalink
feat: use devm API for GPIO
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilia Kuznetsov committed Mar 22, 2024
1 parent 4824a44 commit 4d8ba41
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 87 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ sudo modprobe --force-vermagic ./bes2600.ko
## TODO list
1. ~~Get rid of all unnecessary code (usb/spi parts that we couldn't care less about)~~ [done](https://github.com/cringeops/bes2600/pull/2)
2. ~~Implement MAC setting the standard way via DT local-mac-address~~ [done, needs provided dtsi](https://github.com/cringeops/bes2600/pull/5)
3. Use devm API for GPIO managament
3. ~~Use devm API for GPIO management~~ [done](https://github.com/cringeops/bes2600/pull/6)
4. Solve the sleep issue (PT2 doesn't go into sleep if bes2600 module is loaded)
1 change: 1 addition & 0 deletions bes2600/bes2600_plat.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct bes2600_platform_data_sdio {
const u8 *macaddr; /* if NULL, use bes2600_mac_template module parameter */
const char *sdd_file; /* if NULL, will use default for detected hw type */
bool wakeup_source; /* marks whether bes2600 is the wakeup souce or not */
bool inited; /* platform data init flag */
};

#endif /* BES2600_PLAT_H_INCLUDED */
142 changes: 56 additions & 86 deletions bes2600/bes2600_sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,19 +528,17 @@ static int bes2600_sdio_irq_unsubscribe(struct sbus_priv *self)
return ret;
}

static int bes2600_sdio_off(const struct bes2600_platform_data_sdio *pdata)
static void bes2600_sdio_off(const struct bes2600_platform_data_sdio *pdata)
{
bes2600_info(BES2600_DBG_SDIO, "%s enter\n", __func__);
bes2600_info(BES2600_DBG_SDIO, "%s\n", __func__);
gpiod_direction_output(pdata->powerup, GPIOD_OUT_LOW);
gpiod_direction_output(pdata->reset, GPIOD_OUT_LOW);
return 0;
}

static int bes2600_sdio_on(const struct bes2600_platform_data_sdio *pdata)
static void bes2600_sdio_on(const struct bes2600_platform_data_sdio *pdata)
{
bes2600_info(BES2600_DBG_SDIO, "%s enter\n", __func__);
bes2600_info(BES2600_DBG_SDIO, "%s\n", __func__);
gpiod_direction_output(pdata->powerup, GPIOD_OUT_HIGH);
return 0;
}

static size_t bes2600_sdio_align_size(struct sbus_priv *self, size_t size)
Expand Down Expand Up @@ -1256,74 +1254,69 @@ static int bes2600_sdio_misc_init(struct sbus_priv *self, struct bes2600_common
return 0;
}

static struct bes2600_platform_data_sdio bes_sdio_plat_data;
static struct bes2600_platform_data_sdio bes_sdio_plat_data = {
.inited = false
};

struct bes2600_platform_data_sdio *bes2600_get_platform_data(void)
{
return &bes_sdio_plat_data;
}

static int bes2600_platform_data_init(void)
static int bes2600_platform_data_init(struct device *dev)
{
int ret = 0;
struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data();
struct device_node *np;

// skip reinit if already inited
if (pdata->inited)
return 0;

np = of_find_compatible_node(NULL, NULL, "bestechnic,bes2600-sdio");
if (!np) {
bes2600_err(BES2600_DBG_SDIO, "bes2600-sdio device node not found!\n");
goto exit;
return -ENXIO;
}

/* Ensure I/Os are pulled low */
pdata->reset = fwnode_gpiod_get_index(&np->fwnode, "reset", 0, GPIOD_OUT_LOW, "bes2600_wlan_reset");
pdata->reset = devm_fwnode_gpiod_get_index(dev, &np->fwnode, "reset", 0, GPIOD_OUT_LOW, "bes2600_wlan_reset");
if (IS_ERR(pdata->reset)) {
bes2600_err(BES2600_DBG_SDIO, "can't request reset_gpio (%ld)\n", PTR_ERR(pdata->reset));
pdata->reset = NULL;
}

pdata->powerup = fwnode_gpiod_get_index(&np->fwnode, "powerup", 0, GPIOD_OUT_LOW, "bes2600_wlan_powerup");
pdata->powerup = devm_fwnode_gpiod_get_index(dev, &np->fwnode, "powerup", 0, GPIOD_OUT_LOW, "bes2600_wlan_powerup");
if (IS_ERR(pdata->powerup)) {
bes2600_err(BES2600_DBG_SDIO, "can't request powerup_gpio (%ld)\n", PTR_ERR(pdata->powerup));
pdata->powerup = NULL;
}

pdata->wakeup = fwnode_gpiod_get_index(&np->fwnode, "wakeup", 0, GPIOD_OUT_LOW, "bes2600_wakeup");
pdata->wakeup = devm_fwnode_gpiod_get_index(dev, &np->fwnode, "wakeup", 0, GPIOD_OUT_LOW, "bes2600_wakeup");
if (IS_ERR(pdata->wakeup)) {
bes2600_err(BES2600_DBG_SDIO, "can't request wakeup_gpio (%ld)\n", PTR_ERR(pdata->wakeup));
pdata->wakeup = NULL;
}

pdata->host_wakeup = fwnode_gpiod_get_index(&np->fwnode, "host-wakeup", 0, GPIOD_IN, "bes2600_host_irq");
pdata->host_wakeup = devm_fwnode_gpiod_get_index(dev, &np->fwnode, "host-wakeup", 0, GPIOD_IN, "bes2600_host_irq");
if (IS_ERR(pdata->host_wakeup)) {
bes2600_err(BES2600_DBG_SDIO, "can't request host_wake_gpio (%ld)\n", PTR_ERR(pdata->host_wakeup));
pdata->host_wakeup = NULL;
}

pdata->wlan_bt_hostwake_registered = false;
exit:
return ret;
}

static void bes2600_platform_data_deinit(void)
{
const struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data();

gpiod_put(pdata->reset);
gpiod_put(pdata->powerup);
gpiod_put(pdata->wakeup);
gpiod_put(pdata->host_wakeup);
pdata->inited = true;
return 0;
}

static int bes2600_sdio_reset(struct sbus_priv *self)
{
const struct bes2600_platform_data_sdio *plat_data = bes2600_get_platform_data();
const struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data();

bes2600_info(BES2600_DBG_SDIO, "%s ...\n", __func__);
bes2600_info(BES2600_DBG_SDIO, "%s\n", __func__);

gpiod_direction_output(plat_data->reset, GPIOD_OUT_HIGH);
gpiod_direction_output(pdata->reset, GPIOD_OUT_HIGH);
mdelay(50);
gpiod_direction_output(plat_data->reset, GPIOD_OUT_LOW);
gpiod_direction_output(pdata->reset, GPIOD_OUT_LOW);

return 0;
}
Expand Down Expand Up @@ -1717,21 +1710,6 @@ int bes2600_sdio_deactive(struct sbus_priv *self, int sub_system)
return -ENODEV;
}

static int bes2600_sdio_power_up(void)
{
const struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data();
int ret;

ret = bes2600_sdio_on(pdata);
if (ret)
goto err_on;

return 0;

err_on:
return ret;
}

static void bes2600_sdio_power_down(struct sbus_priv *self)
{
#ifdef POWER_DOWN_BY_MSG
Expand Down Expand Up @@ -1759,14 +1737,14 @@ static void bes2600_sdio_power_down(struct sbus_priv *self)

static int bes2600_sdio_power_switch(struct sbus_priv *self, int on)
{
int ret = 0;
if(on) {
ret = bes2600_sdio_power_up();
} else {
bes2600_sdio_power_down(self);
// TODO: return something meaningful, perhaps
struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data();
if (on) {
bes2600_sdio_on(pdata);
return 0;
}

return ret;
bes2600_sdio_power_down(self);
return 0;
}

static void bes2600_sdio_halt_device(struct sbus_priv *self)
Expand Down Expand Up @@ -1846,6 +1824,12 @@ static int bes2600_sdio_probe(struct sdio_func *func,
return -ENOMEM;
}
spin_lock_init(&self->lock);

struct device *dev = &func->dev;
int ret = bes2600_platform_data_init(dev);
if (ret)
goto err;

self->pdata = bes2600_get_platform_data();
self->func = func;
self->dev = &func->dev;
Expand Down Expand Up @@ -1964,10 +1948,9 @@ bool bes2600_is_net_dev_created(struct sbus_priv *bus_priv)

/* Disconnect Function to be called by SDIO stack when
* device is disconnected */
static void bes2600_sdio_disconnect(struct sdio_func *func)
static void bes2600_sdio_remove(struct sdio_func *func)
{
struct sbus_priv *self = sdio_get_drvdata(func);
const struct bes2600_platform_data_sdio *pdata = bes2600_get_platform_data();

func->card->host->caps &= ~MMC_CAP_NONREMOVABLE;
bes2600_info(BES2600_DBG_SDIO, "%s called:%p,%d\n", __func__, func, func->num);
Expand All @@ -1983,7 +1966,6 @@ static void bes2600_sdio_disconnect(struct sdio_func *func)
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
bes2600_sdio_off(pdata);
bes2600_reg_set_object(NULL, NULL);
bes2600_chrdev_set_sbus_priv_data(NULL, false);
sdio_set_drvdata(func, NULL);
Expand Down Expand Up @@ -2232,7 +2214,7 @@ static struct sdio_driver sdio_driver = {
.name = "bes2600_wlan",
.id_table = bes2600_sdio_ids,
.probe = bes2600_sdio_probe,
.remove = bes2600_sdio_disconnect,
.remove = bes2600_sdio_remove,
.drv = {
.pm = &bes2600_pm_ops,
}
Expand All @@ -2241,42 +2223,33 @@ static struct sdio_driver sdio_driver = {
/* Init Module function -> Called by insmod */
static int __init bes2600_sdio_init(void)
{
int ret;
const struct bes2600_platform_data_sdio *pdata = NULL;

bes2600_info(BES2600_DBG_SDIO, "------Driver: bes2600.ko version :%s\n", BES2600_DRV_VERSION);

bes2600_chrdev_update_signal_mode();
bes2600_dbg(BES2600_DBG_SDIO, "%s type:%d sig_mode:%d\n", __func__,
bes2600_chrdev_get_fw_type(), bes2600_chrdev_is_signal_mode());

if ((ret = bes2600_platform_data_init()))
goto exit;

pdata = bes2600_get_platform_data();

ret = bes2600_chrdev_init(&bes2600_sdio_sbus_ops);
if(ret)
goto err_chardev;

ret = bes2600_sdio_on(pdata);
int ret = bes2600_chrdev_init(&bes2600_sdio_sbus_ops);
if (ret)
goto err_on;
return ret;

ret = sdio_register_driver(&sdio_driver);
if (ret)
goto err_reg;
if (ret) {
bes2600_chrdev_free();
return ret;
}

return 0;
pdata = bes2600_get_platform_data();
if (!pdata->inited) {
bes2600_err(BES2600_DBG_SDIO, "pdata->inited = %d, platform data must be inited at this point\n", pdata->inited);
sdio_unregister_driver(&sdio_driver);
bes2600_chrdev_free();
// probably does nothing, but still
if (pdata)
bes2600_sdio_off(pdata);
return -ECANCELED;
}

err_reg:
bes2600_sdio_off(pdata);
err_on:
bes2600_chrdev_free();
err_chardev:
bes2600_platform_data_deinit();
exit:
return ret;
return 0;
}

/* Called at Driver Unloading */
Expand All @@ -2289,10 +2262,7 @@ static void __exit bes2600_sdio_exit(void)
bes2600_unregister_net_dev(priv);
sdio_unregister_driver(&sdio_driver);
bes2600_chrdev_free();
if(!priv) {
bes2600_sdio_off(pdata);
}
bes2600_platform_data_deinit();
bes2600_sdio_off(pdata);
}

module_init(bes2600_sdio_init);
Expand Down

0 comments on commit 4d8ba41

Please sign in to comment.