Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Defines interfaces for interacting with the Raspberry Pi firmware's
0004  * property channel.
0005  *
0006  * Copyright © 2015 Broadcom
0007  */
0008 
0009 #include <linux/dma-mapping.h>
0010 #include <linux/kref.h>
0011 #include <linux/mailbox_client.h>
0012 #include <linux/module.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/slab.h>
0016 #include <soc/bcm2835/raspberrypi-firmware.h>
0017 
0018 #define MBOX_MSG(chan, data28)      (((data28) & ~0xf) | ((chan) & 0xf))
0019 #define MBOX_CHAN(msg)          ((msg) & 0xf)
0020 #define MBOX_DATA28(msg)        ((msg) & ~0xf)
0021 #define MBOX_CHAN_PROPERTY      8
0022 
0023 static struct platform_device *rpi_hwmon;
0024 static struct platform_device *rpi_clk;
0025 
0026 struct rpi_firmware {
0027     struct mbox_client cl;
0028     struct mbox_chan *chan; /* The property channel. */
0029     struct completion c;
0030     u32 enabled;
0031 
0032     struct kref consumers;
0033 };
0034 
0035 static DEFINE_MUTEX(transaction_lock);
0036 
0037 static void response_callback(struct mbox_client *cl, void *msg)
0038 {
0039     struct rpi_firmware *fw = container_of(cl, struct rpi_firmware, cl);
0040     complete(&fw->c);
0041 }
0042 
0043 /*
0044  * Sends a request to the firmware through the BCM2835 mailbox driver,
0045  * and synchronously waits for the reply.
0046  */
0047 static int
0048 rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data)
0049 {
0050     u32 message = MBOX_MSG(chan, data);
0051     int ret;
0052 
0053     WARN_ON(data & 0xf);
0054 
0055     mutex_lock(&transaction_lock);
0056     reinit_completion(&fw->c);
0057     ret = mbox_send_message(fw->chan, &message);
0058     if (ret >= 0) {
0059         if (wait_for_completion_timeout(&fw->c, HZ)) {
0060             ret = 0;
0061         } else {
0062             ret = -ETIMEDOUT;
0063             WARN_ONCE(1, "Firmware transaction timeout");
0064         }
0065     } else {
0066         dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret);
0067     }
0068     mutex_unlock(&transaction_lock);
0069 
0070     return ret;
0071 }
0072 
0073 /**
0074  * rpi_firmware_property_list - Submit firmware property list
0075  * @fw:     Pointer to firmware structure from rpi_firmware_get().
0076  * @data:   Buffer holding tags.
0077  * @tag_size:   Size of tags buffer.
0078  *
0079  * Submits a set of concatenated tags to the VPU firmware through the
0080  * mailbox property interface.
0081  *
0082  * The buffer header and the ending tag are added by this function and
0083  * don't need to be supplied, just the actual tags for your operation.
0084  * See struct rpi_firmware_property_tag_header for the per-tag
0085  * structure.
0086  */
0087 int rpi_firmware_property_list(struct rpi_firmware *fw,
0088                    void *data, size_t tag_size)
0089 {
0090     size_t size = tag_size + 12;
0091     u32 *buf;
0092     dma_addr_t bus_addr;
0093     int ret;
0094 
0095     /* Packets are processed a dword at a time. */
0096     if (size & 3)
0097         return -EINVAL;
0098 
0099     buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr,
0100                  GFP_ATOMIC);
0101     if (!buf)
0102         return -ENOMEM;
0103 
0104     /* The firmware will error out without parsing in this case. */
0105     WARN_ON(size >= 1024 * 1024);
0106 
0107     buf[0] = size;
0108     buf[1] = RPI_FIRMWARE_STATUS_REQUEST;
0109     memcpy(&buf[2], data, tag_size);
0110     buf[size / 4 - 1] = RPI_FIRMWARE_PROPERTY_END;
0111     wmb();
0112 
0113     ret = rpi_firmware_transaction(fw, MBOX_CHAN_PROPERTY, bus_addr);
0114 
0115     rmb();
0116     memcpy(data, &buf[2], tag_size);
0117     if (ret == 0 && buf[1] != RPI_FIRMWARE_STATUS_SUCCESS) {
0118         /*
0119          * The tag name here might not be the one causing the
0120          * error, if there were multiple tags in the request.
0121          * But single-tag is the most common, so go with it.
0122          */
0123         dev_err(fw->cl.dev, "Request 0x%08x returned status 0x%08x\n",
0124             buf[2], buf[1]);
0125         ret = -EINVAL;
0126     }
0127 
0128     dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr);
0129 
0130     return ret;
0131 }
0132 EXPORT_SYMBOL_GPL(rpi_firmware_property_list);
0133 
0134 /**
0135  * rpi_firmware_property - Submit single firmware property
0136  * @fw:     Pointer to firmware structure from rpi_firmware_get().
0137  * @tag:    One of enum_mbox_property_tag.
0138  * @tag_data:   Tag data buffer.
0139  * @buf_size:   Buffer size.
0140  *
0141  * Submits a single tag to the VPU firmware through the mailbox
0142  * property interface.
0143  *
0144  * This is a convenience wrapper around
0145  * rpi_firmware_property_list() to avoid some of the
0146  * boilerplate in property calls.
0147  */
0148 int rpi_firmware_property(struct rpi_firmware *fw,
0149               u32 tag, void *tag_data, size_t buf_size)
0150 {
0151     struct rpi_firmware_property_tag_header *header;
0152     int ret;
0153 
0154     /* Some mailboxes can use over 1k bytes. Rather than checking
0155      * size and using stack or kmalloc depending on requirements,
0156      * just use kmalloc. Mailboxes don't get called enough to worry
0157      * too much about the time taken in the allocation.
0158      */
0159     void *data = kmalloc(sizeof(*header) + buf_size, GFP_KERNEL);
0160 
0161     if (!data)
0162         return -ENOMEM;
0163 
0164     header = data;
0165     header->tag = tag;
0166     header->buf_size = buf_size;
0167     header->req_resp_size = 0;
0168     memcpy(data + sizeof(*header), tag_data, buf_size);
0169 
0170     ret = rpi_firmware_property_list(fw, data, buf_size + sizeof(*header));
0171 
0172     memcpy(tag_data, data + sizeof(*header), buf_size);
0173 
0174     kfree(data);
0175 
0176     return ret;
0177 }
0178 EXPORT_SYMBOL_GPL(rpi_firmware_property);
0179 
0180 static void
0181 rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
0182 {
0183     time64_t date_and_time;
0184     u32 packet;
0185     int ret = rpi_firmware_property(fw,
0186                     RPI_FIRMWARE_GET_FIRMWARE_REVISION,
0187                     &packet, sizeof(packet));
0188 
0189     if (ret)
0190         return;
0191 
0192     /* This is not compatible with y2038 */
0193     date_and_time = packet;
0194     dev_info(fw->cl.dev, "Attached to firmware from %ptT\n", &date_and_time);
0195 }
0196 
0197 static void
0198 rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
0199 {
0200     u32 packet;
0201     int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
0202                     &packet, sizeof(packet));
0203 
0204     if (ret)
0205         return;
0206 
0207     rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
0208                           -1, NULL, 0);
0209 }
0210 
0211 static void rpi_register_clk_driver(struct device *dev)
0212 {
0213     struct device_node *firmware;
0214 
0215     /*
0216      * Earlier DTs don't have a node for the firmware clocks but
0217      * rely on us creating a platform device by hand. If we do
0218      * have a node for the firmware clocks, just bail out here.
0219      */
0220     firmware = of_get_compatible_child(dev->of_node,
0221                        "raspberrypi,firmware-clocks");
0222     if (firmware) {
0223         of_node_put(firmware);
0224         return;
0225     }
0226 
0227     rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
0228                         -1, NULL, 0);
0229 }
0230 
0231 static void rpi_firmware_delete(struct kref *kref)
0232 {
0233     struct rpi_firmware *fw = container_of(kref, struct rpi_firmware,
0234                            consumers);
0235 
0236     mbox_free_channel(fw->chan);
0237     kfree(fw);
0238 }
0239 
0240 void rpi_firmware_put(struct rpi_firmware *fw)
0241 {
0242     kref_put(&fw->consumers, rpi_firmware_delete);
0243 }
0244 EXPORT_SYMBOL_GPL(rpi_firmware_put);
0245 
0246 static void devm_rpi_firmware_put(void *data)
0247 {
0248     struct rpi_firmware *fw = data;
0249 
0250     rpi_firmware_put(fw);
0251 }
0252 
0253 static int rpi_firmware_probe(struct platform_device *pdev)
0254 {
0255     struct device *dev = &pdev->dev;
0256     struct rpi_firmware *fw;
0257 
0258     /*
0259      * Memory will be freed by rpi_firmware_delete() once all users have
0260      * released their firmware handles. Don't use devm_kzalloc() here.
0261      */
0262     fw = kzalloc(sizeof(*fw), GFP_KERNEL);
0263     if (!fw)
0264         return -ENOMEM;
0265 
0266     fw->cl.dev = dev;
0267     fw->cl.rx_callback = response_callback;
0268     fw->cl.tx_block = true;
0269 
0270     fw->chan = mbox_request_channel(&fw->cl, 0);
0271     if (IS_ERR(fw->chan)) {
0272         int ret = PTR_ERR(fw->chan);
0273         if (ret != -EPROBE_DEFER)
0274             dev_err(dev, "Failed to get mbox channel: %d\n", ret);
0275         return ret;
0276     }
0277 
0278     init_completion(&fw->c);
0279     kref_init(&fw->consumers);
0280 
0281     platform_set_drvdata(pdev, fw);
0282 
0283     rpi_firmware_print_firmware_revision(fw);
0284     rpi_register_hwmon_driver(dev, fw);
0285     rpi_register_clk_driver(dev);
0286 
0287     return 0;
0288 }
0289 
0290 static void rpi_firmware_shutdown(struct platform_device *pdev)
0291 {
0292     struct rpi_firmware *fw = platform_get_drvdata(pdev);
0293 
0294     if (!fw)
0295         return;
0296 
0297     rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT, NULL, 0);
0298 }
0299 
0300 static int rpi_firmware_remove(struct platform_device *pdev)
0301 {
0302     struct rpi_firmware *fw = platform_get_drvdata(pdev);
0303 
0304     platform_device_unregister(rpi_hwmon);
0305     rpi_hwmon = NULL;
0306     platform_device_unregister(rpi_clk);
0307     rpi_clk = NULL;
0308 
0309     rpi_firmware_put(fw);
0310 
0311     return 0;
0312 }
0313 
0314 /**
0315  * rpi_firmware_get - Get pointer to rpi_firmware structure.
0316  * @firmware_node:    Pointer to the firmware Device Tree node.
0317  *
0318  * The reference to rpi_firmware has to be released with rpi_firmware_put().
0319  *
0320  * Returns NULL is the firmware device is not ready.
0321  */
0322 struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
0323 {
0324     struct platform_device *pdev = of_find_device_by_node(firmware_node);
0325     struct rpi_firmware *fw;
0326 
0327     if (!pdev)
0328         return NULL;
0329 
0330     fw = platform_get_drvdata(pdev);
0331     if (!fw)
0332         goto err_put_device;
0333 
0334     if (!kref_get_unless_zero(&fw->consumers))
0335         goto err_put_device;
0336 
0337     put_device(&pdev->dev);
0338 
0339     return fw;
0340 
0341 err_put_device:
0342     put_device(&pdev->dev);
0343     return NULL;
0344 }
0345 EXPORT_SYMBOL_GPL(rpi_firmware_get);
0346 
0347 /**
0348  * devm_rpi_firmware_get - Get pointer to rpi_firmware structure.
0349  * @firmware_node:    Pointer to the firmware Device Tree node.
0350  *
0351  * Returns NULL is the firmware device is not ready.
0352  */
0353 struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
0354                        struct device_node *firmware_node)
0355 {
0356     struct rpi_firmware *fw;
0357 
0358     fw = rpi_firmware_get(firmware_node);
0359     if (!fw)
0360         return NULL;
0361 
0362     if (devm_add_action_or_reset(dev, devm_rpi_firmware_put, fw))
0363         return NULL;
0364 
0365     return fw;
0366 }
0367 EXPORT_SYMBOL_GPL(devm_rpi_firmware_get);
0368 
0369 static const struct of_device_id rpi_firmware_of_match[] = {
0370     { .compatible = "raspberrypi,bcm2835-firmware", },
0371     {},
0372 };
0373 MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
0374 
0375 static struct platform_driver rpi_firmware_driver = {
0376     .driver = {
0377         .name = "raspberrypi-firmware",
0378         .of_match_table = rpi_firmware_of_match,
0379     },
0380     .probe      = rpi_firmware_probe,
0381     .shutdown   = rpi_firmware_shutdown,
0382     .remove     = rpi_firmware_remove,
0383 };
0384 module_platform_driver(rpi_firmware_driver);
0385 
0386 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
0387 MODULE_DESCRIPTION("Raspberry Pi firmware driver");
0388 MODULE_LICENSE("GPL v2");