예제 #1
0
void wm831x_device_exit(struct wm831x *wm831x)
{
	wm831x_otp_exit(wm831x);
	mfd_remove_devices(wm831x->dev);
	free_irq(wm831x_irq(wm831x, WM831X_IRQ_AUXADC_DATA), wm831x);
	wm831x_irq_exit(wm831x);
}
void wm831x_device_exit(struct wm831x *wm831x)
{
	wm831x_otp_exit(wm831x);
	mfd_remove_devices(wm831x->dev);
	if (wm831x->irq_base)
		free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
	wm831x_irq_exit(wm831x);
}
예제 #3
0
/*
 * Instantiate the generic non-control parts of the device.
 */
int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
{
	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
	int rev, wm831x_num;
	enum wm831x_parent parent;
	int ret, i;

	mutex_init(&wm831x->io_lock);
	mutex_init(&wm831x->key_lock);
	dev_set_drvdata(wm831x->dev, wm831x);

	ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
		goto err;
	}
	switch (ret) {
	case 0x6204:
	case 0x6246:
		break;
	default:
		dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
		ret = -EINVAL;
		goto err;
	}

	ret = wm831x_reg_read(wm831x, WM831X_REVISION);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
		goto err;
	}
	rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;

	ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
		goto err;
	}

	/* Some engineering samples do not have the ID set, rely on
	 * the device being registered correctly.
	 */
	if (ret == 0) {
		dev_info(wm831x->dev, "Device is an engineering sample\n");
		ret = id;
	}

	switch (ret) {
	case WM8310:
		parent = WM8310;
		wm831x->num_gpio = 16;
		wm831x->charger_irq_wake = 1;
		if (rev > 0) {
			wm831x->has_gpio_ena = 1;
			wm831x->has_cs_sts = 1;
		}

		dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
		break;

	case WM8311:
		parent = WM8311;
		wm831x->num_gpio = 16;
		wm831x->charger_irq_wake = 1;
		if (rev > 0) {
			wm831x->has_gpio_ena = 1;
			wm831x->has_cs_sts = 1;
		}

		dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
		break;

	case WM8312:
		parent = WM8312;
		wm831x->num_gpio = 16;
		wm831x->charger_irq_wake = 1;
		if (rev > 0) {
			wm831x->has_gpio_ena = 1;
			wm831x->has_cs_sts = 1;
		}

		dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
		break;

	case WM8320:
		parent = WM8320;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev);
		break;

	case WM8321:
		parent = WM8321;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev);
		break;

	case WM8325:
		parent = WM8325;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
		break;

	case WM8326:
		parent = WM8326;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
		break;

	default:
		dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
		ret = -EINVAL;
		goto err;
	}

	/* This will need revisiting in future but is OK for all
	 * current parts.
	 */
	if (parent != id)
		dev_warn(wm831x->dev, "Device was registered as a WM%lx\n",
			 id);

	/* Bootstrap the user key */
	ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
		goto err;
	}
	if (ret != 0) {
		dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
			 ret);
		wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
	}
	wm831x->locked = 1;

	if (pdata && pdata->pre_init) {
		ret = pdata->pre_init(wm831x);
		if (ret != 0) {
			dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
			goto err;
		}
	}

	if (pdata) {
		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
			if (!pdata->gpio_defaults[i])
				continue;

			wm831x_reg_write(wm831x,
					 WM831X_GPIO1_CONTROL + i,
					 pdata->gpio_defaults[i] & 0xffff);
		}
	}

	/* Multiply by 10 as we have many subdevices of the same type */
	if (pdata && pdata->wm831x_num)
		wm831x_num = pdata->wm831x_num * 10;
	else
		wm831x_num = -1;

	ret = wm831x_irq_init(wm831x, irq);
	if (ret != 0)
		goto err;

	wm831x_auxadc_init(wm831x);

	/* The core device is up, instantiate the subdevices. */
	switch (parent) {
	case WM8310:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8310_devs, ARRAY_SIZE(wm8310_devs),
				      NULL, wm831x->irq_base);
		break;

	case WM8311:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8311_devs, ARRAY_SIZE(wm8311_devs),
				      NULL, wm831x->irq_base);
		if (!pdata || !pdata->disable_touch)
			mfd_add_devices(wm831x->dev, wm831x_num,
					touch_devs, ARRAY_SIZE(touch_devs),
					NULL, wm831x->irq_base);
		break;

	case WM8312:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8312_devs, ARRAY_SIZE(wm8312_devs),
				      NULL, wm831x->irq_base);
		if (!pdata || !pdata->disable_touch)
			mfd_add_devices(wm831x->dev, wm831x_num,
					touch_devs, ARRAY_SIZE(touch_devs),
					NULL, wm831x->irq_base);
		break;

	case WM8320:
	case WM8321:
	case WM8325:
	case WM8326:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8320_devs, ARRAY_SIZE(wm8320_devs),
				      NULL, wm831x->irq_base);
		break;

	default:
		/* If this happens the bus probe function is buggy */
		BUG();
	}

	if (ret != 0) {
		dev_err(wm831x->dev, "Failed to add children\n");
		goto err_irq;
	}

	/* The RTC can only be used if the 32.768kHz crystal is
	 * enabled; this can't be controlled by software at runtime.
	 */
	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read clock status: %d\n", ret);
		goto err_irq;
	}

	if (ret & WM831X_XTAL_ENA) {
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      rtc_devs, ARRAY_SIZE(rtc_devs),
				      NULL, wm831x->irq_base);
		if (ret != 0) {
			dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
			goto err_irq;
		}
	} else {
		dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n");
	}

	if (pdata && pdata->backlight) {
		/* Treat errors as non-critical */
		ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
				      ARRAY_SIZE(backlight_devs), NULL,
				      wm831x->irq_base);
		if (ret < 0)
			dev_err(wm831x->dev, "Failed to add backlight: %d\n",
				ret);
	}

	wm831x_otp_init(wm831x);

	if (pdata && pdata->post_init) {
		ret = pdata->post_init(wm831x);
		if (ret != 0) {
			dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
			goto err_irq;
		}
	}

	return 0;

err_irq:
	wm831x_irq_exit(wm831x);
err:
	mfd_remove_devices(wm831x->dev);
	kfree(wm831x);
	return ret;
}