Commit 7da68c64 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'rpi-poe-v5.13' of...

Merge tag 'rpi-poe-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/nsaenz/linux-rpi into arm/drivers

Raspberry Pi driver updates for v5.13:
  - Fix-up all RPi firmware drivers so as for unbind to happen in an
    orderly fashion
  - Support for RPi's PoE hat PWM bus

* tag 'rpi-poe-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/nsaenz/linux-rpi:
  pwm: Add Raspberry Pi Firmware based PWM bus
  dt-bindings: pwm: Add binding for RPi firmware PWM bus
  input: raspberrypi-ts: Release firmware handle when not needed
  staging: vchiq: Release firmware handle on unbind
  soc: bcm: raspberrypi-power: Release firmware handle on unbind
  reset: raspberrypi: Release firmware handle on unbind
  gpio: raspberrypi-exp: Release firmware handle on unbind
  clk: bcm: rpi: Release firmware handle on unbind
  firmware: raspberrypi: Introduce devm_rpi_firmware_get()
  firmware: raspberrypi: Keep count of all consumers

Link: https://lore.kernel.org/r/20210322174232.29549-1-nsaenz@kernel.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 56a6867b 79caa362
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -64,6 +64,21 @@ properties:
      - compatible
      - "#reset-cells"

  pwm:
    type: object

    properties:
      compatible:
        const: raspberrypi,firmware-poe-pwm

      "#pwm-cells":
        # See pwm.yaml in this directory for a description of the cells format.
        const: 2

    required:
      - compatible
      - "#pwm-cells"

    additionalProperties: false

required:
@@ -87,5 +102,10 @@ examples:
            compatible = "raspberrypi,firmware-reset";
            #reset-cells = <1>;
        };

        pwm: pwm {
            compatible = "raspberrypi,firmware-poe-pwm";
            #pwm-cells = <2>;
        };
    };
...
+1 −1
Original line number Diff line number Diff line
@@ -314,7 +314,7 @@ static int raspberrypi_clk_probe(struct platform_device *pdev)
		return -ENOENT;
	}

	firmware = rpi_firmware_get(firmware_node);
	firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node);
	of_node_put(firmware_node);
	if (!firmware)
		return -EPROBE_DEFER;
+66 −3
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 */

#include <linux/dma-mapping.h>
#include <linux/kref.h>
#include <linux/mailbox_client.h>
#include <linux/module.h>
#include <linux/of_platform.h>
@@ -27,6 +28,8 @@ struct rpi_firmware {
	struct mbox_chan *chan; /* The property channel. */
	struct completion c;
	u32 enabled;

	struct kref consumers;
};

static DEFINE_MUTEX(transaction_lock);
@@ -225,12 +228,38 @@ static void rpi_register_clk_driver(struct device *dev)
						-1, NULL, 0);
}

static void rpi_firmware_delete(struct kref *kref)
{
	struct rpi_firmware *fw = container_of(kref, struct rpi_firmware,
					       consumers);

	mbox_free_channel(fw->chan);
	kfree(fw);
}

void rpi_firmware_put(struct rpi_firmware *fw)
{
	kref_put(&fw->consumers, rpi_firmware_delete);
}
EXPORT_SYMBOL_GPL(rpi_firmware_put);

static void devm_rpi_firmware_put(void *data)
{
	struct rpi_firmware *fw = data;

	rpi_firmware_put(fw);
}

static int rpi_firmware_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct rpi_firmware *fw;

	fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
	/*
	 * Memory will be freed by rpi_firmware_delete() once all users have
	 * released their firmware handles. Don't use devm_kzalloc() here.
	 */
	fw = kzalloc(sizeof(*fw), GFP_KERNEL);
	if (!fw)
		return -ENOMEM;

@@ -247,6 +276,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
	}

	init_completion(&fw->c);
	kref_init(&fw->consumers);

	platform_set_drvdata(pdev, fw);

@@ -275,7 +305,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
	rpi_hwmon = NULL;
	platform_device_unregister(rpi_clk);
	rpi_clk = NULL;
	mbox_free_channel(fw->chan);

	rpi_firmware_put(fw);

	return 0;
}
@@ -284,19 +315,51 @@ static int rpi_firmware_remove(struct platform_device *pdev)
 * rpi_firmware_get - Get pointer to rpi_firmware structure.
 * @firmware_node:    Pointer to the firmware Device Tree node.
 *
 * The reference to rpi_firmware has to be released with rpi_firmware_put().
 *
 * Returns NULL is the firmware device is not ready.
 */
struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
{
	struct platform_device *pdev = of_find_device_by_node(firmware_node);
	struct rpi_firmware *fw;

	if (!pdev)
		return NULL;

	return platform_get_drvdata(pdev);
	fw = platform_get_drvdata(pdev);
	if (!fw)
		return NULL;

	if (!kref_get_unless_zero(&fw->consumers))
		return NULL;

	return fw;
}
EXPORT_SYMBOL_GPL(rpi_firmware_get);

/**
 * devm_rpi_firmware_get - Get pointer to rpi_firmware structure.
 * @firmware_node:    Pointer to the firmware Device Tree node.
 *
 * Returns NULL is the firmware device is not ready.
 */
struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
					   struct device_node *firmware_node)
{
	struct rpi_firmware *fw;

	fw = rpi_firmware_get(firmware_node);
	if (!fw)
		return NULL;

	if (devm_add_action_or_reset(dev, devm_rpi_firmware_put, fw))
		return NULL;

	return fw;
}
EXPORT_SYMBOL_GPL(devm_rpi_firmware_get);

static const struct of_device_id rpi_firmware_of_match[] = {
	{ .compatible = "raspberrypi,bcm2835-firmware", },
	{},
+1 −1
Original line number Diff line number Diff line
@@ -208,7 +208,7 @@ static int rpi_exp_gpio_probe(struct platform_device *pdev)
		return -ENOENT;
	}

	fw = rpi_firmware_get(fw_node);
	fw = devm_rpi_firmware_get(&pdev->dev, fw_node);
	of_node_put(fw_node);
	if (!fw)
		return -EPROBE_DEFER;
+1 −1
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ static int rpi_ts_probe(struct platform_device *pdev)
	touchbuf = (u32)ts->fw_regs_phys;
	error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
				      &touchbuf, sizeof(touchbuf));

	rpi_firmware_put(fw);
	if (error || touchbuf != 0) {
		dev_warn(dev, "Failed to set touchbuf, %d\n", error);
		return error;
Loading