1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * PM MFD driver for Broadcom BCM2835 4 * 5 * This driver binds to the PM block and creates the MFD device for 6 * the WDT and power drivers. 7 */ 8 9 #include <linux/delay.h> 10 #include <linux/io.h> 11 #include <linux/mfd/bcm2835-pm.h> 12 #include <linux/mfd/core.h> 13 #include <linux/module.h> 14 #include <linux/of_address.h> 15 #include <linux/of_platform.h> 16 #include <linux/platform_device.h> 17 #include <linux/types.h> 18 #include <linux/watchdog.h> 19 20 static const struct mfd_cell bcm2835_pm_devs[] = { 21 { .name = "bcm2835-wdt" }, 22 }; 23 24 static const struct mfd_cell bcm2835_power_devs[] = { 25 { .name = "bcm2835-power" }, 26 }; 27 28 static int bcm2835_pm_probe(struct platform_device *pdev) 29 { 30 struct resource *res; 31 struct device *dev = &pdev->dev; 32 struct bcm2835_pm *pm; 33 int ret; 34 35 pm = devm_kzalloc(dev, sizeof(*pm), GFP_KERNEL); 36 if (!pm) 37 return -ENOMEM; 38 platform_set_drvdata(pdev, pm); 39 40 pm->dev = dev; 41 42 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 43 pm->base = devm_ioremap_resource(dev, res); 44 if (IS_ERR(pm->base)) 45 return PTR_ERR(pm->base); 46 47 ret = devm_mfd_add_devices(dev, -1, 48 bcm2835_pm_devs, ARRAY_SIZE(bcm2835_pm_devs), 49 NULL, 0, NULL); 50 if (ret) 51 return ret; 52 53 /* We'll use the presence of the AXI ASB regs in the 54 * bcm2835-pm binding as the key for whether we can reference 55 * the full PM register range and support power domains. 56 */ 57 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 58 if (res) { 59 pm->asb = devm_ioremap_resource(dev, res); 60 if (IS_ERR(pm->asb)) 61 return PTR_ERR(pm->asb); 62 63 ret = devm_mfd_add_devices(dev, -1, 64 bcm2835_power_devs, 65 ARRAY_SIZE(bcm2835_power_devs), 66 NULL, 0, NULL); 67 if (ret) 68 return ret; 69 } 70 71 return 0; 72 } 73 74 static const struct of_device_id bcm2835_pm_of_match[] = { 75 { .compatible = "brcm,bcm2835-pm-wdt", }, 76 { .compatible = "brcm,bcm2835-pm", }, 77 {}, 78 }; 79 MODULE_DEVICE_TABLE(of, bcm2835_pm_of_match); 80 81 static struct platform_driver bcm2835_pm_driver = { 82 .probe = bcm2835_pm_probe, 83 .driver = { 84 .name = "bcm2835-pm", 85 .of_match_table = bcm2835_pm_of_match, 86 }, 87 }; 88 module_platform_driver(bcm2835_pm_driver); 89 90 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>"); 91 MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM MFD"); 92 MODULE_LICENSE("GPL"); 93