brintos

brintos / linux-shallow public Read only

0
0
Text · 15.9 KiB · 094c0b3 Raw
675 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * wm8994-core.c  --  Device access for Wolfson WM89944 *5 * Copyright 2009 Wolfson Microelectronics PLC.6 *7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/slab.h>13#include <linux/i2c.h>14#include <linux/err.h>15#include <linux/delay.h>16#include <linux/mfd/core.h>17#include <linux/of.h>18#include <linux/pm_runtime.h>19#include <linux/regmap.h>20#include <linux/regulator/consumer.h>21#include <linux/regulator/machine.h>22 23#include <linux/mfd/wm8994/core.h>24#include <linux/mfd/wm8994/pdata.h>25#include <linux/mfd/wm8994/registers.h>26 27#include "wm8994.h"28 29static const struct mfd_cell wm8994_regulator_devs[] = {30	{31		.name = "wm8994-ldo",32		.id = 0,33		.pm_runtime_no_callbacks = true,34	},35	{36		.name = "wm8994-ldo",37		.id = 1,38		.pm_runtime_no_callbacks = true,39	},40};41 42static const struct resource wm8994_codec_resources[] = {43	{44		.start = WM8994_IRQ_TEMP_SHUT,45		.end   = WM8994_IRQ_TEMP_WARN,46		.flags = IORESOURCE_IRQ,47	},48};49 50static const struct resource wm8994_gpio_resources[] = {51	{52		.start = WM8994_IRQ_GPIO(1),53		.end   = WM8994_IRQ_GPIO(11),54		.flags = IORESOURCE_IRQ,55	},56};57 58static const struct mfd_cell wm8994_devs[] = {59	{60		.name = "wm8994-codec",61		.num_resources = ARRAY_SIZE(wm8994_codec_resources),62		.resources = wm8994_codec_resources,63	},64 65	{66		.name = "wm8994-gpio",67		.num_resources = ARRAY_SIZE(wm8994_gpio_resources),68		.resources = wm8994_gpio_resources,69		.pm_runtime_no_callbacks = true,70	},71};72 73/*74 * Supplies for the main bulk of CODEC; the LDO supplies are ignored75 * and should be handled via the standard regulator API supply76 * management.77 */78static const char *wm1811_main_supplies[] = {79	"DBVDD1",80	"DBVDD2",81	"DBVDD3",82	"DCVDD",83	"AVDD1",84	"AVDD2",85	"CPVDD",86	"SPKVDD1",87	"SPKVDD2",88};89 90static const char *wm8994_main_supplies[] = {91	"DBVDD",92	"DCVDD",93	"AVDD1",94	"AVDD2",95	"CPVDD",96	"SPKVDD1",97	"SPKVDD2",98};99 100static const char *wm8958_main_supplies[] = {101	"DBVDD1",102	"DBVDD2",103	"DBVDD3",104	"DCVDD",105	"AVDD1",106	"AVDD2",107	"CPVDD",108	"SPKVDD1",109	"SPKVDD2",110};111 112static int wm8994_suspend(struct device *dev)113{114	struct wm8994 *wm8994 = dev_get_drvdata(dev);115	int ret;116 117	/* Don't actually go through with the suspend if the CODEC is118	 * still active for accessory detect. */119	switch (wm8994->type) {120	case WM8958:121	case WM1811:122		ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1);123		if (ret < 0) {124			dev_err(dev, "Failed to read power status: %d\n", ret);125		} else if (ret & WM8958_MICD_ENA) {126			dev_dbg(dev, "CODEC still active, ignoring suspend\n");127			return 0;128		}129		break;130	default:131		break;132	}133 134	/* Disable LDO pulldowns while the device is suspended if we135	 * don't know that something will be driving them. */136	if (!wm8994->ldo_ena_always_driven)137		wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,138				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,139				WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);140 141	/* Explicitly put the device into reset in case regulators142	 * don't get disabled in order to ensure consistent restart.143	 */144	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,145			 wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));146 147	regcache_mark_dirty(wm8994->regmap);148 149	/* Restore GPIO registers to prevent problems with mismatched150	 * pin configurations.151	 */152	ret = regcache_sync_region(wm8994->regmap, WM8994_GPIO_1,153				   WM8994_GPIO_11);154	if (ret != 0)155		dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);156 157	/* In case one of the GPIOs is used as a wake input. */158	ret = regcache_sync_region(wm8994->regmap,159				   WM8994_INTERRUPT_STATUS_1_MASK,160				   WM8994_INTERRUPT_STATUS_1_MASK);161	if (ret != 0)162		dev_err(dev, "Failed to restore interrupt mask: %d\n", ret);163 164	regcache_cache_only(wm8994->regmap, true);165	wm8994->suspended = true;166 167	ret = regulator_bulk_disable(wm8994->num_supplies,168				     wm8994->supplies);169	if (ret != 0) {170		dev_err(dev, "Failed to disable supplies: %d\n", ret);171		return ret;172	}173 174	return 0;175}176 177static int wm8994_resume(struct device *dev)178{179	struct wm8994 *wm8994 = dev_get_drvdata(dev);180	int ret;181 182	/* We may have lied to the PM core about suspending */183	if (!wm8994->suspended)184		return 0;185 186	ret = regulator_bulk_enable(wm8994->num_supplies,187				    wm8994->supplies);188	if (ret != 0) {189		dev_err(dev, "Failed to enable supplies: %d\n", ret);190		return ret;191	}192 193	regcache_cache_only(wm8994->regmap, false);194	ret = regcache_sync(wm8994->regmap);195	if (ret != 0) {196		dev_err(dev, "Failed to restore register map: %d\n", ret);197		goto err_enable;198	}199 200	/* Disable LDO pulldowns while the device is active */201	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,202			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,203			0);204 205	wm8994->suspended = false;206 207	return 0;208 209err_enable:210	regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);211 212	return ret;213}214 215#ifdef CONFIG_REGULATOR216static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)217{218	struct wm8994_ldo_pdata *ldo_pdata;219 220	if (!pdata)221		return 0;222 223	ldo_pdata = &pdata->ldo[ldo];224 225	if (!ldo_pdata->init_data)226		return 0;227 228	return ldo_pdata->init_data->num_consumer_supplies != 0;229}230#else231static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)232{233	return 0;234}235#endif236 237static const struct reg_sequence wm8994_revc_patch[] = {238	{ 0x102, 0x3 },239	{ 0x56, 0x3 },240	{ 0x817, 0x0 },241	{ 0x102, 0x0 },242};243 244static const struct reg_sequence wm8958_reva_patch[] = {245	{ 0x102, 0x3 },246	{ 0xcb, 0x81 },247	{ 0x817, 0x0 },248	{ 0x102, 0x0 },249};250 251static const struct reg_sequence wm1811_reva_patch[] = {252	{ 0x102, 0x3 },253	{ 0x56, 0xc07 },254	{ 0x5d, 0x7e },255	{ 0x5e, 0x0 },256	{ 0x102, 0x0 },257};258 259#ifdef CONFIG_OF260static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)261{262	struct device_node *np = wm8994->dev->of_node;263	struct wm8994_pdata *pdata = &wm8994->pdata;264	int i;265 266	if (!np)267		return 0;268 269	if (of_property_read_u32_array(np, "wlf,gpio-cfg", pdata->gpio_defaults,270				       ARRAY_SIZE(pdata->gpio_defaults)) >= 0) {271		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {272			if (wm8994->pdata.gpio_defaults[i] == 0)273				pdata->gpio_defaults[i]274					= WM8994_CONFIGURE_GPIO;275		}276	}277 278	of_property_read_u32_array(np, "wlf,micbias-cfg", pdata->micbias,279				   ARRAY_SIZE(pdata->micbias));280 281	pdata->lineout1_diff = !of_property_read_bool(np, "wlf,lineout1-se");282	pdata->lineout2_diff = !of_property_read_bool(np, "wlf,lineout2-se");283	pdata->lineout1fb = of_property_read_bool(np, "wlf,lineout1-feedback");284	pdata->lineout2fb = of_property_read_bool(np, "wlf,lineout2-feedback") ||285		of_property_read_bool(np, "wlf,ldoena-always-driven");286 287	pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu");288 289	pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd");290 291	return 0;292}293#else294static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)295{296	return 0;297}298#endif299 300/*301 * Instantiate the generic non-control parts of the device.302 */303static int wm8994_device_init(struct wm8994 *wm8994, int irq)304{305	struct wm8994_pdata *pdata;306	struct regmap_config *regmap_config;307	const struct reg_sequence *regmap_patch = NULL;308	const char *devname;309	int ret, i, patch_regs = 0;310	int pulls = 0;311 312	if (dev_get_platdata(wm8994->dev)) {313		pdata = dev_get_platdata(wm8994->dev);314		wm8994->pdata = *pdata;315	}316	pdata = &wm8994->pdata;317 318	ret = wm8994_set_pdata_from_of(wm8994);319	if (ret != 0)320		return ret;321 322	/* Add the on-chip regulators first for bootstrapping */323	ret = mfd_add_devices(wm8994->dev, 0,324			      wm8994_regulator_devs,325			      ARRAY_SIZE(wm8994_regulator_devs),326			      NULL, 0, NULL);327	if (ret != 0) {328		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);329		goto err;330	}331 332	switch (wm8994->type) {333	case WM1811:334		wm8994->num_supplies = ARRAY_SIZE(wm1811_main_supplies);335		break;336	case WM8994:337		wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);338		break;339	case WM8958:340		wm8994->num_supplies = ARRAY_SIZE(wm8958_main_supplies);341		break;342	default:343		BUG();344		goto err;345	}346 347	wm8994->supplies = devm_kcalloc(wm8994->dev,348					wm8994->num_supplies,349					sizeof(struct regulator_bulk_data),350					GFP_KERNEL);351	if (!wm8994->supplies) {352		ret = -ENOMEM;353		goto err;354	}355 356	switch (wm8994->type) {357	case WM1811:358		for (i = 0; i < ARRAY_SIZE(wm1811_main_supplies); i++)359			wm8994->supplies[i].supply = wm1811_main_supplies[i];360		break;361	case WM8994:362		for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)363			wm8994->supplies[i].supply = wm8994_main_supplies[i];364		break;365	case WM8958:366		for (i = 0; i < ARRAY_SIZE(wm8958_main_supplies); i++)367			wm8994->supplies[i].supply = wm8958_main_supplies[i];368		break;369	default:370		BUG();371		goto err;372	}373 374	/*375	 * Can't use devres helper here as some of the supplies are provided by376	 * wm8994->dev's children (regulators) and those regulators are377	 * unregistered by the devres core before the supplies are freed.378	 */379	ret = regulator_bulk_get(wm8994->dev, wm8994->num_supplies,380				 wm8994->supplies);381	if (ret != 0) {382		if (ret != -EPROBE_DEFER)383			dev_err(wm8994->dev, "Failed to get supplies: %d\n",384				ret);385		goto err;386	}387 388	ret = regulator_bulk_enable(wm8994->num_supplies, wm8994->supplies);389	if (ret != 0) {390		dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);391		goto err_regulator_free;392	}393 394	ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);395	if (ret < 0) {396		dev_err(wm8994->dev, "Failed to read ID register\n");397		goto err_enable;398	}399	switch (ret) {400	case 0x1811:401		devname = "WM1811";402		if (wm8994->type != WM1811)403			dev_warn(wm8994->dev, "Device registered as type %d\n",404				 wm8994->type);405		wm8994->type = WM1811;406		break;407	case 0x8994:408		devname = "WM8994";409		if (wm8994->type != WM8994)410			dev_warn(wm8994->dev, "Device registered as type %d\n",411				 wm8994->type);412		wm8994->type = WM8994;413		break;414	case 0x8958:415		devname = "WM8958";416		if (wm8994->type != WM8958)417			dev_warn(wm8994->dev, "Device registered as type %d\n",418				 wm8994->type);419		wm8994->type = WM8958;420		break;421	default:422		dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",423			ret);424		ret = -EINVAL;425		goto err_enable;426	}427 428	ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION);429	if (ret < 0) {430		dev_err(wm8994->dev, "Failed to read revision register: %d\n",431			ret);432		goto err_enable;433	}434	wm8994->revision = ret & WM8994_CHIP_REV_MASK;435	wm8994->cust_id = (ret & WM8994_CUST_ID_MASK) >> WM8994_CUST_ID_SHIFT;436 437	switch (wm8994->type) {438	case WM8994:439		switch (wm8994->revision) {440		case 0:441		case 1:442			dev_warn(wm8994->dev,443				 "revision %c not fully supported\n",444				 'A' + wm8994->revision);445			break;446		case 2:447		case 3:448		default:449			regmap_patch = wm8994_revc_patch;450			patch_regs = ARRAY_SIZE(wm8994_revc_patch);451			break;452		}453		break;454 455	case WM8958:456		switch (wm8994->revision) {457		case 0:458			regmap_patch = wm8958_reva_patch;459			patch_regs = ARRAY_SIZE(wm8958_reva_patch);460			break;461		default:462			break;463		}464		break;465 466	case WM1811:467		/* Revision C did not change the relevant layer */468		if (wm8994->revision > 1)469			wm8994->revision++;470 471		regmap_patch = wm1811_reva_patch;472		patch_regs = ARRAY_SIZE(wm1811_reva_patch);473		break;474 475	default:476		break;477	}478 479	dev_info(wm8994->dev, "%s revision %c CUST_ID %02x\n", devname,480		 'A' + wm8994->revision, wm8994->cust_id);481 482	switch (wm8994->type) {483	case WM1811:484		regmap_config = &wm1811_regmap_config;485		break;486	case WM8994:487		regmap_config = &wm8994_regmap_config;488		break;489	case WM8958:490		regmap_config = &wm8958_regmap_config;491		break;492	default:493		dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);494		ret = -EINVAL;495		goto err_enable;496	}497 498	ret = regmap_reinit_cache(wm8994->regmap, regmap_config);499	if (ret != 0) {500		dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",501			ret);502		goto err_enable;503	}504 505	/* Explicitly put the device into reset in case regulators506	 * don't get disabled in order to ensure we know the device507	 * state.508	 */509	ret = wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,510			       wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));511	if (ret != 0) {512		dev_err(wm8994->dev, "Failed to reset device: %d\n", ret);513		goto err_enable;514	}515 516	if (regmap_patch) {517		ret = regmap_register_patch(wm8994->regmap, regmap_patch,518					    patch_regs);519		if (ret != 0) {520			dev_err(wm8994->dev, "Failed to register patch: %d\n",521				ret);522			goto err_enable;523		}524	}525 526	wm8994->irq_base = pdata->irq_base;527	wm8994->gpio_base = pdata->gpio_base;528 529	/* GPIO configuration is only applied if it's non-zero */530	for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {531		if (pdata->gpio_defaults[i]) {532			wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,533					0xffff, pdata->gpio_defaults[i]);534		}535	}536 537	wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;538 539	if (pdata->spkmode_pu)540		pulls |= WM8994_SPKMODE_PU;541	if (pdata->csnaddr_pd)542		pulls |= WM8994_CSNADDR_PD;543 544	/* Disable unneeded pulls */545	wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,546			WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD |547			WM8994_SPKMODE_PU | WM8994_CSNADDR_PD,548			pulls);549 550	/* In some system designs where the regulators are not in use,551	 * we can achieve a small reduction in leakage currents by552	 * floating LDO outputs.  This bit makes no difference if the553	 * LDOs are enabled, it only affects cases where the LDOs were554	 * in operation and are then disabled.555	 */556	for (i = 0; i < WM8994_NUM_LDO_REGS; i++) {557		if (wm8994_ldo_in_use(pdata, i))558			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,559					WM8994_LDO1_DISCH, WM8994_LDO1_DISCH);560		else561			wm8994_set_bits(wm8994, WM8994_LDO_1 + i,562					WM8994_LDO1_DISCH, 0);563	}564 565	wm8994_irq_init(wm8994);566 567	ret = mfd_add_devices(wm8994->dev, -1,568			      wm8994_devs, ARRAY_SIZE(wm8994_devs),569			      NULL, 0, NULL);570	if (ret != 0) {571		dev_err(wm8994->dev, "Failed to add children: %d\n", ret);572		goto err_irq;573	}574 575	pm_runtime_set_active(wm8994->dev);576	pm_runtime_enable(wm8994->dev);577	pm_runtime_idle(wm8994->dev);578 579	return 0;580 581err_irq:582	wm8994_irq_exit(wm8994);583err_enable:584	regulator_bulk_disable(wm8994->num_supplies,585			       wm8994->supplies);586err_regulator_free:587	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);588err:589	mfd_remove_devices(wm8994->dev);590	return ret;591}592 593static void wm8994_device_exit(struct wm8994 *wm8994)594{595	pm_runtime_get_sync(wm8994->dev);596	pm_runtime_disable(wm8994->dev);597	pm_runtime_put_noidle(wm8994->dev);598	wm8994_irq_exit(wm8994);599	regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);600	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);601	mfd_remove_devices(wm8994->dev);602}603 604static const struct of_device_id wm8994_of_match[] = {605	{ .compatible = "wlf,wm1811", .data = (void *)WM1811 },606	{ .compatible = "wlf,wm8994", .data = (void *)WM8994 },607	{ .compatible = "wlf,wm8958", .data = (void *)WM8958 },608	{ }609};610MODULE_DEVICE_TABLE(of, wm8994_of_match);611 612static int wm8994_i2c_probe(struct i2c_client *i2c)613{614	struct wm8994 *wm8994;615	int ret;616 617	wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);618	if (wm8994 == NULL)619		return -ENOMEM;620 621	i2c_set_clientdata(i2c, wm8994);622	wm8994->dev = &i2c->dev;623	wm8994->irq = i2c->irq;624 625	wm8994->type = (kernel_ulong_t)i2c_get_match_data(i2c);626 627	wm8994->regmap = devm_regmap_init_i2c(i2c, &wm8994_base_regmap_config);628	if (IS_ERR(wm8994->regmap)) {629		ret = PTR_ERR(wm8994->regmap);630		dev_err(wm8994->dev, "Failed to allocate register map: %d\n",631			ret);632		return ret;633	}634 635	return wm8994_device_init(wm8994, i2c->irq);636}637 638static void wm8994_i2c_remove(struct i2c_client *i2c)639{640	struct wm8994 *wm8994 = i2c_get_clientdata(i2c);641 642	wm8994_device_exit(wm8994);643}644 645static const struct i2c_device_id wm8994_i2c_id[] = {646	{ "wm1811", WM1811 },647	{ "wm1811a", WM1811 },648	{ "wm8994", WM8994 },649	{ "wm8958", WM8958 },650	{ }651};652MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);653 654static const struct dev_pm_ops wm8994_pm_ops = {655	RUNTIME_PM_OPS(wm8994_suspend, wm8994_resume, NULL)656};657 658static struct i2c_driver wm8994_i2c_driver = {659	.driver = {660		.name = "wm8994",661		.pm = pm_ptr(&wm8994_pm_ops),662		.of_match_table = wm8994_of_match,663	},664	.probe = wm8994_i2c_probe,665	.remove = wm8994_i2c_remove,666	.id_table = wm8994_i2c_id,667};668 669module_i2c_driver(wm8994_i2c_driver);670 671MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");672MODULE_LICENSE("GPL");673MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");674MODULE_SOFTDEP("pre: wm8994_regulator");675