[PATCH v2] ARM/pxa/mfd/power/sound: Switch Tosa to GPIO descriptors
Dmitry Baryshkov
dbaryshkov at gmail.com
Mon Jan 24 18:22:02 PST 2022
вт, 25 янв. 2022 г. в 03:39, Linus Walleij <linus.walleij at linaro.org>:
>
> The Tosa device (Sharp SL-6000) has a mishmash driver set-up
> for the Toshiba TC6393xb MFD that includes a battery charger
> and touchscreen and has some kind of relationship to the SoC
> sound driver for the AC97 codec. Other devices define a chip
> like this but seem only half-implemented, not really handling
> battery charging etc.
>
> This patch switches the Toshiba MFD device to provide GPIO
> descriptors to the battery charger and SoC codec. As a result
> some descriptors need to be moved out of the Tosa boardfile
> and new one added: all SoC GPIO resources to these drivers
> now comes from the main boardfile, while the MFD provide
> GPIOs for its portions.
>
> As a result we can request one GPIO from our own GPIO chip
> and drop two hairy callbacks into the board file.
>
> This platform badly needs to have its drivers split up and
> converted to device tree probing to handle this quite complex
> relationship in an orderly manner. I just do my best in solving
> the GPIO descriptor part of the puzzle. Please don't ask me
> to fix everything that is wrong with these driver to todays
> standards, I am just trying to fix one aspect. I do try to
> use modern devres resource management and handle deferred
> probe using new functions where appropriate.
>
> Cc: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Reviewed-by: Dmitry Baryshkov <dbaryshkov at gmail.com>
Minor nit bellow.
> Cc: Dirk Opfer <dirk at opfer-online.de>
> Cc: Robert Jarzmik <robert.jarzmik at free.fr>
> Cc: Daniel Mack <daniel at zonque.org>
> Cc: Haojian Zhuang <haojian.zhuang at gmail.com>
> Cc: Lee Jones <lee.jones at linaro.org>
> Cc: Liam Girdwood <lgirdwood at gmail.com>
> Acked-by: Mark Brown <broonie at kernel.org>
> Acked-by: Sebastian Reichel <sebastian.reichel at collabora.com>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
> ChangeLog v1->v2:
> - Rebase on v5.17-rc1
> - Collect some ACKs.
> - Drop comments on includes.
> - Replace defined TOSA_GC_NAME with explicit string
> - Add a macro GPIO_LOOKUP_SINGLE() and use it in the patch
> - As we removed the only users of the .setup() and .teardown()
> callbacks in struct tc6393xb_platform_data these members
> can be removed.
> Merging strategy: please provide ACKs and I will attempt
> to merge this through the SoC tree.
> ---
> arch/arm/mach-pxa/eseries.c | 2 -
> arch/arm/mach-pxa/include/mach/tosa.h | 18 ---
> arch/arm/mach-pxa/tosa.c | 68 +++-------
> drivers/mfd/tc6393xb.c | 130 ++++++++++++++------
> drivers/power/supply/tosa_battery.c | 171 ++++++++++++++++----------
> include/linux/gpio/machine.h | 12 ++
> include/linux/mfd/tc6393xb.h | 3 -
> sound/soc/pxa/tosa.c | 20 ++-
> 8 files changed, 241 insertions(+), 183 deletions(-)
>
> diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
> index f37c44b6139d..9e9b5c78f8ad 100644
> --- a/arch/arm/mach-pxa/eseries.c
> +++ b/arch/arm/mach-pxa/eseries.c
> @@ -699,7 +699,6 @@ static struct tc6393xb_platform_data e750_tc6393xb_info = {
> .irq_base = IRQ_BOARD_START,
> .scr_pll2cr = 0x0cc1,
> .scr_gper = 0,
> - .gpio_base = -1,
> .suspend = &eseries_tmio_suspend,
> .resume = &eseries_tmio_resume,
> .enable = &eseries_tmio_enable,
> @@ -918,7 +917,6 @@ static struct tc6393xb_platform_data e800_tc6393xb_info = {
> .irq_base = IRQ_BOARD_START,
> .scr_pll2cr = 0x0cc1,
> .scr_gper = 0,
> - .gpio_base = -1,
> .suspend = &eseries_tmio_suspend,
> .resume = &eseries_tmio_resume,
> .enable = &eseries_tmio_enable,
> diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h
> index 8bfaca3a8b64..3b3efa0a0e22 100644
> --- a/arch/arm/mach-pxa/include/mach/tosa.h
> +++ b/arch/arm/mach-pxa/include/mach/tosa.h
> @@ -54,24 +54,6 @@
> /* GPIO Direction 1 : output mode / 0:input mode */
> #define TOSA_SCOOP_JC_IO_DIR (TOSA_SCOOP_JC_CARD_LIMIT_SEL)
>
> -/*
> - * TC6393XB GPIOs
> - */
> -#define TOSA_TC6393XB_GPIO_BASE (PXA_NR_BUILTIN_GPIO + 2 * 12)
> -
> -#define TOSA_GPIO_TG_ON (TOSA_TC6393XB_GPIO_BASE + 0)
> -#define TOSA_GPIO_L_MUTE (TOSA_TC6393XB_GPIO_BASE + 1)
> -#define TOSA_GPIO_BL_C20MA (TOSA_TC6393XB_GPIO_BASE + 3)
> -#define TOSA_GPIO_CARD_VCC_ON (TOSA_TC6393XB_GPIO_BASE + 4)
> -#define TOSA_GPIO_CHARGE_OFF (TOSA_TC6393XB_GPIO_BASE + 6)
> -#define TOSA_GPIO_CHARGE_OFF_JC (TOSA_TC6393XB_GPIO_BASE + 7)
> -#define TOSA_GPIO_BAT0_V_ON (TOSA_TC6393XB_GPIO_BASE + 9)
> -#define TOSA_GPIO_BAT1_V_ON (TOSA_TC6393XB_GPIO_BASE + 10)
> -#define TOSA_GPIO_BU_CHRG_ON (TOSA_TC6393XB_GPIO_BASE + 11)
> -#define TOSA_GPIO_BAT_SW_ON (TOSA_TC6393XB_GPIO_BASE + 12)
> -#define TOSA_GPIO_BAT0_TH_ON (TOSA_TC6393XB_GPIO_BASE + 14)
> -#define TOSA_GPIO_BAT1_TH_ON (TOSA_TC6393XB_GPIO_BASE + 15)
> -
> /*
> * PXA GPIOs
> */
> diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
> index 431709725d02..bead2ff44d3e 100644
> --- a/arch/arm/mach-pxa/tosa.c
> +++ b/arch/arm/mach-pxa/tosa.c
> @@ -616,6 +616,22 @@ static struct resource tc6393xb_resources[] = {
> },
> };
>
> +static struct gpiod_lookup_table tosa_battery_gpio_table = {
> + .dev_id = "wm97xx-battery",
> + .table = {
> + GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_BAT0_CRG,
> + "main battery full", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_BAT1_CRG,
> + "jacket battery full", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_BAT0_LOW,
> + "main battery low", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_BAT1_LOW,
> + "jacket battery low", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_JACKET_DETECT,
> + "jacket detect", GPIO_ACTIVE_HIGH),
> + { },
> + },
> +};
>
> static int tosa_tc6393xb_enable(struct platform_device *dev)
> {
> @@ -709,31 +725,6 @@ static struct tmio_nand_data tosa_tc6393xb_nand_config = {
> .part_parsers = probes,
> };
>
> -static int tosa_tc6393xb_setup(struct platform_device *dev)
> -{
> - int rc;
> -
> - rc = gpio_request(TOSA_GPIO_CARD_VCC_ON, "CARD_VCC_ON");
> - if (rc)
> - goto err_req;
> -
> - rc = gpio_direction_output(TOSA_GPIO_CARD_VCC_ON, 1);
> - if (rc)
> - goto err_dir;
> -
> - return rc;
> -
> -err_dir:
> - gpio_free(TOSA_GPIO_CARD_VCC_ON);
> -err_req:
> - return rc;
> -}
> -
> -static void tosa_tc6393xb_teardown(struct platform_device *dev)
> -{
> - gpio_free(TOSA_GPIO_CARD_VCC_ON);
> -}
> -
> #ifdef CONFIG_MFD_TC6393XB
> static struct fb_videomode tosa_tc6393xb_lcd_mode[] = {
> {
> @@ -778,9 +769,6 @@ static struct tc6393xb_platform_data tosa_tc6393xb_data = {
> .scr_gper = 0x3300,
>
> .irq_base = IRQ_BOARD_START,
> - .gpio_base = TOSA_TC6393XB_GPIO_BASE,
> - .setup = tosa_tc6393xb_setup,
> - .teardown = tosa_tc6393xb_teardown,
>
> .enable = tosa_tc6393xb_enable,
> .disable = tosa_tc6393xb_disable,
> @@ -821,26 +809,6 @@ static struct pxa2xx_spi_controller pxa_ssp_master_info = {
> .num_chipselect = 1,
> };
>
> -static struct gpiod_lookup_table tosa_lcd_gpio_table = {
> - .dev_id = "spi2.0",
> - .table = {
> - GPIO_LOOKUP("tc6393xb",
> - TOSA_GPIO_TG_ON - TOSA_TC6393XB_GPIO_BASE,
> - "tg #pwr", GPIO_ACTIVE_HIGH),
> - { },
> - },
> -};
> -
> -static struct gpiod_lookup_table tosa_lcd_bl_gpio_table = {
> - .dev_id = "i2c-tosa-bl",
> - .table = {
> - GPIO_LOOKUP("tc6393xb",
> - TOSA_GPIO_BL_C20MA - TOSA_TC6393XB_GPIO_BASE,
> - "backlight", GPIO_ACTIVE_HIGH),
> - { },
> - },
> -};
> -
> static struct spi_board_info spi_board_info[] __initdata = {
> {
> .modalias = "tosa-lcd",
> @@ -943,6 +911,8 @@ static void __init tosa_init(void)
> /* enable batt_fault */
> PMCR = 0x01;
>
> + gpiod_add_lookup_table(&tosa_battery_gpio_table);
> +
> gpiod_add_lookup_table(&tosa_mci_gpio_table);
> pxa_set_mci_info(&tosa_mci_platform_data);
> pxa_set_ficp_info(&tosa_ficp_platform_data);
> @@ -951,8 +921,6 @@ static void __init tosa_init(void)
> platform_scoop_config = &tosa_pcmcia_config;
>
> pxa2xx_set_spi_info(2, &pxa_ssp_master_info);
> - gpiod_add_lookup_table(&tosa_lcd_gpio_table);
> - gpiod_add_lookup_table(&tosa_lcd_bl_gpio_table);
> spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
>
> clk_add_alias("CLK_CK3P6MI", tc6393xb_device.name, "GPIO11_CLK", NULL);
> diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
> index 3d5b14c60e20..886006144896 100644
> --- a/drivers/mfd/tc6393xb.c
> +++ b/drivers/mfd/tc6393xb.c
> @@ -22,6 +22,8 @@
> #include <linux/mfd/tmio.h>
> #include <linux/mfd/tc6393xb.h>
> #include <linux/gpio/driver.h>
> +#include <linux/gpio/machine.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/slab.h>
>
> #define SCR_REVID 0x08 /* b Revision ID */
> @@ -87,8 +89,10 @@
>
> struct tc6393xb {
> void __iomem *scr;
> + struct device *dev;
>
> struct gpio_chip gpio;
> + struct gpio_desc *vcc_on;
>
> struct clk *clk; /* 3,6 Mhz */
>
> @@ -497,17 +501,93 @@ static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
> return 0;
> }
>
> -static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
> +/*
> + * TC6393XB GPIOs as used on TOSA, are the only user of this chip.
> + * The use of GPIOs 5, 8 and 14 is unknown.
2, 5, 8, 13 are not connected.
> + */
> +#define TOSA_GPIO_TG_ON 0
> +#define TOSA_GPIO_L_MUTE 1
> +#define TOSA_GPIO_BL_C20MA 3
> +#define TOSA_GPIO_CARD_VCC_ON 4
> +#define TOSA_GPIO_CHARGE_OFF 6
> +#define TOSA_GPIO_CHARGE_OFF_JC 7
> +#define TOSA_GPIO_BAT0_V_ON 9
> +#define TOSA_GPIO_BAT1_V_ON 10
> +#define TOSA_GPIO_BU_CHRG_ON 11
> +#define TOSA_GPIO_BAT_SW_ON 12
> +#define TOSA_GPIO_BAT0_TH_ON 14
> +#define TOSA_GPIO_BAT1_TH_ON 15
> +
> +
> +GPIO_LOOKUP_SINGLE(tosa_lcd_gpio_lookup, "spi2.0", "tc6393xb",
> + TOSA_GPIO_TG_ON, "tg #pwr", GPIO_ACTIVE_HIGH);
> +
> +GPIO_LOOKUP_SINGLE(tosa_lcd_bl_gpio_lookup, "i2c-tos-bl", "tc6393xb",
> + TOSA_GPIO_BL_C20MA, "backlight", GPIO_ACTIVE_HIGH);
> +
> +GPIO_LOOKUP_SINGLE(tosa_audio_gpio_lookup, "tosa-audio", "tc6393xb",
> + TOSA_GPIO_L_MUTE, NULL, GPIO_ACTIVE_HIGH);
> +
> +static struct gpiod_lookup_table tosa_battery_gpio_lookup = {
> + .dev_id = "wm97xx-battery",
> + .table = {
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_CHARGE_OFF,
> + "main charge off", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_CHARGE_OFF_JC,
> + "jacket charge off", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT0_V_ON,
> + "main battery", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT1_V_ON,
> + "jacket battery", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BU_CHRG_ON,
> + "backup battery", GPIO_ACTIVE_HIGH),
> + /* BAT1 and BAT0 thermistors appear to be swapped */
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT1_TH_ON,
> + "main battery temp", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT0_TH_ON,
> + "jacket battery temp", GPIO_ACTIVE_HIGH),
> + GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT_SW_ON,
> + "battery switch", GPIO_ACTIVE_HIGH),
> + { },
> + },
> +};
> +
> +static struct gpiod_lookup_table *tc6393xb_gpio_lookups[] = {
> + &tosa_lcd_gpio_lookup,
> + &tosa_lcd_bl_gpio_lookup,
> + &tosa_audio_gpio_lookup,
> + &tosa_battery_gpio_lookup,
> +};
> +
> +static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb)
> {
> - tc6393xb->gpio.label = "tc6393xb";
> - tc6393xb->gpio.base = gpio_base;
> - tc6393xb->gpio.ngpio = 16;
> - tc6393xb->gpio.set = tc6393xb_gpio_set;
> - tc6393xb->gpio.get = tc6393xb_gpio_get;
> - tc6393xb->gpio.direction_input = tc6393xb_gpio_direction_input;
> - tc6393xb->gpio.direction_output = tc6393xb_gpio_direction_output;
> -
> - return gpiochip_add_data(&tc6393xb->gpio, tc6393xb);
> + struct gpio_chip *gc = &tc6393xb->gpio;
> + struct device *dev = tc6393xb->dev;
> + int ret;
> +
> + gc->label = "tc6393xb";
> + gc->base = -1; /* Dynamic allocation */
> + gc->ngpio = 16;
> + gc->set = tc6393xb_gpio_set;
> + gc->get = tc6393xb_gpio_get;
> + gc->direction_input = tc6393xb_gpio_direction_input;
> + gc->direction_output = tc6393xb_gpio_direction_output;
> +
> + ret = devm_gpiochip_add_data(dev, gc, tc6393xb);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to add GPIO chip\n");
> +
> + /* Register descriptor look-ups for consumers */
> + gpiod_add_lookup_tables(tc6393xb_gpio_lookups, ARRAY_SIZE(tc6393xb_gpio_lookups));
> +
> + /* Request some of our own GPIOs */
> + tc6393xb->vcc_on = gpiochip_request_own_desc(gc, TOSA_GPIO_CARD_VCC_ON, "VCC ON",
> + GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH);
> + if (IS_ERR(tc6393xb->vcc_on))
> + return dev_err_probe(dev, PTR_ERR(tc6393xb->vcc_on),
> + "failed to request VCC ON GPIO\n");
> +
> + return 0;
> }
>
> /*--------------------------------------------------------------------------*/
> @@ -617,6 +697,7 @@ static int tc6393xb_probe(struct platform_device *dev)
> ret = -ENOMEM;
> goto err_kzalloc;
> }
> + tc6393xb->dev = &dev->dev;
>
> raw_spin_lock_init(&tc6393xb->lock);
>
> @@ -676,22 +757,12 @@ static int tc6393xb_probe(struct platform_device *dev)
> tmio_ioread8(tc6393xb->scr + SCR_REVID),
> (unsigned long) iomem->start, tc6393xb->irq);
>
> - tc6393xb->gpio.base = -1;
> -
> - if (tcpd->gpio_base >= 0) {
> - ret = tc6393xb_register_gpio(tc6393xb, tcpd->gpio_base);
> - if (ret)
> - goto err_gpio_add;
> - }
> + ret = tc6393xb_register_gpio(tc6393xb);
> + if (ret)
> + goto err_gpio_add;
>
> tc6393xb_attach_irq(dev);
>
> - if (tcpd->setup) {
> - ret = tcpd->setup(dev);
> - if (ret)
> - goto err_setup;
> - }
> -
> tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tcpd->nand_data;
> tc6393xb_cells[TC6393XB_CELL_NAND].pdata_size =
> sizeof(*tcpd->nand_data);
> @@ -705,15 +776,8 @@ static int tc6393xb_probe(struct platform_device *dev)
> if (!ret)
> return 0;
>
> - if (tcpd->teardown)
> - tcpd->teardown(dev);
> -
> -err_setup:
> tc6393xb_detach_irq(dev);
> -
> err_gpio_add:
> - if (tc6393xb->gpio.base != -1)
> - gpiochip_remove(&tc6393xb->gpio);
> tcpd->disable(dev);
> err_enable:
> clk_disable_unprepare(tc6393xb->clk);
> @@ -738,14 +802,8 @@ static int tc6393xb_remove(struct platform_device *dev)
>
> mfd_remove_devices(&dev->dev);
>
> - if (tcpd->teardown)
> - tcpd->teardown(dev);
> -
> tc6393xb_detach_irq(dev);
>
> - if (tc6393xb->gpio.base != -1)
> - gpiochip_remove(&tc6393xb->gpio);
> -
> ret = tcpd->disable(dev);
> clk_disable_unprepare(tc6393xb->clk);
> iounmap(tc6393xb->scr);
> diff --git a/drivers/power/supply/tosa_battery.c b/drivers/power/supply/tosa_battery.c
> index 32cc31cd4761..272d3ee44769 100644
> --- a/drivers/power/supply/tosa_battery.c
> +++ b/drivers/power/supply/tosa_battery.c
> @@ -12,7 +12,7 @@
> #include <linux/delay.h>
> #include <linux/spinlock.h>
> #include <linux/interrupt.h>
> -#include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
>
> #include <asm/mach-types.h>
> #include <mach/tosa.h>
> @@ -28,22 +28,23 @@ struct tosa_bat {
> struct mutex work_lock; /* protects data */
>
> bool (*is_present)(struct tosa_bat *bat);
> - int gpio_full;
> - int gpio_charge_off;
> + struct gpio_desc *gpiod_full;
> + struct gpio_desc *gpiod_charge_off;
>
> int technology;
>
> - int gpio_bat;
> + struct gpio_desc *gpiod_bat;
> int adc_bat;
> int adc_bat_divider;
> int bat_max;
> int bat_min;
>
> - int gpio_temp;
> + struct gpio_desc *gpiod_temp;
> int adc_temp;
> int adc_temp_divider;
> };
>
> +static struct gpio_desc *jacket_detect;
> static struct tosa_bat tosa_bat_main;
> static struct tosa_bat tosa_bat_jacket;
>
> @@ -51,15 +52,15 @@ static unsigned long tosa_read_bat(struct tosa_bat *bat)
> {
> unsigned long value = 0;
>
> - if (bat->gpio_bat < 0 || bat->adc_bat < 0)
> + if (!bat->gpiod_bat || bat->adc_bat < 0)
> return 0;
>
> mutex_lock(&bat_lock);
> - gpio_set_value(bat->gpio_bat, 1);
> + gpiod_set_value(bat->gpiod_bat, 1);
> msleep(5);
> value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy->dev.parent),
> bat->adc_bat);
> - gpio_set_value(bat->gpio_bat, 0);
> + gpiod_set_value(bat->gpiod_bat, 0);
> mutex_unlock(&bat_lock);
>
> value = value * 1000000 / bat->adc_bat_divider;
> @@ -71,15 +72,15 @@ static unsigned long tosa_read_temp(struct tosa_bat *bat)
> {
> unsigned long value = 0;
>
> - if (bat->gpio_temp < 0 || bat->adc_temp < 0)
> + if (!bat->gpiod_temp || bat->adc_temp < 0)
> return 0;
>
> mutex_lock(&bat_lock);
> - gpio_set_value(bat->gpio_temp, 1);
> + gpiod_set_value(bat->gpiod_temp, 1);
> msleep(5);
> value = wm97xx_read_aux_adc(dev_get_drvdata(bat->psy->dev.parent),
> bat->adc_temp);
> - gpio_set_value(bat->gpio_temp, 0);
> + gpiod_set_value(bat->gpiod_temp, 0);
> mutex_unlock(&bat_lock);
>
> value = value * 10000 / bat->adc_temp_divider;
> @@ -136,7 +137,7 @@ static int tosa_bat_get_property(struct power_supply *psy,
>
> static bool tosa_jacket_bat_is_present(struct tosa_bat *bat)
> {
> - return gpio_get_value(TOSA_GPIO_JACKET_DETECT) == 0;
> + return gpiod_get_value(jacket_detect) == 0;
> }
>
> static void tosa_bat_external_power_changed(struct power_supply *psy)
> @@ -166,23 +167,23 @@ static void tosa_bat_update(struct tosa_bat *bat)
> bat->full_chrg = -1;
> } else if (power_supply_am_i_supplied(psy)) {
> if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) {
> - gpio_set_value(bat->gpio_charge_off, 0);
> + gpiod_set_value(bat->gpiod_charge_off, 0);
> mdelay(15);
> }
>
> - if (gpio_get_value(bat->gpio_full)) {
> + if (gpiod_get_value(bat->gpiod_full)) {
> if (old == POWER_SUPPLY_STATUS_CHARGING ||
> bat->full_chrg == -1)
> bat->full_chrg = tosa_read_bat(bat);
>
> - gpio_set_value(bat->gpio_charge_off, 1);
> + gpiod_set_value(bat->gpiod_charge_off, 1);
> bat->status = POWER_SUPPLY_STATUS_FULL;
> } else {
> - gpio_set_value(bat->gpio_charge_off, 0);
> + gpiod_set_value(bat->gpiod_charge_off, 0);
> bat->status = POWER_SUPPLY_STATUS_CHARGING;
> }
> } else {
> - gpio_set_value(bat->gpio_charge_off, 1);
> + gpiod_set_value(bat->gpiod_charge_off, 1);
> bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
> }
>
> @@ -251,18 +252,18 @@ static struct tosa_bat tosa_bat_main = {
> .full_chrg = -1,
> .psy = NULL,
>
> - .gpio_full = TOSA_GPIO_BAT0_CRG,
> - .gpio_charge_off = TOSA_GPIO_CHARGE_OFF,
> + .gpiod_full = NULL,
> + .gpiod_charge_off = NULL,
>
> .technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
>
> - .gpio_bat = TOSA_GPIO_BAT0_V_ON,
> + .gpiod_bat = NULL,
> .adc_bat = WM97XX_AUX_ID3,
> .adc_bat_divider = 414,
> .bat_max = 4310000,
> .bat_min = 1551 * 1000000 / 414,
>
> - .gpio_temp = TOSA_GPIO_BAT1_TH_ON,
> + .gpiod_temp = NULL,
> .adc_temp = WM97XX_AUX_ID2,
> .adc_temp_divider = 10000,
> };
> @@ -273,18 +274,18 @@ static struct tosa_bat tosa_bat_jacket = {
> .psy = NULL,
>
> .is_present = tosa_jacket_bat_is_present,
> - .gpio_full = TOSA_GPIO_BAT1_CRG,
> - .gpio_charge_off = TOSA_GPIO_CHARGE_OFF_JC,
> + .gpiod_full = NULL,
> + .gpiod_charge_off = NULL,
>
> .technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
>
> - .gpio_bat = TOSA_GPIO_BAT1_V_ON,
> + .gpiod_bat = NULL,
> .adc_bat = WM97XX_AUX_ID3,
> .adc_bat_divider = 414,
> .bat_max = 4310000,
> .bat_min = 1551 * 1000000 / 414,
>
> - .gpio_temp = TOSA_GPIO_BAT0_TH_ON,
> + .gpiod_temp = NULL,
> .adc_temp = WM97XX_AUX_ID2,
> .adc_temp_divider = 10000,
> };
> @@ -294,36 +295,20 @@ static struct tosa_bat tosa_bat_bu = {
> .full_chrg = -1,
> .psy = NULL,
>
> - .gpio_full = -1,
> - .gpio_charge_off = -1,
> + .gpiod_full = NULL,
> + .gpiod_charge_off = NULL,
>
> .technology = POWER_SUPPLY_TECHNOLOGY_LiMn,
>
> - .gpio_bat = TOSA_GPIO_BU_CHRG_ON,
> + .gpiod_bat = NULL,
> .adc_bat = WM97XX_AUX_ID4,
> .adc_bat_divider = 1266,
>
> - .gpio_temp = -1,
> + .gpiod_temp = NULL,
> .adc_temp = -1,
> .adc_temp_divider = -1,
> };
>
> -static struct gpio tosa_bat_gpios[] = {
> - { TOSA_GPIO_CHARGE_OFF, GPIOF_OUT_INIT_HIGH, "main charge off" },
> - { TOSA_GPIO_CHARGE_OFF_JC, GPIOF_OUT_INIT_HIGH, "jacket charge off" },
> - { TOSA_GPIO_BAT_SW_ON, GPIOF_OUT_INIT_LOW, "battery switch" },
> - { TOSA_GPIO_BAT0_V_ON, GPIOF_OUT_INIT_LOW, "main battery" },
> - { TOSA_GPIO_BAT1_V_ON, GPIOF_OUT_INIT_LOW, "jacket battery" },
> - { TOSA_GPIO_BAT1_TH_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
> - { TOSA_GPIO_BAT0_TH_ON, GPIOF_OUT_INIT_LOW, "jacket battery temp" },
> - { TOSA_GPIO_BU_CHRG_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
> - { TOSA_GPIO_BAT0_CRG, GPIOF_IN, "main battery full" },
> - { TOSA_GPIO_BAT1_CRG, GPIOF_IN, "jacket battery full" },
> - { TOSA_GPIO_BAT0_LOW, GPIOF_IN, "main battery low" },
> - { TOSA_GPIO_BAT1_LOW, GPIOF_IN, "jacket battery low" },
> - { TOSA_GPIO_JACKET_DETECT, GPIOF_IN, "jacket detect" },
> -};
> -
> #ifdef CONFIG_PM
> static int tosa_bat_suspend(struct platform_device *dev, pm_message_t state)
> {
> @@ -343,19 +328,83 @@ static int tosa_bat_resume(struct platform_device *dev)
> #define tosa_bat_resume NULL
> #endif
>
> -static int tosa_bat_probe(struct platform_device *dev)
> +static int tosa_bat_probe(struct platform_device *pdev)
> {
> int ret;
> struct power_supply_config main_psy_cfg = {},
> jacket_psy_cfg = {},
> bu_psy_cfg = {};
> + struct device *dev = &pdev->dev;
> + struct gpio_desc *dummy;
>
> if (!machine_is_tosa())
> return -ENODEV;
>
> - ret = gpio_request_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
> - if (ret)
> - return ret;
> + /* Main charging control GPIOs */
> + tosa_bat_main.gpiod_charge_off = devm_gpiod_get(dev, "main charge off", GPIOD_OUT_HIGH);
> + if (IS_ERR(tosa_bat_main.gpiod_charge_off))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_main.gpiod_charge_off),
> + "no main charger GPIO\n");
> + tosa_bat_jacket.gpiod_charge_off = devm_gpiod_get(dev, "jacket charge off", GPIOD_OUT_HIGH);
> + if (IS_ERR(tosa_bat_jacket.gpiod_charge_off))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_jacket.gpiod_charge_off),
> + "no jacket charger GPIO\n");
> +
> + /* Per-battery output check (routes battery voltage to ADC) */
> + tosa_bat_main.gpiod_bat = devm_gpiod_get(dev, "main battery", GPIOD_OUT_LOW);
> + if (IS_ERR(tosa_bat_main.gpiod_bat))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_main.gpiod_bat),
> + "no main battery GPIO\n");
> + tosa_bat_jacket.gpiod_bat = devm_gpiod_get(dev, "jacket battery", GPIOD_OUT_LOW);
> + if (IS_ERR(tosa_bat_jacket.gpiod_bat))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_jacket.gpiod_bat),
> + "no jacket battery GPIO\n");
> + tosa_bat_bu.gpiod_bat = devm_gpiod_get(dev, "backup battery", GPIOD_OUT_LOW);
> + if (IS_ERR(tosa_bat_bu.gpiod_bat))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_bu.gpiod_bat),
> + "no backup battery GPIO\n");
> +
> + /* Battery full detect GPIOs (using PXA SoC GPIOs) */
> + tosa_bat_main.gpiod_full = devm_gpiod_get(dev, "main battery full", GPIOD_IN);
> + if (IS_ERR(tosa_bat_main.gpiod_full))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_main.gpiod_full),
> + "no main battery full GPIO\n");
> + tosa_bat_jacket.gpiod_full = devm_gpiod_get(dev, "jacket battery full", GPIOD_IN);
> + if (IS_ERR(tosa_bat_jacket.gpiod_full))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_jacket.gpiod_full),
> + "no jacket battery full GPIO\n");
> +
> + /* Battery temperature GPIOs (routes thermistor voltage to ADC) */
> + tosa_bat_main.gpiod_temp = devm_gpiod_get(dev, "main battery temp", GPIOD_OUT_LOW);
> + if (IS_ERR(tosa_bat_main.gpiod_temp))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_main.gpiod_temp),
> + "no main battery temp GPIO\n");
> + tosa_bat_jacket.gpiod_temp = devm_gpiod_get(dev, "jacket battery temp", GPIOD_OUT_LOW);
> + if (IS_ERR(tosa_bat_jacket.gpiod_temp))
> + return dev_err_probe(dev, PTR_ERR(tosa_bat_jacket.gpiod_temp),
> + "no jacket battery temp GPIO\n");
> +
> + /* Jacket detect GPIO */
> + jacket_detect = devm_gpiod_get(dev, "jacket detect", GPIOD_IN);
> + if (IS_ERR(jacket_detect))
> + return dev_err_probe(dev, PTR_ERR(jacket_detect),
> + "no jacket detect GPIO\n");
> +
> + /* Battery low indication GPIOs (not used, we just request them) */
> + dummy = devm_gpiod_get(dev, "main battery low", GPIOD_IN);
> + if (IS_ERR(dummy))
> + return dev_err_probe(dev, PTR_ERR(dummy),
> + "no main battery low GPIO\n");
> + dummy = devm_gpiod_get(dev, "jacket battery low", GPIOD_IN);
> + if (IS_ERR(dummy))
> + return dev_err_probe(dev, PTR_ERR(dummy),
> + "no jacket battery low GPIO\n");
> +
> + /* Battery switch GPIO (not used just requested) */
> + dummy = devm_gpiod_get(dev, "battery switch", GPIOD_OUT_LOW);
> + if (IS_ERR(dummy))
> + return dev_err_probe(dev, PTR_ERR(dummy),
> + "no battery switch GPIO\n");
>
> mutex_init(&tosa_bat_main.work_lock);
> mutex_init(&tosa_bat_jacket.work_lock);
> @@ -363,7 +412,7 @@ static int tosa_bat_probe(struct platform_device *dev)
> INIT_WORK(&bat_work, tosa_bat_work);
>
> main_psy_cfg.drv_data = &tosa_bat_main;
> - tosa_bat_main.psy = power_supply_register(&dev->dev,
> + tosa_bat_main.psy = power_supply_register(dev,
> &tosa_bat_main_desc,
> &main_psy_cfg);
> if (IS_ERR(tosa_bat_main.psy)) {
> @@ -372,7 +421,7 @@ static int tosa_bat_probe(struct platform_device *dev)
> }
>
> jacket_psy_cfg.drv_data = &tosa_bat_jacket;
> - tosa_bat_jacket.psy = power_supply_register(&dev->dev,
> + tosa_bat_jacket.psy = power_supply_register(dev,
> &tosa_bat_jacket_desc,
> &jacket_psy_cfg);
> if (IS_ERR(tosa_bat_jacket.psy)) {
> @@ -381,28 +430,28 @@ static int tosa_bat_probe(struct platform_device *dev)
> }
>
> bu_psy_cfg.drv_data = &tosa_bat_bu;
> - tosa_bat_bu.psy = power_supply_register(&dev->dev, &tosa_bat_bu_desc,
> + tosa_bat_bu.psy = power_supply_register(dev, &tosa_bat_bu_desc,
> &bu_psy_cfg);
> if (IS_ERR(tosa_bat_bu.psy)) {
> ret = PTR_ERR(tosa_bat_bu.psy);
> goto err_psy_reg_bu;
> }
>
> - ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG),
> + ret = request_irq(gpiod_to_irq(tosa_bat_main.gpiod_full),
> tosa_bat_gpio_isr,
> IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
> "main full", &tosa_bat_main);
> if (ret)
> goto err_req_main;
>
> - ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG),
> + ret = request_irq(gpiod_to_irq(tosa_bat_jacket.gpiod_full),
> tosa_bat_gpio_isr,
> IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
> "jacket full", &tosa_bat_jacket);
> if (ret)
> goto err_req_jacket;
>
> - ret = request_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT),
> + ret = request_irq(gpiod_to_irq(jacket_detect),
> tosa_bat_gpio_isr,
> IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
> "jacket detect", &tosa_bat_jacket);
> @@ -411,9 +460,9 @@ static int tosa_bat_probe(struct platform_device *dev)
> return 0;
> }
>
> - free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
> + free_irq(gpiod_to_irq(tosa_bat_jacket.gpiod_full), &tosa_bat_jacket);
> err_req_jacket:
> - free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
> + free_irq(gpiod_to_irq(tosa_bat_main.gpiod_full), &tosa_bat_main);
> err_req_main:
> power_supply_unregister(tosa_bat_bu.psy);
> err_psy_reg_bu:
> @@ -425,15 +474,14 @@ static int tosa_bat_probe(struct platform_device *dev)
> /* see comment in tosa_bat_remove */
> cancel_work_sync(&bat_work);
>
> - gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
> return ret;
> }
>
> static int tosa_bat_remove(struct platform_device *dev)
> {
> - free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
> - free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
> - free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
> + free_irq(gpiod_to_irq(jacket_detect), &tosa_bat_jacket);
> + free_irq(gpiod_to_irq(tosa_bat_jacket.gpiod_full), &tosa_bat_jacket);
> + free_irq(gpiod_to_irq(tosa_bat_main.gpiod_full), &tosa_bat_main);
>
> power_supply_unregister(tosa_bat_bu.psy);
> power_supply_unregister(tosa_bat_jacket.psy);
> @@ -445,7 +493,6 @@ static int tosa_bat_remove(struct platform_device *dev)
> * unregistered now.
> */
> cancel_work_sync(&bat_work);
> - gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
> return 0;
> }
>
> diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h
> index 2647dd10b541..4d55da28e664 100644
> --- a/include/linux/gpio/machine.h
> +++ b/include/linux/gpio/machine.h
> @@ -63,6 +63,18 @@ struct gpiod_hog {
> int dflags;
> };
>
> +/*
> + * Helper for lookup tables with just one single lookup for a device.
> + */
> +#define GPIO_LOOKUP_SINGLE(_name, _dev_id, _key, _chip_hwnum, _con_id, _flags) \
> +static struct gpiod_lookup_table _name = { \
> + .dev_id = _dev_id, \
> + .table = { \
> + GPIO_LOOKUP(_key, _chip_hwnum, _con_id, _flags), \
> + {}, \
> + }, \
> +}
> +
> /*
> * Simple definition of a single GPIO under a con_id
> */
> diff --git a/include/linux/mfd/tc6393xb.h b/include/linux/mfd/tc6393xb.h
> index fcc8e74f0e8d..d336c541b7df 100644
> --- a/include/linux/mfd/tc6393xb.h
> +++ b/include/linux/mfd/tc6393xb.h
> @@ -27,9 +27,6 @@ struct tc6393xb_platform_data {
> int (*resume)(struct platform_device *dev);
>
> int irq_base; /* base for subdevice irqs */
> - int gpio_base;
> - int (*setup)(struct platform_device *dev);
> - void (*teardown)(struct platform_device *dev);
>
> struct tmio_nand_data *nand_data;
> struct tmio_fb_data *fb_data;
> diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
> index 3b40b5fa5de7..c2b05896e284 100644
> --- a/sound/soc/pxa/tosa.c
> +++ b/sound/soc/pxa/tosa.c
> @@ -16,7 +16,7 @@
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/device.h>
> -#include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
>
> #include <sound/core.h>
> #include <sound/pcm.h>
> @@ -33,6 +33,7 @@
> #define TOSA_SPK_ON 0
> #define TOSA_SPK_OFF 1
>
> +static struct gpio_desc *tosa_mute;
> static int tosa_jack_func;
> static int tosa_spk_func;
>
> @@ -128,7 +129,7 @@ static int tosa_set_spk(struct snd_kcontrol *kcontrol,
> static int tosa_hp_event(struct snd_soc_dapm_widget *w,
> struct snd_kcontrol *k, int event)
> {
> - gpio_set_value(TOSA_GPIO_L_MUTE, SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0);
> + gpiod_set_value(tosa_mute, SND_SOC_DAPM_EVENT_ON(event) ? 1 : 0);
> return 0;
> }
>
> @@ -222,8 +223,11 @@ static int tosa_probe(struct platform_device *pdev)
> struct snd_soc_card *card = ⤩
> int ret;
>
> - ret = gpio_request_one(TOSA_GPIO_L_MUTE, GPIOF_OUT_INIT_LOW,
> - "Headphone Jack");
> + tosa_mute = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW);
> + if (IS_ERR(tosa_mute))
> + return dev_err_probe(&pdev->dev, PTR_ERR(tosa_mute),
> + "failed to get L_MUTE GPIO\n");
> + gpiod_set_consumer_name(tosa_mute, "Headphone Jack");
> if (ret)
> return ret;
>
> @@ -233,24 +237,16 @@ static int tosa_probe(struct platform_device *pdev)
> if (ret) {
> dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
> ret);
> - gpio_free(TOSA_GPIO_L_MUTE);
> }
> return ret;
> }
>
> -static int tosa_remove(struct platform_device *pdev)
> -{
> - gpio_free(TOSA_GPIO_L_MUTE);
> - return 0;
> -}
> -
> static struct platform_driver tosa_driver = {
> .driver = {
> .name = "tosa-audio",
> .pm = &snd_soc_pm_ops,
> },
> .probe = tosa_probe,
> - .remove = tosa_remove,
> };
>
> module_platform_driver(tosa_driver);
> --
> 2.34.1
>
--
With best wishes
Dmitry
More information about the linux-arm-kernel
mailing list