diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/ab8500-core.c | 138 | ||||
-rw-r--r-- | drivers/mfd/arizona-core.c | 6 | ||||
-rw-r--r-- | drivers/mfd/cs5535-mfd.c | 108 | ||||
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 84 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss-pci.c | 41 | ||||
-rw-r--r-- | drivers/mfd/intel-lpss.c | 2 | ||||
-rw-r--r-- | drivers/mfd/intel_soc_pmic_crc.c | 3 | ||||
-rw-r--r-- | drivers/mfd/ipaq-micro.c | 6 | ||||
-rw-r--r-- | drivers/mfd/madera-core.c | 27 | ||||
-rw-r--r-- | drivers/mfd/max77620.c | 5 | ||||
-rw-r--r-- | drivers/mfd/mfd-core.c | 118 | ||||
-rw-r--r-- | drivers/mfd/mt6397-core.c | 12 | ||||
-rw-r--r-- | drivers/mfd/qcom-spmi-pmic.c | 4 | ||||
-rw-r--r-- | drivers/mfd/rk808.c | 22 | ||||
-rw-r--r-- | drivers/mfd/rohm-bd70528.c | 17 | ||||
-rw-r--r-- | drivers/mfd/syscon.c | 1 | ||||
-rw-r--r-- | drivers/mfd/ti_am335x_tscadc.c | 2 | ||||
-rw-r--r-- | drivers/mfd/wm8998-tables.c | 12 | ||||
-rw-r--r-- | drivers/power/reset/Kconfig | 10 | ||||
-rw-r--r-- | drivers/power/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/reset/mt6323-poweroff.c | 97 | ||||
-rw-r--r-- | drivers/rtc/rtc-mt6397.c | 107 |
22 files changed, 384 insertions, 439 deletions
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 3e9dc92cb467..bafc729fc434 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -610,107 +610,53 @@ int ab8500_suspend(struct ab8500 *ab8500) } static const struct mfd_cell ab8500_bm_devs[] = { - { - .name = "ab8500-charger", - .of_compatible = "stericsson,ab8500-charger", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, - { - .name = "ab8500-btemp", - .of_compatible = "stericsson,ab8500-btemp", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, - { - .name = "ab8500-fg", - .of_compatible = "stericsson,ab8500-fg", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, - { - .name = "ab8500-chargalg", - .of_compatible = "stericsson,ab8500-chargalg", - .platform_data = &ab8500_bm_data, - .pdata_size = sizeof(ab8500_bm_data), - }, + OF_MFD_CELL("ab8500-charger", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-charger"), + OF_MFD_CELL("ab8500-btemp", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-btemp"), + OF_MFD_CELL("ab8500-fg", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-fg"), + OF_MFD_CELL("ab8500-chargalg", NULL, &ab8500_bm_data, + sizeof(ab8500_bm_data), 0, "stericsson,ab8500-chargalg"), }; static const struct mfd_cell ab8500_devs[] = { #ifdef CONFIG_DEBUG_FS - { - .name = "ab8500-debug", - .of_compatible = "stericsson,ab8500-debug", - }, + OF_MFD_CELL("ab8500-debug", + NULL, NULL, 0, 0, "stericsson,ab8500-debug"), #endif - { - .name = "ab8500-sysctrl", - .of_compatible = "stericsson,ab8500-sysctrl", - }, - { - .name = "ab8500-ext-regulator", - .of_compatible = "stericsson,ab8500-ext-regulator", - }, - { - .name = "ab8500-regulator", - .of_compatible = "stericsson,ab8500-regulator", - }, - { - .name = "ab8500-clk", - .of_compatible = "stericsson,ab8500-clk", - }, - { - .name = "ab8500-gpadc", - .of_compatible = "stericsson,ab8500-gpadc", - }, - { - .name = "ab8500-rtc", - .of_compatible = "stericsson,ab8500-rtc", - }, - { - .name = "ab8500-acc-det", - .of_compatible = "stericsson,ab8500-acc-det", - }, - { - - .name = "ab8500-poweron-key", - .of_compatible = "stericsson,ab8500-poweron-key", - }, - { - .name = "ab8500-pwm", - .of_compatible = "stericsson,ab8500-pwm", - .id = 1, - }, - { - .name = "ab8500-pwm", - .of_compatible = "stericsson,ab8500-pwm", - .id = 2, - }, - { - .name = "ab8500-pwm", - .of_compatible = "stericsson,ab8500-pwm", - .id = 3, - }, - { - .name = "ab8500-denc", - .of_compatible = "stericsson,ab8500-denc", - }, - { - .name = "pinctrl-ab8500", - .of_compatible = "stericsson,ab8500-gpio", - }, - { - .name = "abx500-temp", - .of_compatible = "stericsson,abx500-temp", - }, - { - .name = "ab8500-usb", - .of_compatible = "stericsson,ab8500-usb", - }, - { - .name = "ab8500-codec", - .of_compatible = "stericsson,ab8500-codec", - }, + OF_MFD_CELL("ab8500-sysctrl", + NULL, NULL, 0, 0, "stericsson,ab8500-sysctrl"), + OF_MFD_CELL("ab8500-ext-regulator", + NULL, NULL, 0, 0, "stericsson,ab8500-ext-regulator"), + OF_MFD_CELL("ab8500-regulator", + NULL, NULL, 0, 0, "stericsson,ab8500-regulator"), + OF_MFD_CELL("abx500-clk", + NULL, NULL, 0, 0, "stericsson,abx500-clk"), + OF_MFD_CELL("ab8500-gpadc", + NULL, NULL, 0, 0, "stericsson,ab8500-gpadc"), + OF_MFD_CELL("ab8500-rtc", + NULL, NULL, 0, 0, "stericsson,ab8500-rtc"), + OF_MFD_CELL("ab8500-acc-det", + NULL, NULL, 0, 0, "stericsson,ab8500-acc-det"), + OF_MFD_CELL("ab8500-poweron-key", + NULL, NULL, 0, 0, "stericsson,ab8500-poweron-key"), + OF_MFD_CELL("ab8500-pwm", + NULL, NULL, 0, 1, "stericsson,ab8500-pwm"), + OF_MFD_CELL("ab8500-pwm", + NULL, NULL, 0, 2, "stericsson,ab8500-pwm"), + OF_MFD_CELL("ab8500-pwm", + NULL, NULL, 0, 3, "stericsson,ab8500-pwm"), + OF_MFD_CELL("ab8500-denc", + NULL, NULL, 0, 0, "stericsson,ab8500-denc"), + OF_MFD_CELL("pinctrl-ab8500", + NULL, NULL, 0, 0, "stericsson,ab8500-gpio"), + OF_MFD_CELL("abx500-temp", + NULL, NULL, 0, 0, "stericsson,abx500-temp"), + OF_MFD_CELL("ab8500-usb", + NULL, NULL, 0, 0, "stericsson,ab8500-usb"), + OF_MFD_CELL("ab8500-codec", + NULL, NULL, 0, 0, "stericsson,ab8500-codec"), }; static const struct mfd_cell ab9540_devs[] = { diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 4a31907a4525..f73cf76d1373 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -814,11 +814,7 @@ static int arizona_of_get_core_pdata(struct arizona *arizona) int ret, i; /* Handle old non-standard DT binding */ - pdata->reset = devm_gpiod_get_from_of_node(arizona->dev, - arizona->dev->of_node, - "wlf,reset", 0, - GPIOD_OUT_LOW, - "arizona /RESET"); + pdata->reset = devm_gpiod_get(arizona->dev, "wlf,reset", GPIOD_OUT_LOW); if (IS_ERR(pdata->reset)) { ret = PTR_ERR(pdata->reset); diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c index f1825c0ccbd0..d0fb2e52ee76 100644 --- a/drivers/mfd/cs5535-mfd.c +++ b/drivers/mfd/cs5535-mfd.c @@ -27,121 +27,106 @@ enum cs5535_mfd_bars { NR_BARS, }; -static int cs5535_mfd_res_enable(struct platform_device *pdev) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(&pdev->dev, "can't fetch device resource info\n"); - return -EIO; - } - - if (!request_region(res->start, resource_size(res), DRV_NAME)) { - dev_err(&pdev->dev, "can't request region\n"); - return -EIO; - } - - return 0; -} - -static int cs5535_mfd_res_disable(struct platform_device *pdev) -{ - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(&pdev->dev, "can't fetch device resource info\n"); - return -EIO; - } - - release_region(res->start, resource_size(res)); - return 0; -} - static struct resource cs5535_mfd_resources[NR_BARS]; static struct mfd_cell cs5535_mfd_cells[] = { { - .id = SMB_BAR, .name = "cs5535-smb", .num_resources = 1, .resources = &cs5535_mfd_resources[SMB_BAR], }, { - .id = GPIO_BAR, .name = "cs5535-gpio", .num_resources = 1, .resources = &cs5535_mfd_resources[GPIO_BAR], }, { - .id = MFGPT_BAR, .name = "cs5535-mfgpt", .num_resources = 1, .resources = &cs5535_mfd_resources[MFGPT_BAR], }, { - .id = PMS_BAR, .name = "cs5535-pms", .num_resources = 1, .resources = &cs5535_mfd_resources[PMS_BAR], + }, +}; - .enable = cs5535_mfd_res_enable, - .disable = cs5535_mfd_res_disable, +static struct mfd_cell cs5535_olpc_mfd_cells[] = { + { + .name = "olpc-xo1-pm-acpi", + .num_resources = 1, + .resources = &cs5535_mfd_resources[ACPI_BAR], }, { - .id = ACPI_BAR, - .name = "cs5535-acpi", + .name = "olpc-xo1-sci-acpi", .num_resources = 1, .resources = &cs5535_mfd_resources[ACPI_BAR], - - .enable = cs5535_mfd_res_enable, - .disable = cs5535_mfd_res_disable, }, }; -static const char *olpc_acpi_clones[] = { - "olpc-xo1-pm-acpi", - "olpc-xo1-sci-acpi" -}; - static int cs5535_mfd_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int err, i; + int err, bar; err = pci_enable_device(pdev); if (err) return err; - /* fill in IO range for each cell; subdrivers handle the region */ - for (i = 0; i < ARRAY_SIZE(cs5535_mfd_cells); i++) { - int bar = cs5535_mfd_cells[i].id; + for (bar = 0; bar < NR_BARS; bar++) { struct resource *r = &cs5535_mfd_resources[bar]; r->flags = IORESOURCE_IO; r->start = pci_resource_start(pdev, bar); r->end = pci_resource_end(pdev, bar); + } - /* id is used for temporarily storing BAR; unset it now */ - cs5535_mfd_cells[i].id = 0; + err = pci_request_region(pdev, PMS_BAR, DRV_NAME); + if (err) { + dev_err(&pdev->dev, "Failed to request PMS_BAR's IO region\n"); + goto err_disable; } - err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells, + err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, cs5535_mfd_cells, ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL); if (err) { - dev_err(&pdev->dev, "MFD add devices failed: %d\n", err); - goto err_disable; + dev_err(&pdev->dev, + "Failed to add CS5535 sub-devices: %d\n", err); + goto err_release_pms; } - if (machine_is_olpc()) - mfd_clone_cell("cs5535-acpi", olpc_acpi_clones, ARRAY_SIZE(olpc_acpi_clones)); + if (machine_is_olpc()) { + err = pci_request_region(pdev, ACPI_BAR, DRV_NAME); + if (err) { + dev_err(&pdev->dev, + "Failed to request ACPI_BAR's IO region\n"); + goto err_remove_devices; + } + + err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + cs5535_olpc_mfd_cells, + ARRAY_SIZE(cs5535_olpc_mfd_cells), + NULL, 0, NULL); + if (err) { + dev_err(&pdev->dev, + "Failed to add CS5535 OLPC sub-devices: %d\n", + err); + goto err_release_acpi; + } + } dev_info(&pdev->dev, "%zu devices registered.\n", ARRAY_SIZE(cs5535_mfd_cells)); return 0; +err_release_acpi: + pci_release_region(pdev, ACPI_BAR); +err_remove_devices: + mfd_remove_devices(&pdev->dev); +err_release_pms: + pci_release_region(pdev, PMS_BAR); err_disable: pci_disable_device(pdev); return err; @@ -150,6 +135,11 @@ err_disable: static void cs5535_mfd_remove(struct pci_dev *pdev) { mfd_remove_devices(&pdev->dev); + + if (machine_is_olpc()) + pci_release_region(pdev, ACPI_BAR); + + pci_release_region(pdev, PMS_BAR); pci_disable_device(pdev); } diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dfac6afa82ca..57ac58b4b5f3 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -27,6 +27,7 @@ #include <linux/bitops.h> #include <linux/fs.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/uaccess.h> @@ -668,6 +669,14 @@ struct prcmu_fw_version *prcmu_get_fw_version(void) return fw_info.valid ? &fw_info.version : NULL; } +static bool prcmu_is_ulppll_disabled(void) +{ + struct prcmu_fw_version *ver; + + ver = prcmu_get_fw_version(); + return ver && ver->project == PRCMU_FW_PROJECT_U8420_SYSCLK; +} + bool prcmu_has_arm_maxopp(void) { return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & @@ -1308,10 +1317,23 @@ static int request_sysclk(bool enable) static int request_timclk(bool enable) { - u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); + u32 val; + + /* + * On the U8420_CLKSEL firmware, the ULP (Ultra Low Power) + * PLL is disabled so we cannot use doze mode, this will + * stop the clock on this firmware. + */ + if (prcmu_is_ulppll_disabled()) + val = 0; + else + val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); if (!enable) - val |= PRCM_TCR_STOP_TIMERS; + val |= PRCM_TCR_STOP_TIMERS | + PRCM_TCR_DOZE_MODE | + PRCM_TCR_TENSEL_MASK; + writel(val, PRCM_TCR); return 0; @@ -1615,7 +1637,8 @@ unsigned long prcmu_clock_rate(u8 clock) if (clock < PRCMU_NUM_REG_CLOCKS) return clock_rate(clock); else if (clock == PRCMU_TIMCLK) - return ROOT_CLOCK_RATE / 16; + return prcmu_is_ulppll_disabled() ? + 32768 : ROOT_CLOCK_RATE / 16; else if (clock == PRCMU_SYSCLK) return ROOT_CLOCK_RATE; else if (clock == PRCMU_PLLSOC0) @@ -2646,6 +2669,8 @@ static char *fw_project_name(u32 project) return "U8520 MBL"; case PRCMU_FW_PROJECT_U8420: return "U8420"; + case PRCMU_FW_PROJECT_U8420_SYSCLK: + return "U8420-sysclk"; case PRCMU_FW_PROJECT_U9540: return "U9540"; case PRCMU_FW_PROJECT_A9420: @@ -2693,27 +2718,18 @@ static int db8500_irq_init(struct device_node *np) return 0; } -static void dbx500_fw_version_init(struct platform_device *pdev, - u32 version_offset) +static void dbx500_fw_version_init(struct device_node *np) { - struct resource *res; void __iomem *tcpm_base; u32 version; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "prcmu-tcpm"); - if (!res) { - dev_err(&pdev->dev, - "Error: no prcmu tcpm memory region provided\n"); - return; - } - tcpm_base = ioremap(res->start, resource_size(res)); + tcpm_base = of_iomap(np, 1); if (!tcpm_base) { - dev_err(&pdev->dev, "no prcmu tcpm mem region provided\n"); + pr_err("no prcmu tcpm mem region provided\n"); return; } - version = readl(tcpm_base + version_offset); + version = readl(tcpm_base + DB8500_PRCMU_FW_VERSION_OFFSET); fw_info.version.project = (version & 0xFF); fw_info.version.api_version = (version >> 8) & 0xFF; fw_info.version.func_version = (version >> 16) & 0xFF; @@ -2731,7 +2747,7 @@ static void dbx500_fw_version_init(struct platform_device *pdev, iounmap(tcpm_base); } -void __init db8500_prcmu_early_init(u32 phy_base, u32 size) +void __init db8500_prcmu_early_init(void) { /* * This is a temporary remap to bring up the clocks. It is @@ -2740,9 +2756,17 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size) * clock driver can probe independently. An early initcall will * still be needed, but it can be diverted into drivers/clk/ux500. */ - prcmu_base = ioremap(phy_base, size); - if (!prcmu_base) + struct device_node *np; + + np = of_find_compatible_node(NULL, NULL, "stericsson,db8500-prcmu"); + prcmu_base = of_iomap(np, 0); + if (!prcmu_base) { + of_node_put(np); pr_err("%s: ioremap() of prcmu registers failed!\n", __func__); + return; + } + dbx500_fw_version_init(np); + of_node_put(np); spin_lock_init(&mb0_transfer.lock); spin_lock_init(&mb0_transfer.dbb_irqs_lock); @@ -3024,20 +3048,13 @@ static const struct mfd_cell common_prcmu_devs[] = { }; static const struct mfd_cell db8500_prcmu_devs[] = { - { - .name = "db8500-prcmu-regulators", - .of_compatible = "stericsson,db8500-prcmu-regulator", - .platform_data = &db8500_regulators, - .pdata_size = sizeof(db8500_regulators), - }, - { - .name = "cpuidle-dbx500", - .of_compatible = "stericsson,cpuidle-dbx500", - }, - { - .name = "db8500-thermal", - .of_compatible = "stericsson,db8500-thermal", - }, + OF_MFD_CELL("db8500-prcmu-regulators", NULL, + &db8500_regulators, sizeof(db8500_regulators), 0, + "stericsson,db8500-prcmu-regulator"), + OF_MFD_CELL("cpuidle-dbx500", + NULL, NULL, 0, 0, "stericsson,cpuidle-dbx500"), + OF_MFD_CELL("db8500-thermal", + NULL, NULL, 0, 0, "stericsson,db8500-thermal"), }; static int db8500_prcmu_register_ab8500(struct device *parent) @@ -3091,7 +3108,6 @@ static int db8500_prcmu_probe(struct platform_device *pdev) return -ENOMEM; } init_prcm_registers(); - dbx500_fw_version_init(pdev, DB8500_PRCMU_FW_VERSION_OFFSET); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); if (!res) { dev_err(&pdev->dev, "no prcmu tcdm region provided\n"); diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 9355db29d2f9..b33030e3385c 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -122,13 +122,25 @@ static const struct intel_lpss_platform_info apl_i2c_info = { .properties = apl_i2c_properties, }; +static struct property_entry glk_i2c_properties[] = { + PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 313), + PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171), + PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 290), + { }, +}; + +static const struct intel_lpss_platform_info glk_i2c_info = { + .clk_rate = 133000000, + .properties = glk_i2c_properties, +}; + static const struct intel_lpss_platform_info cnl_i2c_info = { .clk_rate = 216000000, .properties = spt_i2c_properties, }; static const struct pci_device_id intel_lpss_pci_ids[] = { - /* CML */ + /* CML-LP */ { PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info }, { PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info }, @@ -141,6 +153,17 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info }, { PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info }, + /* CML-H */ + { PCI_VDEVICE(INTEL, 0x06a8), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x06a9), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x06aa), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x06ab), (kernel_ulong_t)&spt_info }, + { PCI_VDEVICE(INTEL, 0x06c7), (kernel_ulong_t)&spt_uart_info }, + { PCI_VDEVICE(INTEL, 0x06e8), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06e9), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06ea), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06eb), (kernel_ulong_t)&cnl_i2c_info }, + { PCI_VDEVICE(INTEL, 0x06fb), (kernel_ulong_t)&spt_info }, /* BXT A-Step */ { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, @@ -174,14 +197,14 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info }, { PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info }, /* GLK */ - { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&bxt_i2c_info }, - { PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&bxt_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&glk_i2c_info }, + { PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&glk_i2c_info }, { PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info }, { PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info }, diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index bfe4ff337581..b0f0781a6b9c 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -384,7 +384,7 @@ int intel_lpss_probe(struct device *dev, if (!lpss) return -ENOMEM; - lpss->priv = devm_ioremap(dev, info->mem->start + LPSS_PRIV_OFFSET, + lpss->priv = devm_ioremap_uc(dev, info->mem->start + LPSS_PRIV_OFFSET, LPSS_PRIV_SIZE); if (!lpss->priv) return -ENOMEM; diff --git a/drivers/mfd/intel_soc_pmic_crc.c b/drivers/mfd/intel_soc_pmic_crc.c index ab09b8225b76..429efa1f8e55 100644 --- a/drivers/mfd/intel_soc_pmic_crc.c +++ b/drivers/mfd/intel_soc_pmic_crc.c @@ -89,6 +89,9 @@ static struct mfd_cell crystal_cove_cht_dev[] = { .resources = gpio_resources, }, { + .name = "cht_crystal_cove_pmic", + }, + { .name = "crystal_cove_pwm", }, }; diff --git a/drivers/mfd/ipaq-micro.c b/drivers/mfd/ipaq-micro.c index a1d9be82734d..e92eeeb67a98 100644 --- a/drivers/mfd/ipaq-micro.c +++ b/drivers/mfd/ipaq-micro.c @@ -396,11 +396,7 @@ static int __init micro_probe(struct platform_device *pdev) if (IS_ERR(micro->base)) return PTR_ERR(micro->base); - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) - return -EINVAL; - - micro->sdlc = devm_ioremap_resource(&pdev->dev, res); + micro->sdlc = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(micro->sdlc)) return PTR_ERR(micro->sdlc); diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c index 29540cbf7593..a8cfadc1fc01 100644 --- a/drivers/mfd/madera-core.c +++ b/drivers/mfd/madera-core.c @@ -450,6 +450,21 @@ int madera_dev_init(struct madera *madera) sizeof(madera->pdata)); } + madera->mclk[MADERA_MCLK1].id = "mclk1"; + madera->mclk[MADERA_MCLK2].id = "mclk2"; + madera->mclk[MADERA_MCLK3].id = "mclk3"; + + ret = devm_clk_bulk_get_optional(madera->dev, ARRAY_SIZE(madera->mclk), + madera->mclk); + if (ret) { + dev_err(madera->dev, "Failed to get clocks: %d\n", ret); + return ret; + } + + /* Not using devm_clk_get to prevent breakage of existing DTs */ + if (!madera->mclk[MADERA_MCLK2].clk) + dev_warn(madera->dev, "Missing MCLK2, requires 32kHz clock\n"); + ret = madera_get_reset_gpio(madera); if (ret) return ret; @@ -660,13 +675,19 @@ int madera_dev_init(struct madera *madera) } /* Init 32k clock sourced from MCLK2 */ + ret = clk_prepare_enable(madera->mclk[MADERA_MCLK2].clk); + if (ret) { + dev_err(madera->dev, "Failed to enable 32k clock: %d\n", ret); + goto err_reset; + } + ret = regmap_update_bits(madera->regmap, MADERA_CLOCK_32K_1, MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK, MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2); if (ret) { dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret); - goto err_reset; + goto err_clock; } pm_runtime_set_active(madera->dev); @@ -687,6 +708,8 @@ int madera_dev_init(struct madera *madera) err_pm_runtime: pm_runtime_disable(madera->dev); +err_clock: + clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk); err_reset: madera_enable_hard_reset(madera); regulator_disable(madera->dcvdd); @@ -713,6 +736,8 @@ int madera_dev_exit(struct madera *madera) */ pm_runtime_disable(madera->dev); + clk_disable_unprepare(madera->mclk[MADERA_MCLK2].clk); + regulator_disable(madera->dcvdd); regulator_put(madera->dcvdd); diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c index a851ff473a44..c7ed5c353553 100644 --- a/drivers/mfd/max77620.c +++ b/drivers/mfd/max77620.c @@ -507,7 +507,6 @@ static int max77620_probe(struct i2c_client *client, i2c_set_clientdata(client, chip); chip->dev = &client->dev; - chip->irq_base = -1; chip->chip_irq = client->irq; chip->chip_id = (enum max77620_chip_id)id->driver_data; @@ -545,8 +544,8 @@ static int max77620_probe(struct i2c_client *client, max77620_top_irq_chip.irq_drv_data = chip; ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq, - IRQF_ONESHOT | IRQF_SHARED, - chip->irq_base, &max77620_top_irq_chip, + IRQF_ONESHOT | IRQF_SHARED, 0, + &max77620_top_irq_chip, &chip->top_irq_data); if (ret < 0) { dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret); diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 23276a80e3b4..f5a73af60dd4 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -26,54 +26,28 @@ static struct device_type mfd_dev_type = { int mfd_cell_enable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); - int err = 0; - /* only call enable hook if the cell wasn't previously enabled */ - if (atomic_inc_return(cell->usage_count) == 1) - err = cell->enable(pdev); - - /* if the enable hook failed, decrement counter to allow retries */ - if (err) - atomic_dec(cell->usage_count); + if (!cell->enable) { + dev_dbg(&pdev->dev, "No .enable() call-back registered\n"); + return 0; + } - return err; + return cell->enable(pdev); } EXPORT_SYMBOL(mfd_cell_enable); int mfd_cell_disable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); - int err = 0; - - /* only disable if no other clients are using it */ - if (atomic_dec_return(cell->usage_count) == 0) - err = cell->disable(pdev); - - /* if the disable hook failed, increment to allow retries */ - if (err) - atomic_inc(cell->usage_count); - - /* sanity check; did someone call disable too many times? */ - WARN_ON(atomic_read(cell->usage_count) < 0); - return err; -} -EXPORT_SYMBOL(mfd_cell_disable); - -static int mfd_platform_add_cell(struct platform_device *pdev, - const struct mfd_cell *cell, - atomic_t *usage_count) -{ - if (!cell) + if (!cell->disable) { + dev_dbg(&pdev->dev, "No .disable() call-back registered\n"); return 0; + } - pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL); - if (!pdev->mfd_cell) - return -ENOMEM; - - pdev->mfd_cell->usage_count = usage_count; - return 0; + return cell->disable(pdev); } +EXPORT_SYMBOL(mfd_cell_disable); #if IS_ENABLED(CONFIG_ACPI) static void mfd_acpi_add_device(const struct mfd_cell *cell, @@ -134,7 +108,7 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell, #endif static int mfd_add_device(struct device *parent, int id, - const struct mfd_cell *cell, atomic_t *usage_count, + const struct mfd_cell *cell, struct resource *mem_base, int irq_base, struct irq_domain *domain) { @@ -154,6 +128,10 @@ static int mfd_add_device(struct device *parent, int id, if (!pdev) goto fail_alloc; + pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL); + if (!pdev->mfd_cell) + goto fail_device; + res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL); if (!res) goto fail_device; @@ -174,6 +152,11 @@ static int mfd_add_device(struct device *parent, int id, if (parent->of_node && cell->of_compatible) { for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { + if (!of_device_is_available(np)) { + /* Ignore disabled devices error free */ + ret = 0; + goto fail_alias; + } pdev->dev.of_node = np; pdev->dev.fwnode = &np->fwnode; break; @@ -196,10 +179,6 @@ static int mfd_add_device(struct device *parent, int id, goto fail_alias; } - ret = mfd_platform_add_cell(pdev, cell, usage_count); - if (ret) - goto fail_alias; - for (r = 0; r < cell->num_resources; r++) { res[r].name = cell->resources[r].name; res[r].flags = cell->resources[r].flags; @@ -286,16 +265,9 @@ int mfd_add_devices(struct device *parent, int id, { int i; int ret; - atomic_t *cnts; - - /* initialize reference counting for all cells */ - cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL); - if (!cnts) - return -ENOMEM; for (i = 0; i < n_devs; i++) { - atomic_set(&cnts[i], 0); - ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, + ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base, domain); if (ret) goto fail; @@ -306,17 +278,15 @@ int mfd_add_devices(struct device *parent, int id, fail: if (i) mfd_remove_devices(parent); - else - kfree(cnts); + return ret; } EXPORT_SYMBOL(mfd_add_devices); -static int mfd_remove_devices_fn(struct device *dev, void *c) +static int mfd_remove_devices_fn(struct device *dev, void *data) { struct platform_device *pdev; const struct mfd_cell *cell; - atomic_t **usage_count = c; if (dev->type != &mfd_dev_type) return 0; @@ -327,20 +297,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *c) regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, cell->num_parent_supplies); - /* find the base address of usage_count pointers (for freeing) */ - if (!*usage_count || (cell->usage_count < *usage_count)) - *usage_count = cell->usage_count; - platform_device_unregister(pdev); return 0; } void mfd_remove_devices(struct device *parent) { - atomic_t *cnts = NULL; - - device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn); - kfree(cnts); + device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn); } EXPORT_SYMBOL(mfd_remove_devices); @@ -382,38 +345,5 @@ int devm_mfd_add_devices(struct device *dev, int id, } EXPORT_SYMBOL(devm_mfd_add_devices); -int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) -{ - struct mfd_cell cell_entry; - struct device *dev; - struct platform_device *pdev; - int i; - - /* fetch the parent cell's device (should already be registered!) */ - dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); - if (!dev) { - printk(KERN_ERR "failed to find device for cell %s\n", cell); - return -ENODEV; - } - pdev = to_platform_device(dev); - memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry)); - - WARN_ON(!cell_entry.enable); - - for (i = 0; i < n_clones; i++) { - cell_entry.name = clones[i]; - /* don't give up if a single call fails; just report error */ - if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, - cell_entry.usage_count, NULL, 0, NULL)) - dev_err(dev, "failed to create platform device '%s'\n", - clones[i]); - } - - put_device(dev); - - return 0; -} -EXPORT_SYMBOL(mfd_clone_cell); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index b2c325ead1c8..0437c858d115 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -189,16 +189,16 @@ static int mt6397_probe(struct platform_device *pdev) switch (pmic->chip_id) { case MT6323_CHIP_ID: - ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs, - ARRAY_SIZE(mt6323_devs), NULL, - 0, pmic->irq_domain); + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + mt6323_devs, ARRAY_SIZE(mt6323_devs), + NULL, 0, pmic->irq_domain); break; case MT6391_CHIP_ID: case MT6397_CHIP_ID: - ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs, - ARRAY_SIZE(mt6397_devs), NULL, - 0, pmic->irq_domain); + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + mt6397_devs, ARRAY_SIZE(mt6397_devs), + NULL, 0, pmic->irq_domain); break; default: diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c index e8fe705073fa..1df1a2711328 100644 --- a/drivers/mfd/qcom-spmi-pmic.c +++ b/drivers/mfd/qcom-spmi-pmic.c @@ -31,6 +31,8 @@ #define PM8916_SUBTYPE 0x0b #define PM8004_SUBTYPE 0x0c #define PM8909_SUBTYPE 0x0d +#define PM8950_SUBTYPE 0x10 +#define PMI8950_SUBTYPE 0x11 #define PM8998_SUBTYPE 0x14 #define PMI8998_SUBTYPE 0x15 #define PM8005_SUBTYPE 0x18 @@ -50,6 +52,8 @@ static const struct of_device_id pmic_spmi_id_table[] = { { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, + { .compatible = "qcom,pm8950", .data = (void *)PM8950_SUBTYPE }, + { .compatible = "qcom,pmi8950", .data = (void *)PMI8950_SUBTYPE }, { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE }, { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE }, { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE }, diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 050478cabc95..a69a6742ecdc 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -109,11 +109,7 @@ static const struct regmap_config rk817_regmap_config = { }; static struct resource rtc_resources[] = { - { - .start = RK808_IRQ_RTC_ALARM, - .end = RK808_IRQ_RTC_ALARM, - .flags = IORESOURCE_IRQ, - } + DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), }; static struct resource rk817_rtc_resources[] = { @@ -121,16 +117,8 @@ static struct resource rk817_rtc_resources[] = { }; static struct resource rk805_key_resources[] = { - { - .start = RK805_IRQ_PWRON_FALL, - .end = RK805_IRQ_PWRON_FALL, - .flags = IORESOURCE_IRQ, - }, - { - .start = RK805_IRQ_PWRON_RISE, - .end = RK805_IRQ_PWRON_RISE, - .flags = IORESOURCE_IRQ, - } + DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE), + DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL), }; static struct resource rk817_pwrkey_resources[] = { @@ -167,7 +155,7 @@ static const struct mfd_cell rk817s[] = { { .name = "rk808-clkout",}, { .name = "rk808-regulator",}, { - .name = "rk8xx-pwrkey", + .name = "rk805-pwrkey", .num_resources = ARRAY_SIZE(rk817_pwrkey_resources), .resources = &rk817_pwrkey_resources[0], }, @@ -215,7 +203,7 @@ static const struct rk808_reg_data rk808_pre_init_reg[] = { static const struct rk808_reg_data rk817_pre_init_reg[] = { {RK817_RTC_CTRL_REG, RTC_STOP, RTC_STOP}, - {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_H}, + {RK817_GPIO_INT_CFG, RK817_INT_POL_MSK, RK817_INT_POL_L}, {RK817_SYS_CFG(1), RK817_HOTDIE_TEMP_MSK | RK817_TSD_TEMP_MSK, RK817_HOTDIE_105 | RK817_TSD_140}, }; diff --git a/drivers/mfd/rohm-bd70528.c b/drivers/mfd/rohm-bd70528.c index 55599d5c5c86..ef6786fd3b00 100644 --- a/drivers/mfd/rohm-bd70528.c +++ b/drivers/mfd/rohm-bd70528.c @@ -105,15 +105,14 @@ static struct regmap_config bd70528_regmap = { * register. */ -/* bit [0] - Shutdown register */ -unsigned int bit0_offsets[] = {0}; /* Shutdown register */ -unsigned int bit1_offsets[] = {1}; /* Power failure register */ -unsigned int bit2_offsets[] = {2}; /* VR FAULT register */ -unsigned int bit3_offsets[] = {3}; /* PMU register interrupts */ -unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 registers */ -unsigned int bit5_offsets[] = {6}; /* RTC register */ -unsigned int bit6_offsets[] = {7}; /* GPIO register */ -unsigned int bit7_offsets[] = {8}; /* Invalid operation register */ +static unsigned int bit0_offsets[] = {0}; /* Shutdown */ +static unsigned int bit1_offsets[] = {1}; /* Power failure */ +static unsigned int bit2_offsets[] = {2}; /* VR FAULT */ +static unsigned int bit3_offsets[] = {3}; /* PMU interrupts */ +static unsigned int bit4_offsets[] = {4, 5}; /* Charger 1 and Charger 2 */ +static unsigned int bit5_offsets[] = {6}; /* RTC */ +static unsigned int bit6_offsets[] = {7}; /* GPIO */ +static unsigned int bit7_offsets[] = {8}; /* Invalid operation */ static struct regmap_irq_sub_irq_map bd70528_sub_irq_offsets[] = { REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets), diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 660723276481..e22197c832e8 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -105,7 +105,6 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) syscon_config.reg_stride = reg_io_width; syscon_config.val_bits = reg_io_width * 8; syscon_config.max_register = resource_size(&res) - reg_io_width; - syscon_config.name = of_node_full_name(np); regmap = regmap_init_mmio(NULL, base, &syscon_config); if (IS_ERR(regmap)) { diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c index fd111296b959..926c289cb040 100644 --- a/drivers/mfd/ti_am335x_tscadc.c +++ b/drivers/mfd/ti_am335x_tscadc.c @@ -182,11 +182,11 @@ static int ti_tscadc_probe(struct platform_device *pdev) tscadc->irq = err; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - tscadc->tscadc_phys_base = res->start; tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(tscadc->tscadc_base)) return PTR_ERR(tscadc->tscadc_base); + tscadc->tscadc_phys_base = res->start; tscadc->regmap = devm_regmap_init_mmio(&pdev->dev, tscadc->tscadc_base, &tscadc_regmap_config); if (IS_ERR(tscadc->regmap)) { diff --git a/drivers/mfd/wm8998-tables.c b/drivers/mfd/wm8998-tables.c index ebf0eadd2075..9b34a6d76094 100644 --- a/drivers/mfd/wm8998-tables.c +++ b/drivers/mfd/wm8998-tables.c @@ -806,12 +806,6 @@ static const struct reg_default wm8998_reg_default[] = { { 0x00000EF3, 0x0000 }, /* R3827 - ISRC 2 CTRL 1 */ { 0x00000EF4, 0x0001 }, /* R3828 - ISRC 2 CTRL 2 */ { 0x00000EF5, 0x0000 }, /* R3829 - ISRC 2 CTRL 3 */ - { 0x00001700, 0x0000 }, /* R5888 - FRF_COEFF_1 */ - { 0x00001701, 0x0000 }, /* R5889 - FRF_COEFF_2 */ - { 0x00001702, 0x0000 }, /* R5890 - FRF_COEFF_3 */ - { 0x00001703, 0x0000 }, /* R5891 - FRF_COEFF_4 */ - { 0x00001704, 0x0000 }, /* R5892 - DAC_COMP_1 */ - { 0x00001705, 0x0000 }, /* R5893 - DAC_COMP_2 */ }; static bool wm8998_readable_register(struct device *dev, unsigned int reg) @@ -1492,12 +1486,6 @@ static bool wm8998_readable_register(struct device *dev, unsigned int reg) case ARIZONA_ISRC_2_CTRL_1: case ARIZONA_ISRC_2_CTRL_2: case ARIZONA_ISRC_2_CTRL_3: - case ARIZONA_FRF_COEFF_1: - case ARIZONA_FRF_COEFF_2: - case ARIZONA_FRF_COEFF_3: - case ARIZONA_FRF_COEFF_4: - case ARIZONA_V2_DAC_COMP_1: - case ARIZONA_V2_DAC_COMP_2: return true; default: return false; diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index a564237278ff..c721939767eb 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -140,6 +140,16 @@ config POWER_RESET_LTC2952 This driver supports an external powerdown trigger and board power down via the LTC2952. Bindings are made in the device tree. +config POWER_RESET_MT6323 + bool "MediaTek MT6323 power-off driver" + depends on MFD_MT6397 + help + The power-off driver is responsible for externally shutdown down + the power of a remote MediaTek SoC MT6323 is connected to through + controlling a tiny circuit BBPU inside MT6323 RTC. + + Say Y if you have a board where MT6323 could be found. + config POWER_RESET_QNAP bool "QNAP power-off driver" depends on OF_GPIO && PLAT_ORION diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 85da3198e4e0..da37f8b851dc 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o +obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o diff --git a/drivers/power/reset/mt6323-poweroff.c b/drivers/power/reset/mt6323-poweroff.c new file mode 100644 index 000000000000..1caf43d9e46d --- /dev/null +++ b/drivers/power/reset/mt6323-poweroff.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Power off through MediaTek PMIC + * + * Copyright (C) 2018 MediaTek Inc. + * + * Author: Sean Wang <sean.wang@mediatek.com> + * + */ + +#include <linux/err.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/mfd/mt6397/core.h> +#include <linux/mfd/mt6397/rtc.h> + +struct mt6323_pwrc { + struct device *dev; + struct regmap *regmap; + u32 base; +}; + +static struct mt6323_pwrc *mt_pwrc; + +static void mt6323_do_pwroff(void) +{ + struct mt6323_pwrc *pwrc = mt_pwrc; + unsigned int val; + int ret; + + regmap_write(pwrc->regmap, pwrc->base + RTC_BBPU, RTC_BBPU_KEY); + regmap_write(pwrc->regmap, pwrc->base + RTC_WRTGR, 1); + + ret = regmap_read_poll_timeout(pwrc->regmap, + pwrc->base + RTC_BBPU, val, + !(val & RTC_BBPU_CBUSY), + MTK_RTC_POLL_DELAY_US, + MTK_RTC_POLL_TIMEOUT); + if (ret) + dev_err(pwrc->dev, "failed to write BBPU: %d\n", ret); + + /* Wait some time until system down, otherwise, notice with a warn */ + mdelay(1000); + + WARN_ONCE(1, "Unable to power off system\n"); +} + +static int mt6323_pwrc_probe(struct platform_device *pdev) +{ + struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent); + struct mt6323_pwrc *pwrc; + struct resource *res; + + pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL); + if (!pwrc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pwrc->base = res->start; + pwrc->regmap = mt6397_chip->regmap; + pwrc->dev = &pdev->dev; + mt_pwrc = pwrc; + + pm_power_off = &mt6323_do_pwroff; + + return 0; +} + +static int mt6323_pwrc_remove(struct platform_device *pdev) +{ + if (pm_power_off == &mt6323_do_pwroff) + pm_power_off = NULL; + + return 0; +} + +static const struct of_device_id mt6323_pwrc_dt_match[] = { + { .compatible = "mediatek,mt6323-pwrc" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mt6323_pwrc_dt_match); + +static struct platform_driver mt6323_pwrc_driver = { + .probe = mt6323_pwrc_probe, + .remove = mt6323_pwrc_remove, + .driver = { + .name = "mt6323-pwrc", + .of_match_table = mt6323_pwrc_dt_match, + }, +}; + +module_platform_driver(mt6323_pwrc_driver); + +MODULE_DESCRIPTION("Poweroff driver for MT6323 PMIC"); +MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index 704229eb0cac..5249fc99fd5f 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -4,69 +4,19 @@ * Author: Tianping.Fang <tianping.fang@mediatek.com> */ -#include <linux/delay.h> -#include <linux/init.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/mfd/mt6397/core.h> #include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/rtc.h> -#include <linux/irqdomain.h> -#include <linux/platform_device.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/io.h> -#include <linux/mfd/mt6397/core.h> - -#define RTC_BBPU 0x0000 -#define RTC_BBPU_CBUSY BIT(6) - -#define RTC_WRTGR 0x003c - -#define RTC_IRQ_STA 0x0002 -#define RTC_IRQ_STA_AL BIT(0) -#define RTC_IRQ_STA_LP BIT(3) - -#define RTC_IRQ_EN 0x0004 -#define RTC_IRQ_EN_AL BIT(0) -#define RTC_IRQ_EN_ONESHOT BIT(2) -#define RTC_IRQ_EN_LP BIT(3) -#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL) - -#define RTC_AL_MASK 0x0008 -#define RTC_AL_MASK_DOW BIT(4) - -#define RTC_TC_SEC 0x000a -/* Min, Hour, Dom... register offset to RTC_TC_SEC */ -#define RTC_OFFSET_SEC 0 -#define RTC_OFFSET_MIN 1 -#define RTC_OFFSET_HOUR 2 -#define RTC_OFFSET_DOM 3 -#define RTC_OFFSET_DOW 4 -#define RTC_OFFSET_MTH 5 -#define RTC_OFFSET_YEAR 6 -#define RTC_OFFSET_COUNT 7 - -#define RTC_AL_SEC 0x0018 - -#define RTC_PDN2 0x002e -#define RTC_PDN2_PWRON_ALARM BIT(4) - -#define RTC_MIN_YEAR 1968 -#define RTC_BASE_YEAR 1900 -#define RTC_NUM_YEARS 128 -#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR) - -struct mt6397_rtc { - struct device *dev; - struct rtc_device *rtc_dev; - struct mutex lock; - struct regmap *regmap; - int irq; - u32 addr_base; -}; +#include <linux/mfd/mt6397/rtc.h> +#include <linux/mod_devicetable.h> static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) { - unsigned long timeout = jiffies + HZ; int ret; u32 data; @@ -74,19 +24,13 @@ static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) if (ret < 0) return ret; - while (1) { - ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU, - &data); - if (ret < 0) - break; - if (!(data & RTC_BBPU_CBUSY)) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - break; - } - cpu_relax(); - } + ret = regmap_read_poll_timeout(rtc->regmap, + rtc->addr_base + RTC_BBPU, data, + !(data & RTC_BBPU_CBUSY), + MTK_RTC_POLL_DELAY_US, + MTK_RTC_POLL_TIMEOUT); + if (ret < 0) + dev_err(rtc->dev, "failed to write WRTGE: %d\n", ret); return ret; } @@ -319,19 +263,19 @@ static int mtk_rtc_probe(struct platform_device *pdev) return rtc->irq; rtc->regmap = mt6397_chip->regmap; - rtc->dev = &pdev->dev; mutex_init(&rtc->lock); platform_set_drvdata(pdev, rtc); - rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev); + rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc_dev)) return PTR_ERR(rtc->rtc_dev); - ret = request_threaded_irq(rtc->irq, NULL, - mtk_rtc_irq_handler_thread, - IRQF_ONESHOT | IRQF_TRIGGER_HIGH, - "mt6397-rtc", rtc); + ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, + mtk_rtc_irq_handler_thread, + IRQF_ONESHOT | IRQF_TRIGGER_HIGH, + "mt6397-rtc", rtc); + if (ret) { dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", rtc->irq, ret); @@ -353,15 +297,6 @@ out_free_irq: return ret; } -static int mtk_rtc_remove(struct platform_device *pdev) -{ - struct mt6397_rtc *rtc = platform_get_drvdata(pdev); - - free_irq(rtc->irq, rtc); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int mt6397_rtc_suspend(struct device *dev) { @@ -388,6 +323,7 @@ static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend, mt6397_rtc_resume); static const struct of_device_id mt6397_rtc_of_match[] = { + { .compatible = "mediatek,mt6323-rtc", }, { .compatible = "mediatek,mt6397-rtc", }, { } }; @@ -400,7 +336,6 @@ static struct platform_driver mtk_rtc_driver = { .pm = &mt6397_pm_ops, }, .probe = mtk_rtc_probe, - .remove = mtk_rtc_remove, }; module_platform_driver(mtk_rtc_driver); |