Loading Documentation/devicetree/bindings/mfd/arizona.txt 0 → 100644 +62 −0 Original line number Diff line number Diff line Wolfson Arizona class audio SoCs These devices are audio SoCs with extensive digital capabilites and a range of analogue I/O. Required properties: - compatible : one of the following chip-specific strings: "wlf,wm5102" "wlf,wm5110" - reg : I2C slave address when connected using I2C, chip select number when using SPI. - interrupts : The interrupt line the /IRQ signal for the device is connected to. - interrupt-controller : Arizona class devices contain interrupt controllers and may provide interrupt services to other devices. - interrupt-parent : The parent interrupt controller. - #interrupt-cells: the number of cells to describe an IRQ, this should be 2. The first cell is the IRQ number. The second cell is the flags, encoded as the trigger masks from Documentation/devicetree/bindings/interrupts.txt - gpio-controller : Indicates this device is a GPIO controller. - #gpio-cells : Must be 2. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). - AVDD1-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply, SPKVDDL-supply, SPKVDDR-supply : power supplies for the device, as covered in Documentation/devicetree/bindings/regulator/regulator.txt Optional properties: - wlf,reset : GPIO specifier for the GPIO controlling /RESET - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA - wlf,gpio-defaults : A list of GPIO configuration register values. If absent, no configuration of these registers is performed. If any entry has a value that is out of range for a 16 bit register then the chip default will be used. If present exactly five values must be specified. Example: codec: wm5102@1a { compatible = "wlf,wm5102"; reg = <0x1a>; interrupts = <347>; #interrupt-cells = <2>; interrupt-parent = <&gic>; gpio-controller; #gpio-cells = <2>; wlf,gpio-defaults = < 0x00000000, /* AIF1TXLRCLK */ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, >; }; drivers/mfd/arizona-core.c +201 −33 Original line number Diff line number Diff line Loading @@ -16,9 +16,13 @@ #include <linux/interrupt.h> #include <linux/mfd/core.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/regulator/machine.h> #include <linux/slab.h> #include <linux/mfd/arizona/core.h> Loading Loading @@ -344,6 +348,17 @@ static int arizona_runtime_resume(struct device *dev) switch (arizona->type) { case WM5102: if (arizona->external_dcvdd) { ret = regmap_update_bits(arizona->regmap, ARIZONA_ISOLATION_CONTROL, ARIZONA_ISOLATE_DCVDD1, 0); if (ret != 0) { dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret); goto err; } } ret = wm5102_patch(arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to apply patch: %d\n", Loading @@ -365,6 +380,28 @@ static int arizona_runtime_resume(struct device *dev) goto err; } if (arizona->external_dcvdd) { ret = regmap_update_bits(arizona->regmap, ARIZONA_ISOLATION_CONTROL, ARIZONA_ISOLATE_DCVDD1, 0); if (ret != 0) { dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret); goto err; } } break; } switch (arizona->type) { case WM5102: ret = wm5102_patch(arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to apply patch: %d\n", ret); goto err; } default: break; } Loading @@ -385,9 +422,22 @@ static int arizona_runtime_resume(struct device *dev) static int arizona_runtime_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); int ret; dev_dbg(arizona->dev, "Entering AoD mode\n"); if (arizona->external_dcvdd) { ret = regmap_update_bits(arizona->regmap, ARIZONA_ISOLATION_CONTROL, ARIZONA_ISOLATE_DCVDD1, ARIZONA_ISOLATE_DCVDD1); if (ret != 0) { dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", ret); return ret; } } regulator_disable(arizona->dcvdd); regcache_cache_only(arizona->regmap, true); regcache_mark_dirty(arizona->regmap); Loading @@ -397,6 +447,26 @@ static int arizona_runtime_suspend(struct device *dev) #endif #ifdef CONFIG_PM_SLEEP static int arizona_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); dev_dbg(arizona->dev, "Suspend, disabling IRQ\n"); disable_irq(arizona->irq); return 0; } static int arizona_suspend_late(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); dev_dbg(arizona->dev, "Late suspend, reenabling IRQ\n"); enable_irq(arizona->irq); return 0; } static int arizona_resume_noirq(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); Loading @@ -422,13 +492,78 @@ const struct dev_pm_ops arizona_pm_ops = { SET_RUNTIME_PM_OPS(arizona_runtime_suspend, arizona_runtime_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(NULL, arizona_resume) SET_SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume) #ifdef CONFIG_PM_SLEEP .suspend_late = arizona_suspend_late, .resume_noirq = arizona_resume_noirq, #endif }; EXPORT_SYMBOL_GPL(arizona_pm_ops); #ifdef CONFIG_OF int arizona_of_get_type(struct device *dev) { const struct of_device_id *id = of_match_device(arizona_of_match, dev); if (id) return (int)id->data; else return 0; } EXPORT_SYMBOL_GPL(arizona_of_get_type); static int arizona_of_get_core_pdata(struct arizona *arizona) { int ret, i; arizona->pdata.reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0); if (arizona->pdata.reset < 0) arizona->pdata.reset = 0; arizona->pdata.ldoena = of_get_named_gpio(arizona->dev->of_node, "wlf,ldoena", 0); if (arizona->pdata.ldoena < 0) arizona->pdata.ldoena = 0; ret = of_property_read_u32_array(arizona->dev->of_node, "wlf,gpio-defaults", arizona->pdata.gpio_defaults, ARRAY_SIZE(arizona->pdata.gpio_defaults)); if (ret >= 0) { /* * All values are literal except out of range values * which are chip default, translate into platform * data which uses 0 as chip default and out of range * as zero. */ for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { if (arizona->pdata.gpio_defaults[i] > 0xffff) arizona->pdata.gpio_defaults[i] = 0; if (arizona->pdata.gpio_defaults[i] == 0) arizona->pdata.gpio_defaults[i] = 0x10000; } } else { dev_err(arizona->dev, "Failed to parse GPIO defaults: %d\n", ret); } return 0; } const struct of_device_id arizona_of_match[] = { { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, {}, }; EXPORT_SYMBOL_GPL(arizona_of_match); #else static inline int arizona_of_get_core_pdata(struct arizona *arizona) { return 0; } #endif static struct mfd_cell early_devs[] = { { .name = "arizona-ldo1" }, }; Loading Loading @@ -462,6 +597,8 @@ int arizona_dev_init(struct arizona *arizona) dev_set_drvdata(arizona->dev, arizona); mutex_init(&arizona->clk_lock); arizona_of_get_core_pdata(arizona); if (dev_get_platdata(arizona->dev)) memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), sizeof(arizona->pdata)); Loading Loading @@ -536,51 +673,22 @@ int arizona_dev_init(struct arizona *arizona) regcache_cache_only(arizona->regmap, false); /* Verify that this is a chip we know about */ ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); if (ret != 0) { dev_err(dev, "Failed to read ID register: %d\n", ret); goto err_reset; } ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, &arizona->rev); if (ret != 0) { dev_err(dev, "Failed to read revision register: %d\n", ret); goto err_reset; } arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; switch (reg) { #ifdef CONFIG_MFD_WM5102 case 0x5102: type_name = "WM5102"; if (arizona->type != WM5102) { dev_err(arizona->dev, "WM5102 registered as %d\n", arizona->type); arizona->type = WM5102; } apply_patch = wm5102_patch; arizona->rev &= 0x7; break; #endif #ifdef CONFIG_MFD_WM5110 case 0x5110: type_name = "WM5110"; if (arizona->type != WM5110) { dev_err(arizona->dev, "WM5110 registered as %d\n", arizona->type); arizona->type = WM5110; } apply_patch = wm5110_patch; break; #endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); dev_err(arizona->dev, "Unknown device ID: %x\n", reg); goto err_reset; } dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); /* If we have a /RESET GPIO we'll already be reset */ if (!arizona->pdata.reset) { regcache_mark_dirty(arizona->regmap); Loading @@ -600,6 +708,7 @@ int arizona_dev_init(struct arizona *arizona) } } /* Ensure device startup is complete */ switch (arizona->type) { case WM5102: ret = regmap_read(arizona->regmap, 0x19, &val); Loading @@ -620,6 +729,52 @@ int arizona_dev_init(struct arizona *arizona) break; } /* Read the device ID information & do device specific stuff */ ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); if (ret != 0) { dev_err(dev, "Failed to read ID register: %d\n", ret); goto err_reset; } ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, &arizona->rev); if (ret != 0) { dev_err(dev, "Failed to read revision register: %d\n", ret); goto err_reset; } arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; switch (reg) { #ifdef CONFIG_MFD_WM5102 case 0x5102: type_name = "WM5102"; if (arizona->type != WM5102) { dev_err(arizona->dev, "WM5102 registered as %d\n", arizona->type); arizona->type = WM5102; } apply_patch = wm5102_patch; arizona->rev &= 0x7; break; #endif #ifdef CONFIG_MFD_WM5110 case 0x5110: type_name = "WM5110"; if (arizona->type != WM5110) { dev_err(arizona->dev, "WM5110 registered as %d\n", arizona->type); arizona->type = WM5110; } apply_patch = wm5110_patch; break; #endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); goto err_reset; } dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); if (apply_patch) { ret = apply_patch(arizona); if (ret != 0) { Loading Loading @@ -651,6 +806,14 @@ int arizona_dev_init(struct arizona *arizona) arizona->pdata.gpio_defaults[i]); } /* * LDO1 can only be used to supply DCVDD so if it has no * consumers then DCVDD is supplied externally. */ if (arizona->pdata.ldo1 && arizona->pdata.ldo1->num_consumer_supplies == 0) arizona->external_dcvdd = true; pm_runtime_set_autosuspend_delay(arizona->dev, 100); pm_runtime_use_autosuspend(arizona->dev); pm_runtime_enable(arizona->dev); Loading Loading @@ -697,7 +860,7 @@ int arizona_dev_init(struct arizona *arizona) if (arizona->pdata.micbias[i].discharge) val |= ARIZONA_MICB1_DISCH; if (arizona->pdata.micbias[i].fast_start) if (arizona->pdata.micbias[i].soft_start) val |= ARIZONA_MICB1_RATE; if (arizona->pdata.micbias[i].bypass) Loading Loading @@ -809,6 +972,11 @@ int arizona_dev_exit(struct arizona *arizona) arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona); pm_runtime_disable(arizona->dev); arizona_irq_exit(arizona); if (arizona->pdata.reset) gpio_set_value_cansleep(arizona->pdata.reset, 0); regulator_disable(arizona->dcvdd); regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies), arizona->core_supplies); return 0; } EXPORT_SYMBOL_GPL(arizona_dev_exit); drivers/mfd/arizona-i2c.c +8 −2 Original line number Diff line number Diff line Loading @@ -27,9 +27,14 @@ static int arizona_i2c_probe(struct i2c_client *i2c, { struct arizona *arizona; const struct regmap_config *regmap_config; int ret; int ret, type; switch (id->driver_data) { if (i2c->dev.of_node) type = arizona_of_get_type(&i2c->dev); else type = id->driver_data; switch (type) { #ifdef CONFIG_MFD_WM5102 case WM5102: regmap_config = &wm5102_i2c_regmap; Loading Loading @@ -84,6 +89,7 @@ static struct i2c_driver arizona_i2c_driver = { .name = "arizona", .owner = THIS_MODULE, .pm = &arizona_pm_ops, .of_match_table = of_match_ptr(arizona_of_match), }, .probe = arizona_i2c_probe, .remove = arizona_i2c_remove, Loading drivers/mfd/arizona-spi.c +8 −2 Original line number Diff line number Diff line Loading @@ -27,9 +27,14 @@ static int arizona_spi_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct arizona *arizona; const struct regmap_config *regmap_config; int ret; int ret, type; switch (id->driver_data) { if (spi->dev.of_node) type = arizona_of_get_type(&spi->dev); else type = id->driver_data; switch (type) { #ifdef CONFIG_MFD_WM5102 case WM5102: regmap_config = &wm5102_spi_regmap; Loading Loading @@ -84,6 +89,7 @@ static struct spi_driver arizona_spi_driver = { .name = "arizona", .owner = THIS_MODULE, .pm = &arizona_pm_ops, .of_match_table = of_match_ptr(arizona_of_match), }, .probe = arizona_spi_probe, .remove = arizona_spi_remove, Loading drivers/mfd/arizona.h +12 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #ifndef _WM5102_H #define _WM5102_H #include <linux/of.h> #include <linux/regmap.h> #include <linux/pm.h> Loading @@ -26,6 +27,8 @@ extern const struct regmap_config wm5110_spi_regmap; extern const struct dev_pm_ops arizona_pm_ops; extern const struct of_device_id arizona_of_match[]; extern const struct regmap_irq_chip wm5102_aod; extern const struct regmap_irq_chip wm5102_irq; Loading @@ -37,4 +40,13 @@ int arizona_dev_exit(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona); int arizona_irq_exit(struct arizona *arizona); #ifdef CONFIG_OF int arizona_of_get_type(struct device *dev); #else static inline int arizona_of_get_type(struct device *dev) { return 0; } #endif #endif Loading
Documentation/devicetree/bindings/mfd/arizona.txt 0 → 100644 +62 −0 Original line number Diff line number Diff line Wolfson Arizona class audio SoCs These devices are audio SoCs with extensive digital capabilites and a range of analogue I/O. Required properties: - compatible : one of the following chip-specific strings: "wlf,wm5102" "wlf,wm5110" - reg : I2C slave address when connected using I2C, chip select number when using SPI. - interrupts : The interrupt line the /IRQ signal for the device is connected to. - interrupt-controller : Arizona class devices contain interrupt controllers and may provide interrupt services to other devices. - interrupt-parent : The parent interrupt controller. - #interrupt-cells: the number of cells to describe an IRQ, this should be 2. The first cell is the IRQ number. The second cell is the flags, encoded as the trigger masks from Documentation/devicetree/bindings/interrupts.txt - gpio-controller : Indicates this device is a GPIO controller. - #gpio-cells : Must be 2. The first cell is the pin number and the second cell is used to specify optional parameters (currently unused). - AVDD1-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply, SPKVDDL-supply, SPKVDDR-supply : power supplies for the device, as covered in Documentation/devicetree/bindings/regulator/regulator.txt Optional properties: - wlf,reset : GPIO specifier for the GPIO controlling /RESET - wlf,ldoena : GPIO specifier for the GPIO controlling LDOENA - wlf,gpio-defaults : A list of GPIO configuration register values. If absent, no configuration of these registers is performed. If any entry has a value that is out of range for a 16 bit register then the chip default will be used. If present exactly five values must be specified. Example: codec: wm5102@1a { compatible = "wlf,wm5102"; reg = <0x1a>; interrupts = <347>; #interrupt-cells = <2>; interrupt-parent = <&gic>; gpio-controller; #gpio-cells = <2>; wlf,gpio-defaults = < 0x00000000, /* AIF1TXLRCLK */ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, >; };
drivers/mfd/arizona-core.c +201 −33 Original line number Diff line number Diff line Loading @@ -16,9 +16,13 @@ #include <linux/interrupt.h> #include <linux/mfd/core.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/regulator/machine.h> #include <linux/slab.h> #include <linux/mfd/arizona/core.h> Loading Loading @@ -344,6 +348,17 @@ static int arizona_runtime_resume(struct device *dev) switch (arizona->type) { case WM5102: if (arizona->external_dcvdd) { ret = regmap_update_bits(arizona->regmap, ARIZONA_ISOLATION_CONTROL, ARIZONA_ISOLATE_DCVDD1, 0); if (ret != 0) { dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret); goto err; } } ret = wm5102_patch(arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to apply patch: %d\n", Loading @@ -365,6 +380,28 @@ static int arizona_runtime_resume(struct device *dev) goto err; } if (arizona->external_dcvdd) { ret = regmap_update_bits(arizona->regmap, ARIZONA_ISOLATION_CONTROL, ARIZONA_ISOLATE_DCVDD1, 0); if (ret != 0) { dev_err(arizona->dev, "Failed to connect DCVDD: %d\n", ret); goto err; } } break; } switch (arizona->type) { case WM5102: ret = wm5102_patch(arizona); if (ret != 0) { dev_err(arizona->dev, "Failed to apply patch: %d\n", ret); goto err; } default: break; } Loading @@ -385,9 +422,22 @@ static int arizona_runtime_resume(struct device *dev) static int arizona_runtime_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); int ret; dev_dbg(arizona->dev, "Entering AoD mode\n"); if (arizona->external_dcvdd) { ret = regmap_update_bits(arizona->regmap, ARIZONA_ISOLATION_CONTROL, ARIZONA_ISOLATE_DCVDD1, ARIZONA_ISOLATE_DCVDD1); if (ret != 0) { dev_err(arizona->dev, "Failed to isolate DCVDD: %d\n", ret); return ret; } } regulator_disable(arizona->dcvdd); regcache_cache_only(arizona->regmap, true); regcache_mark_dirty(arizona->regmap); Loading @@ -397,6 +447,26 @@ static int arizona_runtime_suspend(struct device *dev) #endif #ifdef CONFIG_PM_SLEEP static int arizona_suspend(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); dev_dbg(arizona->dev, "Suspend, disabling IRQ\n"); disable_irq(arizona->irq); return 0; } static int arizona_suspend_late(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); dev_dbg(arizona->dev, "Late suspend, reenabling IRQ\n"); enable_irq(arizona->irq); return 0; } static int arizona_resume_noirq(struct device *dev) { struct arizona *arizona = dev_get_drvdata(dev); Loading @@ -422,13 +492,78 @@ const struct dev_pm_ops arizona_pm_ops = { SET_RUNTIME_PM_OPS(arizona_runtime_suspend, arizona_runtime_resume, NULL) SET_SYSTEM_SLEEP_PM_OPS(NULL, arizona_resume) SET_SYSTEM_SLEEP_PM_OPS(arizona_suspend, arizona_resume) #ifdef CONFIG_PM_SLEEP .suspend_late = arizona_suspend_late, .resume_noirq = arizona_resume_noirq, #endif }; EXPORT_SYMBOL_GPL(arizona_pm_ops); #ifdef CONFIG_OF int arizona_of_get_type(struct device *dev) { const struct of_device_id *id = of_match_device(arizona_of_match, dev); if (id) return (int)id->data; else return 0; } EXPORT_SYMBOL_GPL(arizona_of_get_type); static int arizona_of_get_core_pdata(struct arizona *arizona) { int ret, i; arizona->pdata.reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0); if (arizona->pdata.reset < 0) arizona->pdata.reset = 0; arizona->pdata.ldoena = of_get_named_gpio(arizona->dev->of_node, "wlf,ldoena", 0); if (arizona->pdata.ldoena < 0) arizona->pdata.ldoena = 0; ret = of_property_read_u32_array(arizona->dev->of_node, "wlf,gpio-defaults", arizona->pdata.gpio_defaults, ARRAY_SIZE(arizona->pdata.gpio_defaults)); if (ret >= 0) { /* * All values are literal except out of range values * which are chip default, translate into platform * data which uses 0 as chip default and out of range * as zero. */ for (i = 0; i < ARRAY_SIZE(arizona->pdata.gpio_defaults); i++) { if (arizona->pdata.gpio_defaults[i] > 0xffff) arizona->pdata.gpio_defaults[i] = 0; if (arizona->pdata.gpio_defaults[i] == 0) arizona->pdata.gpio_defaults[i] = 0x10000; } } else { dev_err(arizona->dev, "Failed to parse GPIO defaults: %d\n", ret); } return 0; } const struct of_device_id arizona_of_match[] = { { .compatible = "wlf,wm5102", .data = (void *)WM5102 }, { .compatible = "wlf,wm5110", .data = (void *)WM5110 }, {}, }; EXPORT_SYMBOL_GPL(arizona_of_match); #else static inline int arizona_of_get_core_pdata(struct arizona *arizona) { return 0; } #endif static struct mfd_cell early_devs[] = { { .name = "arizona-ldo1" }, }; Loading Loading @@ -462,6 +597,8 @@ int arizona_dev_init(struct arizona *arizona) dev_set_drvdata(arizona->dev, arizona); mutex_init(&arizona->clk_lock); arizona_of_get_core_pdata(arizona); if (dev_get_platdata(arizona->dev)) memcpy(&arizona->pdata, dev_get_platdata(arizona->dev), sizeof(arizona->pdata)); Loading Loading @@ -536,51 +673,22 @@ int arizona_dev_init(struct arizona *arizona) regcache_cache_only(arizona->regmap, false); /* Verify that this is a chip we know about */ ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); if (ret != 0) { dev_err(dev, "Failed to read ID register: %d\n", ret); goto err_reset; } ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, &arizona->rev); if (ret != 0) { dev_err(dev, "Failed to read revision register: %d\n", ret); goto err_reset; } arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; switch (reg) { #ifdef CONFIG_MFD_WM5102 case 0x5102: type_name = "WM5102"; if (arizona->type != WM5102) { dev_err(arizona->dev, "WM5102 registered as %d\n", arizona->type); arizona->type = WM5102; } apply_patch = wm5102_patch; arizona->rev &= 0x7; break; #endif #ifdef CONFIG_MFD_WM5110 case 0x5110: type_name = "WM5110"; if (arizona->type != WM5110) { dev_err(arizona->dev, "WM5110 registered as %d\n", arizona->type); arizona->type = WM5110; } apply_patch = wm5110_patch; break; #endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); dev_err(arizona->dev, "Unknown device ID: %x\n", reg); goto err_reset; } dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); /* If we have a /RESET GPIO we'll already be reset */ if (!arizona->pdata.reset) { regcache_mark_dirty(arizona->regmap); Loading @@ -600,6 +708,7 @@ int arizona_dev_init(struct arizona *arizona) } } /* Ensure device startup is complete */ switch (arizona->type) { case WM5102: ret = regmap_read(arizona->regmap, 0x19, &val); Loading @@ -620,6 +729,52 @@ int arizona_dev_init(struct arizona *arizona) break; } /* Read the device ID information & do device specific stuff */ ret = regmap_read(arizona->regmap, ARIZONA_SOFTWARE_RESET, ®); if (ret != 0) { dev_err(dev, "Failed to read ID register: %d\n", ret); goto err_reset; } ret = regmap_read(arizona->regmap, ARIZONA_DEVICE_REVISION, &arizona->rev); if (ret != 0) { dev_err(dev, "Failed to read revision register: %d\n", ret); goto err_reset; } arizona->rev &= ARIZONA_DEVICE_REVISION_MASK; switch (reg) { #ifdef CONFIG_MFD_WM5102 case 0x5102: type_name = "WM5102"; if (arizona->type != WM5102) { dev_err(arizona->dev, "WM5102 registered as %d\n", arizona->type); arizona->type = WM5102; } apply_patch = wm5102_patch; arizona->rev &= 0x7; break; #endif #ifdef CONFIG_MFD_WM5110 case 0x5110: type_name = "WM5110"; if (arizona->type != WM5110) { dev_err(arizona->dev, "WM5110 registered as %d\n", arizona->type); arizona->type = WM5110; } apply_patch = wm5110_patch; break; #endif default: dev_err(arizona->dev, "Unknown device ID %x\n", reg); goto err_reset; } dev_info(dev, "%s revision %c\n", type_name, arizona->rev + 'A'); if (apply_patch) { ret = apply_patch(arizona); if (ret != 0) { Loading Loading @@ -651,6 +806,14 @@ int arizona_dev_init(struct arizona *arizona) arizona->pdata.gpio_defaults[i]); } /* * LDO1 can only be used to supply DCVDD so if it has no * consumers then DCVDD is supplied externally. */ if (arizona->pdata.ldo1 && arizona->pdata.ldo1->num_consumer_supplies == 0) arizona->external_dcvdd = true; pm_runtime_set_autosuspend_delay(arizona->dev, 100); pm_runtime_use_autosuspend(arizona->dev); pm_runtime_enable(arizona->dev); Loading Loading @@ -697,7 +860,7 @@ int arizona_dev_init(struct arizona *arizona) if (arizona->pdata.micbias[i].discharge) val |= ARIZONA_MICB1_DISCH; if (arizona->pdata.micbias[i].fast_start) if (arizona->pdata.micbias[i].soft_start) val |= ARIZONA_MICB1_RATE; if (arizona->pdata.micbias[i].bypass) Loading Loading @@ -809,6 +972,11 @@ int arizona_dev_exit(struct arizona *arizona) arizona_free_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, arizona); pm_runtime_disable(arizona->dev); arizona_irq_exit(arizona); if (arizona->pdata.reset) gpio_set_value_cansleep(arizona->pdata.reset, 0); regulator_disable(arizona->dcvdd); regulator_bulk_disable(ARRAY_SIZE(arizona->core_supplies), arizona->core_supplies); return 0; } EXPORT_SYMBOL_GPL(arizona_dev_exit);
drivers/mfd/arizona-i2c.c +8 −2 Original line number Diff line number Diff line Loading @@ -27,9 +27,14 @@ static int arizona_i2c_probe(struct i2c_client *i2c, { struct arizona *arizona; const struct regmap_config *regmap_config; int ret; int ret, type; switch (id->driver_data) { if (i2c->dev.of_node) type = arizona_of_get_type(&i2c->dev); else type = id->driver_data; switch (type) { #ifdef CONFIG_MFD_WM5102 case WM5102: regmap_config = &wm5102_i2c_regmap; Loading Loading @@ -84,6 +89,7 @@ static struct i2c_driver arizona_i2c_driver = { .name = "arizona", .owner = THIS_MODULE, .pm = &arizona_pm_ops, .of_match_table = of_match_ptr(arizona_of_match), }, .probe = arizona_i2c_probe, .remove = arizona_i2c_remove, Loading
drivers/mfd/arizona-spi.c +8 −2 Original line number Diff line number Diff line Loading @@ -27,9 +27,14 @@ static int arizona_spi_probe(struct spi_device *spi) const struct spi_device_id *id = spi_get_device_id(spi); struct arizona *arizona; const struct regmap_config *regmap_config; int ret; int ret, type; switch (id->driver_data) { if (spi->dev.of_node) type = arizona_of_get_type(&spi->dev); else type = id->driver_data; switch (type) { #ifdef CONFIG_MFD_WM5102 case WM5102: regmap_config = &wm5102_spi_regmap; Loading Loading @@ -84,6 +89,7 @@ static struct spi_driver arizona_spi_driver = { .name = "arizona", .owner = THIS_MODULE, .pm = &arizona_pm_ops, .of_match_table = of_match_ptr(arizona_of_match), }, .probe = arizona_spi_probe, .remove = arizona_spi_remove, Loading
drivers/mfd/arizona.h +12 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ #ifndef _WM5102_H #define _WM5102_H #include <linux/of.h> #include <linux/regmap.h> #include <linux/pm.h> Loading @@ -26,6 +27,8 @@ extern const struct regmap_config wm5110_spi_regmap; extern const struct dev_pm_ops arizona_pm_ops; extern const struct of_device_id arizona_of_match[]; extern const struct regmap_irq_chip wm5102_aod; extern const struct regmap_irq_chip wm5102_irq; Loading @@ -37,4 +40,13 @@ int arizona_dev_exit(struct arizona *arizona); int arizona_irq_init(struct arizona *arizona); int arizona_irq_exit(struct arizona *arizona); #ifdef CONFIG_OF int arizona_of_get_type(struct device *dev); #else static inline int arizona_of_get_type(struct device *dev) { return 0; } #endif #endif