static int __devinit w90p910_keypad_probe(struct platform_device *pdev)
{
	const struct w90p910_keypad_platform_data *pdata =
						pdev->dev.platform_data;
	const struct matrix_keymap_data *keymap_data;
	struct w90p910_keypad *keypad;
	struct input_dev *input_dev;
	struct resource *res;
	int irq;
	int error;

	if (!pdata) {
		dev_err(&pdev->dev, "no platform data defined\n");
		return -EINVAL;
	}

	keymap_data = pdata->keymap_data;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "failed to get keypad irq\n");
		return -ENXIO;
	}

	keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!keypad || !input_dev) {
		dev_err(&pdev->dev, "failed to allocate driver data\n");
		error = -ENOMEM;
		goto failed_free;
	}

	keypad->pdata = pdata;
	keypad->input_dev = input_dev;
	keypad->irq = irq;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to get I/O memory\n");
		error = -ENXIO;
		goto failed_free;
	}

	res = request_mem_region(res->start, resource_size(res), pdev->name);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to request I/O memory\n");
		error = -EBUSY;
		goto failed_free;
	}

	keypad->mmio_base = ioremap(res->start, resource_size(res));
	if (keypad->mmio_base == NULL) {
		dev_err(&pdev->dev, "failed to remap I/O memory\n");
		error = -ENXIO;
		goto failed_free_res;
	}

	keypad->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(keypad->clk)) {
		dev_err(&pdev->dev, "failed to get keypad clock\n");
		error = PTR_ERR(keypad->clk);
		goto failed_free_io;
	}

	/* set multi-function pin for w90p910 kpi. */
	mfp_set_groupi(&pdev->dev);

	input_dev->name = pdev->name;
	input_dev->id.bustype = BUS_HOST;
	input_dev->open = w90p910_keypad_open;
	input_dev->close = w90p910_keypad_close;
	input_dev->dev.parent = &pdev->dev;

	input_dev->keycode = keypad->keymap;
	input_dev->keycodesize = sizeof(keypad->keymap[0]);
	input_dev->keycodemax = ARRAY_SIZE(keypad->keymap);

	input_set_drvdata(input_dev, keypad);

	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT,
				   input_dev->keycode, input_dev->keybit);

	error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
			    IRQF_DISABLED, pdev->name, keypad);
	if (error) {
		dev_err(&pdev->dev, "failed to request IRQ\n");
		goto failed_put_clk;
	}

	/* Register the input device */
	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to register input device\n");
		goto failed_free_irq;
	}

	platform_set_drvdata(pdev, keypad);
	return 0;

failed_free_irq:
	free_irq(irq, pdev);
failed_put_clk:
	clk_put(keypad->clk);
failed_free_io:
	iounmap(keypad->mmio_base);
failed_free_res:
	release_mem_region(res->start, resource_size(res));
failed_free:
	input_free_device(input_dev);
	kfree(keypad);
	return error;
}
예제 #2
0
파일: imx_keypad.c 프로젝트: 7799/linux
static int imx_keypad_probe(struct platform_device *pdev)
{
	const struct matrix_keymap_data *keymap_data =
			dev_get_platdata(&pdev->dev);
	struct imx_keypad *keypad;
	struct input_dev *input_dev;
	struct resource *res;
	int irq, error, i, row, col;

	if (!keymap_data && !pdev->dev.of_node) {
		dev_err(&pdev->dev, "no keymap defined\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "no irq defined in platform data\n");
		return irq;
	}

	input_dev = devm_input_allocate_device(&pdev->dev);
	if (!input_dev) {
		dev_err(&pdev->dev, "failed to allocate the input device\n");
		return -ENOMEM;
	}

	keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad),
			      GFP_KERNEL);
	if (!keypad) {
		dev_err(&pdev->dev, "not enough memory for driver data\n");
		return -ENOMEM;
	}

	keypad->input_dev = input_dev;
	keypad->irq = irq;
	keypad->stable_count = 0;

	setup_timer(&keypad->check_matrix_timer,
		    imx_keypad_check_for_events, (unsigned long) keypad);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	keypad->mmio_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(keypad->mmio_base))
		return PTR_ERR(keypad->mmio_base);

	keypad->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(keypad->clk)) {
		dev_err(&pdev->dev, "failed to get keypad clock\n");
		return PTR_ERR(keypad->clk);
	}

	/* Init the Input device */
	input_dev->name = pdev->name;
	input_dev->id.bustype = BUS_HOST;
	input_dev->dev.parent = &pdev->dev;
	input_dev->open = imx_keypad_open;
	input_dev->close = imx_keypad_close;

	error = matrix_keypad_build_keymap(keymap_data, NULL,
					   MAX_MATRIX_KEY_ROWS,
					   MAX_MATRIX_KEY_COLS,
					   keypad->keycodes, input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to build keymap\n");
		return error;
	}

	/* Search for rows and cols enabled */
	for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
		for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
			i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
			if (keypad->keycodes[i] != KEY_RESERVED) {
				keypad->rows_en_mask |= 1 << row;
				keypad->cols_en_mask |= 1 << col;
			}
		}
	}
	dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
	dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);

	__set_bit(EV_REP, input_dev->evbit);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
	input_set_drvdata(input_dev, keypad);

	/* Ensure that the keypad will stay dormant until opened */
	clk_prepare_enable(keypad->clk);
	imx_keypad_inhibit(keypad);
	clk_disable_unprepare(keypad->clk);

	error = devm_request_irq(&pdev->dev, irq, imx_keypad_irq_handler, 0,
			    pdev->name, keypad);
	if (error) {
		dev_err(&pdev->dev, "failed to request IRQ\n");
		return error;
	}

	/* Register the input device */
	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to register input device\n");
		return error;
	}

	platform_set_drvdata(pdev, keypad);
	device_init_wakeup(&pdev->dev, 1);

	return 0;
}
예제 #3
0
static int tca8418_keypad_probe(struct i2c_client *client,
					  const struct i2c_device_id *id)
{
	struct device *dev = &client->dev;
	const struct tca8418_keypad_platform_data *pdata =
						dev_get_platdata(dev);
	struct tca8418_keypad *keypad_data;
	struct input_dev *input;
	const struct matrix_keymap_data *keymap_data = NULL;
	u32 rows = 0, cols = 0;
	bool rep = false;
	bool irq_is_gpio = false;
	int irq;
	int error, row_shift, max_keys;

	/* Copy the platform data */
	if (pdata) {
		if (!pdata->keymap_data) {
			dev_err(dev, "no keymap data defined\n");
			return -EINVAL;
		}
		keymap_data = pdata->keymap_data;
		rows = pdata->rows;
		cols = pdata->cols;
		rep  = pdata->rep;
		irq_is_gpio = pdata->irq_is_gpio;
	} else {
		struct device_node *np = dev->of_node;
		int err;

		err = matrix_keypad_parse_of_params(dev, &rows, &cols);
		if (err)
			return err;
		rep = of_property_read_bool(np, "keypad,autorepeat");
	}

	if (!rows || rows > TCA8418_MAX_ROWS) {
		dev_err(dev, "invalid rows\n");
		return -EINVAL;
	}

	if (!cols || cols > TCA8418_MAX_COLS) {
		dev_err(dev, "invalid columns\n");
		return -EINVAL;
	}

	/* Check i2c driver capabilities */
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
		dev_err(dev, "%s adapter not supported\n",
			dev_driver_string(&client->adapter->dev));
		return -ENODEV;
	}

	row_shift = get_count_order(cols);
	max_keys = rows << row_shift;

	/* Allocate memory for keypad_data and input device */
	keypad_data = devm_kzalloc(dev, sizeof(*keypad_data), GFP_KERNEL);
	if (!keypad_data)
		return -ENOMEM;

	keypad_data->client = client;
	keypad_data->row_shift = row_shift;

	/* Initialize the chip or fail if chip isn't present */
	error = tca8418_configure(keypad_data, rows, cols);
	if (error < 0)
		return error;

	/* Configure input device */
	input = devm_input_allocate_device(dev);
	if (!input)
		return -ENOMEM;

	keypad_data->input = input;

	input->name = client->name;
	input->id.bustype = BUS_I2C;
	input->id.vendor  = 0x0001;
	input->id.product = 0x001;
	input->id.version = 0x0001;

	error = matrix_keypad_build_keymap(keymap_data, NULL, rows, cols,
					   NULL, input);
	if (error) {
		dev_err(dev, "Failed to build keymap\n");
		return error;
	}

	if (rep)
		__set_bit(EV_REP, input->evbit);
	input_set_capability(input, EV_MSC, MSC_SCAN);

	input_set_drvdata(input, keypad_data);

	irq = client->irq;
	if (irq_is_gpio)
		irq = gpio_to_irq(irq);

	error = devm_request_threaded_irq(dev, irq, NULL, tca8418_irq_handler,
					  IRQF_TRIGGER_FALLING |
						IRQF_SHARED |
						IRQF_ONESHOT,
					  client->name, keypad_data);
	if (error) {
		dev_err(dev, "Unable to claim irq %d; error %d\n",
			client->irq, error);
		return error;
	}

	error = input_register_device(input);
	if (error) {
		dev_err(dev, "Unable to register input device, error: %d\n",
			error);
		return error;
	}

	return 0;
}
static int __devinit omap_kp_probe(struct platform_device *pdev)
{
	struct omap_kp *omap_kp;
	struct input_dev *input_dev;
	struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
	int i, col_idx, row_idx, irq_idx, ret;
	unsigned int row_shift, keycodemax;

	if (!pdata->rows || !pdata->cols || !pdata->keymap_data) {
		printk(KERN_ERR "No rows, cols or keymap_data from pdata\n");
		return -EINVAL;
	}

	row_shift = get_count_order(pdata->cols);
	keycodemax = pdata->rows << row_shift;

	omap_kp = kzalloc(sizeof(struct omap_kp) +
			keycodemax * sizeof(unsigned short), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!omap_kp || !input_dev) {
		kfree(omap_kp);
		input_free_device(input_dev);
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, omap_kp);

	omap_kp->input = input_dev;

	/* Disable the interrupt for the MPUIO keyboard */
	if (!cpu_is_omap24xx())
		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);

	input_dev->keycode      = &omap_kp[1];
	input_dev->keycodesize  = sizeof(unsigned short);
	input_dev->keycodemax   = keycodemax;

	if (pdata->rep)
		__set_bit(EV_REP, input_dev->evbit);

	if (pdata->delay)
		omap_kp->delay = pdata->delay;

	if (pdata->row_gpios && pdata->col_gpios) {
		row_gpios = pdata->row_gpios;
		col_gpios = pdata->col_gpios;
	}

	omap_kp->rows = pdata->rows;
	omap_kp->cols = pdata->cols;

	if (cpu_is_omap24xx()) {
		/* Cols: outputs */
		for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
			if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) {
				printk(KERN_ERR "Failed to request"
				       "GPIO%d for keypad\n",
				       col_gpios[col_idx]);
				goto err1;
			}
			gpio_direction_output(col_gpios[col_idx], 0);
		}
		/* Rows: inputs */
		for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
			if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) {
				printk(KERN_ERR "Failed to request"
				       "GPIO%d for keypad\n",
				       row_gpios[row_idx]);
				goto err2;
			}
			gpio_direction_input(row_gpios[row_idx]);
		}
	} else {
		col_idx = 0;
		row_idx = 0;
	}

	setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);

	/* get the irq and init timer*/
	tasklet_enable(&kp_tasklet);
	kp_tasklet.data = (unsigned long) omap_kp;

	ret = device_create_file(&pdev->dev, &dev_attr_enable);
	if (ret < 0)
		goto err2;

	/* setup input device */
	__set_bit(EV_KEY, input_dev->evbit);
	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
			input_dev->keycode, input_dev->keybit);
	input_dev->name = "omap-keypad";
	input_dev->phys = "omap-keypad/input0";
	input_dev->dev.parent = &pdev->dev;

	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0100;

	ret = input_register_device(omap_kp->input);
	if (ret < 0) {
		printk(KERN_ERR "Unable to register omap-keypad input device\n");
		goto err3;
	}

	if (pdata->dbounce)
		omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);

	/* scan current status and enable interrupt */
	omap_kp_scan_keypad(omap_kp, keypad_state);
	if (!cpu_is_omap24xx()) {
		omap_kp->irq = platform_get_irq(pdev, 0);
		if (omap_kp->irq >= 0) {
			if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
					"omap-keypad", omap_kp) < 0)
				goto err4;
		}
		omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
	} else {
		for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
			if (request_irq(gpio_to_irq(row_gpios[irq_idx]),
					omap_kp_interrupt,
					IRQF_TRIGGER_FALLING,
					"omap-keypad", omap_kp) < 0)
				goto err5;
		}
	}
	return 0;
err5:
	for (i = irq_idx - 1; i >=0; i--)
		free_irq(row_gpios[i], omap_kp);
err4:
	input_unregister_device(omap_kp->input);
	input_dev = NULL;
err3:
	device_remove_file(&pdev->dev, &dev_attr_enable);
err2:
	for (i = row_idx - 1; i >=0; i--)
		gpio_free(row_gpios[i]);
err1:
	for (i = col_idx - 1; i >=0; i--)
		gpio_free(col_gpios[i]);

	kfree(omap_kp);
	input_free_device(input_dev);

	return -EINVAL;
}
예제 #5
0
static int matrix_keypad_probe(struct platform_device *pdev)
{
	struct matrix_keypad_platform_data *pdata;
	struct matrix_keypad *keypad;
	struct input_dev *input_dev;
#ifdef CONFIG_SUPPORT_KEYPAD_LED
	struct device *sec_keypad;
#endif
	int err;

	pdata = dev_get_platdata(&pdev->dev);
	if (!pdata) {
		pdata = matrix_keypad_parse_dt(&pdev->dev);
		if (IS_ERR(pdata)) {
			dev_err(&pdev->dev, "no platform data defined\n");
			return PTR_ERR(pdata);
		}
	} else if (!pdata->keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!keypad || !input_dev) {
		err = -ENOMEM;
		goto err_free_mem;
	}

	keypad->input_dev = input_dev;
	keypad->pdata = pdata;
	keypad->row_shift = get_count_order(pdata->num_col_gpios);
	keypad->stopped = true;
	INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
	spin_lock_init(&keypad->lock);

	if (pdata->project)
		input_dev->name		= pdata->project;
	else
		input_dev->name		= pdev->name;

	input_dev->id.bustype	= BUS_HOST;
	input_dev->dev.parent	= &pdev->dev;
	input_dev->open		= matrix_keypad_start;
	input_dev->close	= matrix_keypad_stop;

	err = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
					 pdata->num_row_gpios,
					 pdata->num_col_gpios,
					 NULL, input_dev);
	if (err) {
		dev_err(&pdev->dev, "failed to build keymap\n");
		goto err_free_mem;
	}

	if (!pdata->no_autorepeat)
		__set_bit(EV_REP, input_dev->evbit);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
	input_set_drvdata(input_dev, keypad);

	err = matrix_keypad_init_gpio(pdev, keypad);
	if (err)
		goto err_free_mem;

	err = input_register_device(keypad->input_dev);
	if (err)
		goto err_free_gpio;

#ifdef CONFIG_SUPPORT_KEYPAD_LED
/* keypad led control */
	sec_keypad = sec_device_create(pdata, "sec_keypad");
	if (IS_ERR(sec_keypad))
		dev_err(&pdev->dev,"Failed to create device(sec_key)!\n");

	err = device_create_file(sec_keypad, &dev_attr_brightness);
	if (err) {
		dev_err(&pdev->dev,"Failed to create device file in sysfs entries(%s)!\n",
				dev_attr_brightness.attr.name);
	}

	dev_set_drvdata(sec_keypad, pdata);

	pdata->vddo_vreg = regulator_get(&pdev->dev,"vddo");
	if (IS_ERR(pdata->vddo_vreg)){
		pdata->vddo_vreg = NULL;
		printk(KERN_INFO "pdata->vddo_vreg error\n");
		err = -EPERM;
		goto err_free_gpio;
	}
#endif
	device_init_wakeup(&pdev->dev, pdata->wakeup);
	platform_set_drvdata(pdev, keypad);

	return 0;

err_free_gpio:
	matrix_keypad_free_gpio(keypad);
err_free_mem:
	input_free_device(input_dev);
	kfree(keypad);
	return err;
}
static int __devinit matrix_keypad_probe(struct platform_device *pdev)
{
	const struct matrix_keypad_platform_data *pdata;
	const struct matrix_keymap_data *keymap_data;
	struct matrix_keypad *keypad;
	struct input_dev *input_dev;
	unsigned short *keycodes;
	unsigned int row_shift;
	int err;

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data defined\n");
		return -EINVAL;
	}

	keymap_data = pdata->keymap_data;
	if (!keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	row_shift = get_count_order(pdata->num_col_gpios);

	keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
	keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
				sizeof(*keycodes),
			   GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!keypad || !keycodes || !input_dev) {
		err = -ENOMEM;
		goto err_free_mem;
	}

	keypad->input_dev = input_dev;
	keypad->pdata = pdata;
	keypad->keycodes = keycodes;
	keypad->row_shift = row_shift;
	keypad->stopped = true;
	INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
	mutex_init(&keypad->lock);

	input_dev->name		= pdev->name;
	input_dev->id.bustype	= BUS_HOST;
	input_dev->dev.parent	= &pdev->dev;
	input_dev->evbit[0]	= BIT_MASK(EV_KEY);
	if (!pdata->no_autorepeat)
		input_dev->evbit[0] |= BIT_MASK(EV_REP);
	input_dev->open		= matrix_keypad_start;
	input_dev->close	= matrix_keypad_stop;

	input_dev->keycode	= keycodes;
	input_dev->keycodesize	= sizeof(*keycodes);
	input_dev->keycodemax	= pdata->num_row_gpios << row_shift;

	matrix_keypad_build_keymap(keymap_data, row_shift,
				   input_dev->keycode, input_dev->keybit);

	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
	input_set_drvdata(input_dev, keypad);

	err = init_matrix_gpio(pdev, keypad);
	if (err)
		goto err_free_mem;

	err = input_register_device(keypad->input_dev);
	if (err)
		goto err_free_mem;

	device_init_wakeup(&pdev->dev, pdata->wakeup);
	platform_set_drvdata(pdev, keypad);

	return 0;

err_free_mem:
	input_free_device(input_dev);
	kfree(keycodes);
	kfree(keypad);
	return err;
}
static int __devinit ske_keypad_probe(struct platform_device *pdev)
{
	const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
	struct ske_keypad *keypad;
	struct input_dev *input;
	struct resource *res;
	int irq;
	int error;

	if (!plat) {
		dev_err(&pdev->dev, "invalid keypad platform data\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "failed to get keypad irq\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "missing platform resources\n");
		return -EINVAL;
	}

	keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL);
	input = input_allocate_device();
	if (!keypad || !input) {
		dev_err(&pdev->dev, "failed to allocate keypad memory\n");
		error = -ENOMEM;
		goto err_free_mem;
	}

	keypad->irq = irq;
	keypad->board = plat;
	keypad->input = input;
	spin_lock_init(&keypad->ske_keypad_lock);

	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
		dev_err(&pdev->dev, "failed to request I/O memory\n");
		error = -EBUSY;
		goto err_free_mem;
	}

	keypad->reg_base = ioremap(res->start, resource_size(res));
	if (!keypad->reg_base) {
		dev_err(&pdev->dev, "failed to remap I/O memory\n");
		error = -ENXIO;
		goto err_free_mem_region;
	}

	keypad->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(keypad->clk)) {
		dev_err(&pdev->dev, "failed to get clk\n");
		error = PTR_ERR(keypad->clk);
		goto err_iounmap;
	}

	input->id.bustype = BUS_HOST;
	input->name = "ux500-ske-keypad";
	input->dev.parent = &pdev->dev;

	input->keycode = keypad->keymap;
	input->keycodesize = sizeof(keypad->keymap[0]);
	input->keycodemax = ARRAY_SIZE(keypad->keymap);

	input_set_capability(input, EV_MSC, MSC_SCAN);

	__set_bit(EV_KEY, input->evbit);
	if (!plat->no_autorepeat)
		__set_bit(EV_REP, input->evbit);

	matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT,
			input->keycode, input->keybit);

	clk_enable(keypad->clk);

	/* go through board initialization helpers */
	if (keypad->board->init)
		keypad->board->init();

	error = ske_keypad_chip_init(keypad);
	if (error) {
		dev_err(&pdev->dev, "unable to init keypad hardware\n");
		goto err_clk_disable;
	}

	error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq,
				     IRQF_ONESHOT, "ske-keypad", keypad);
	if (error) {
		dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
		goto err_clk_disable;
	}

	error = input_register_device(input);
	if (error) {
		dev_err(&pdev->dev,
				"unable to register input device: %d\n", error);
		goto err_free_irq;
	}

	if (plat->wakeup_enable)
		device_init_wakeup(&pdev->dev, true);

	platform_set_drvdata(pdev, keypad);

	return 0;

err_free_irq:
	free_irq(keypad->irq, keypad);
err_clk_disable:
	clk_disable(keypad->clk);
	clk_put(keypad->clk);
err_iounmap:
	iounmap(keypad->reg_base);
err_free_mem_region:
	release_mem_region(res->start, resource_size(res));
err_free_mem:
	input_free_device(input);
	kfree(keypad);
	return error;
}
static int __devinit sci_keypad_probe(struct platform_device *pdev)
{

	struct sci_keypad_t *sci_kpd;
	struct input_dev *input_dev;
	struct sci_keypad_platform_data *pdata = pdev->dev.platform_data;
	int error;
	unsigned long value;
	unsigned int row_shift, keycodemax;

	row_shift = get_count_order(pdata->cols);
	keycodemax = pdata->rows << row_shift;

	sci_kpd = kzalloc(sizeof(struct sci_keypad_t) +
			  keycodemax * sizeof(unsigned short), GFP_KERNEL);
	input_dev = input_allocate_device();

	if (!sci_kpd || !input_dev) {
		kfree(sci_kpd);
		input_free_device(input_dev);
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, sci_kpd);

	sci_kpd->input_dev = input_dev;
	sci_kpd->rows = pdata->rows;
	sci_kpd->cols = pdata->cols;

	sci_glb_set(REG_GLB_SOFT_RST,BIT_KPD_RST);
	mdelay(2);
	sci_glb_clr(REG_GLB_SOFT_RST,BIT_KPD_RST);
	sci_glb_set(REG_GLB_GEN0,BIT_KPD_EB | BIT_RTC_KPD_EB);

	keypad_writel(KPD_INT_CLR, KPD_INT_ALL);
	value = CFG_ROW_POLARITY | CFG_COL_POLARITY;
	keypad_writel(KPD_POLARITY, value);
	keypad_writel(KPD_CLK_DIV_CNT, 1);
	keypad_writel(KPD_LONG_KEY_CNT, 0xc);
	keypad_writel(KPD_DEBOUNCE_CNT, 0x5);

	sci_kpd->irq = platform_get_irq(pdev, 0);
	if (sci_kpd->irq < 0) {
		error = -ENODEV;
		dev_err(&pdev->dev, "Get irq number error,Keypad Module\n");
		goto out2;
	}

	error =
	    request_irq(sci_kpd->irq, sci_keypad_isr, 0, "sci-keypad", sci_kpd);
	if (error) {
		dev_err(&pdev->dev, "unable to claim irq %d\n", sci_kpd->irq);
		goto out2;
	}

	input_dev->name = pdev->name;
	input_dev->phys = "sci-key/input0";
	input_dev->dev.parent = &pdev->dev;
	input_set_drvdata(input_dev, sci_kpd);

	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0100;

	input_dev->keycode = &sci_kpd[1];
	input_dev->keycodesize = sizeof(unsigned short);
	input_dev->keycodemax = keycodemax;

	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
				   input_dev->keycode, input_dev->keybit);

	/* there are keys from hw other than keypad controller */
	__set_bit(KEY_POWER, input_dev->keybit);

	__set_bit(EV_KEY, input_dev->evbit);
	if (pdata->repeat)
		__set_bit(EV_REP, input_dev->evbit);

	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "unable to register input device\n");
		goto out4;
	}

	device_init_wakeup(&pdev->dev, 1);

	value = KPD_INT_DOWNUP;
	if (pdata->support_long_key)
		value |= KPD_INT_LONG;
	keypad_writel(KPD_INT_EN, value);

	value = KPD_SLEEP_CNT_VALUE(1000);
	keypad_writel(KPD_SLEEP_CNT, value);

	value = KPD_SLEEP_EN | (pdata->rows_choose_hw & KPDCTL_ROW_MSK) |
	    (pdata->cols_choose_hw & KPDCTL_COL_MSK);
	if (pdata->support_long_key)
		value |= KPD_LONG_KEY_EN;
	value |= KPD_EN;
	keypad_writel(KPD_CTRL, value);

	gpio_request(ANA_GPI_PB, "powerkey");
	gpio_direction_input(ANA_GPI_PB);

	error = request_irq(gpio_to_irq(ANA_GPI_PB), sci_powerkey_isr,
			IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "powerkey", sci_kpd);
	if (error) {
		dev_err(&pdev->dev, "unable to claim irq %d\n",
			gpio_to_irq(ANA_GPI_PB));
		goto out2;
	}


	dump_keypad_register();

	return 0;

out4:
	input_free_device(input_dev);
	free_irq(sci_kpd->irq, pdev);
out2:
	kfree(sci_kpd);
	platform_set_drvdata(pdev, NULL);
	return error;
}
예제 #9
0
static int __devinit omap4_keypad_probe(struct platform_device *pdev)
{
	const struct omap4_keypad_platform_data *pdata;
	struct omap4_keypad *keypad_data;
	struct input_dev *input_dev;
	struct resource *res;
	resource_size_t size;
	unsigned int row_shift, max_keys;
	int rev;
	int irq;
	int error;

	/* platform data */
	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data defined\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no base address specified\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);
	if (!irq) {
		dev_err(&pdev->dev, "no keyboard irq assigned\n");
		return -EINVAL;
	}

	if (!pdata->keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	row_shift = get_count_order(pdata->cols);
	max_keys = pdata->rows << row_shift;

	keypad_data = kzalloc(sizeof(struct omap4_keypad) +
				max_keys * sizeof(keypad_data->keymap[0]),
			      GFP_KERNEL);
	if (!keypad_data) {
		dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
		return -ENOMEM;
	}

	size = resource_size(res);

	res = request_mem_region(res->start, size, pdev->name);
	if (!res) {
		dev_err(&pdev->dev, "can't request mem region\n");
		error = -EBUSY;
		goto err_free_keypad;
	}

	keypad_data->base = ioremap(res->start, resource_size(res));
	if (!keypad_data->base) {
		dev_err(&pdev->dev, "can't ioremap mem resource\n");
		error = -ENOMEM;
		goto err_release_mem;
	}

	keypad_data->irq = irq;
	keypad_data->row_shift = row_shift;
	keypad_data->rows = pdata->rows;
	keypad_data->cols = pdata->cols;

	/*
	* Enable clocks for the keypad module so that we can read
	* revision register.
	*/
	pm_runtime_enable(&pdev->dev);
	error = pm_runtime_get_sync(&pdev->dev);
	if (error) {
		dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
		goto err_unmap;
	}
	rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
	rev &= 0x03 << 30;
	rev >>= 30;
	switch (rev) {
	case KBD_REVISION_OMAP4:
		keypad_data->reg_offset = 0x00;
		keypad_data->irqreg_offset = 0x00;
		break;
	case KBD_REVISION_OMAP5:
		keypad_data->reg_offset = 0x10;
		keypad_data->irqreg_offset = 0x0c;
		break;
	default:
		dev_err(&pdev->dev,
			"Keypad reports unsupported revision %d", rev);
		error = -EINVAL;
		goto err_pm_put_sync;
	}

	/* input device allocation */
	keypad_data->input = input_dev = input_allocate_device();
	if (!input_dev) {
		error = -ENOMEM;
		goto err_pm_put_sync;
	}

	input_dev->name = pdev->name;
	input_dev->dev.parent = &pdev->dev;
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0001;

	input_dev->open = omap4_keypad_open;
	input_dev->close = omap4_keypad_close;

	error = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
					   pdata->rows, pdata->cols,
					   keypad_data->keymap, input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to build keymap\n");
		goto err_free_input;
	}

	__set_bit(EV_REP, input_dev->evbit);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	input_set_drvdata(input_dev, keypad_data);

	error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
			     IRQF_TRIGGER_RISING,
			     "omap4-keypad", keypad_data);
	if (error) {
		dev_err(&pdev->dev, "failed to register interrupt\n");
		goto err_free_input;
	}

	pm_runtime_put_sync(&pdev->dev);

	error = input_register_device(keypad_data->input);
	if (error < 0) {
		dev_err(&pdev->dev, "failed to register input device\n");
		goto err_pm_disable;
	}

	platform_set_drvdata(pdev, keypad_data);
	return 0;

err_pm_disable:
	pm_runtime_disable(&pdev->dev);
	free_irq(keypad_data->irq, keypad_data);
err_free_input:
	input_free_device(input_dev);
err_pm_put_sync:
	pm_runtime_put_sync(&pdev->dev);
err_unmap:
	iounmap(keypad_data->base);
err_release_mem:
	release_mem_region(res->start, size);
err_free_keypad:
	kfree(keypad_data);
	return error;
}
예제 #10
0
static int __devinit spear_kbd_probe(struct platform_device *pdev)
{
	const struct kbd_platform_data *pdata = pdev->dev.platform_data;
	const struct matrix_keymap_data *keymap;
	struct spear_kbd *kbd;
	struct input_dev *input_dev;
	struct resource *res;
	int irq;
	int error;

	if (!pdata) {
		dev_err(&pdev->dev, "Invalid platform data\n");
		return -EINVAL;
	}

	keymap = pdata->keymap;
	if (!keymap) {
		dev_err(&pdev->dev, "no keymap defined\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no keyboard resource defined\n");
		return -EBUSY;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "not able to get irq for the device\n");
		return irq;
	}

	kbd = kzalloc(sizeof(*kbd), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!kbd || !input_dev) {
		dev_err(&pdev->dev, "out of memory\n");
		error = -ENOMEM;
		goto err_free_mem;
	}

	kbd->input = input_dev;
	kbd->irq = irq;
	kbd->res = request_mem_region(res->start, resource_size(res),
				      pdev->name);
	if (!kbd->res) {
		dev_err(&pdev->dev, "keyboard region already claimed\n");
		error = -EBUSY;
		goto err_free_mem;
	}

	kbd->io_base = ioremap(res->start, resource_size(res));
	if (!kbd->io_base) {
		dev_err(&pdev->dev, "ioremap failed for kbd_region\n");
		error = -ENOMEM;
		goto err_release_mem_region;
	}

	kbd->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(kbd->clk)) {
		error = PTR_ERR(kbd->clk);
		goto err_iounmap;
	}

	input_dev->name = "Spear Keyboard";
	input_dev->phys = "keyboard/input0";
	input_dev->dev.parent = &pdev->dev;
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0100;
	input_dev->open = spear_kbd_open;
	input_dev->close = spear_kbd_close;

	__set_bit(EV_KEY, input_dev->evbit);
	if (pdata->rep)
		__set_bit(EV_REP, input_dev->evbit);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	input_dev->keycode = kbd->keycodes;
	input_dev->keycodesize = sizeof(kbd->keycodes[0]);
	input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes);

	matrix_keypad_build_keymap(keymap, ROW_SHIFT,
			input_dev->keycode, input_dev->keybit);

	input_set_drvdata(input_dev, kbd);

	error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd);
	if (error) {
		dev_err(&pdev->dev, "request_irq fail\n");
		goto err_put_clk;
	}

	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "Unable to register keyboard device\n");
		goto err_free_irq;
	}

	device_init_wakeup(&pdev->dev, 1);
	platform_set_drvdata(pdev, kbd);

	return 0;

err_free_irq:
	free_irq(kbd->irq, kbd);
err_put_clk:
	clk_put(kbd->clk);
err_iounmap:
	iounmap(kbd->io_base);
err_release_mem_region:
	release_mem_region(res->start, resource_size(res));
err_free_mem:
	input_free_device(input_dev);
	kfree(kbd);

	return error;
}
예제 #11
0
/******************************************************************************
 * struct platform_driver functions
 *****************************************************************************/
static int __devinit ftkbc010_probe(struct platform_device *pdev)
{
	struct matrix_keypad_platform_data *pdata = pdev->dev.platform_data;
	struct device *dev = &pdev->dev;
	struct ftkbc010 *ftkbc010;
	struct input_dev *input;
	struct resource *res;
	unsigned int row_shift, max_keys;
	int irq;
	int ret;

	if (!pdata) {
		dev_err(&pdev->dev, "no platform data defined\n");
		return -EINVAL;
	}

	if (!pdata->keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "No mmio resource defined.\n");
		return -ENXIO;
	}

	if ((irq = platform_get_irq(pdev, 0)) < 0) {
		dev_err(dev, "No irq resource defined.\n");
		ret = irq;
		goto err_get_irq;
	}

	/*
	 * Allocate driver private data
	 */
	ftkbc010 = kzalloc(sizeof(struct ftkbc010), GFP_KERNEL);
	if (!ftkbc010) {
		dev_err(dev, "Failed to allocate memory.\n");
		ret = -ENOMEM;
		goto err_alloc_priv;
	}
	platform_set_drvdata(pdev, ftkbc010);

	/*
	 * Allocate input_dev
	 */
	input = input_allocate_device();
	if (!input) {
		dev_err(dev, "Failed to allocate input device.\n");
		ret = -EBUSY;
		goto err_alloc_input_dev;
	}
	ftkbc010->input = input;

	/*
	 * Map io memory
	 */
	ftkbc010->res = request_mem_region(res->start, resource_size(res), dev_name(dev));
	if (!ftkbc010->res) {
		dev_err(dev, "Resources is unavailable.\n");
		ret = -EBUSY;
		goto err_req_mem_region;
	}

	ftkbc010->base = ioremap(res->start, resource_size(res));
	if (!ftkbc010->base) {
		dev_err(dev, "Failed to map registers.\n");
		ret = -ENOMEM;
		goto err_ioremap;
	}

	ret = request_irq(irq, ftkbc010_interrupt, 0, pdev->name, ftkbc010);
	if (ret < 0) {
		dev_err(dev, "Failed to request irq %d\n", irq);
		goto err_req_irq;
	}
	ftkbc010->irq = irq;

	row_shift = get_count_order(pdata->num_col_gpios);
	max_keys = pdata->num_row_gpios << row_shift;
	ftkbc010->rows = pdata->num_row_gpios;
	ftkbc010->cols = pdata->num_col_gpios;
	ftkbc010->row_shift = row_shift;

	input->name = "Faraday keyboard controller";
	input->keycode		= ftkbc010->keycode;
	input->keycodesize	= sizeof(ftkbc010->keycode[0]);
	input->keycodemax	= max_keys;

	/*
	 * Declare what events and event codes can be generated
	 */
	input->evbit[0] = BIT_MASK(EV_KEY);

	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
				   input->keycode, input->keybit);

	/*
	 * Enable hardware
	 */
	ftkbc010_enable(ftkbc010);

	/*
	 * All went ok, so register to the input system
	 */
	ret = input_register_device(input);
	if (ret)
		goto err_register_input;

	dev_info(dev, "irq %d, mapped at %p\n", irq, ftkbc010->base);
	return 0;

err_register_input:
	free_irq(irq, ftkbc010);
err_req_irq:
	iounmap(ftkbc010->base);
err_ioremap:
	release_mem_region(res->start, resource_size(res));
err_req_mem_region:
	input_free_device(ftkbc010->input);
err_alloc_input_dev:
	platform_set_drvdata(pdev, NULL);
	kfree(ftkbc010);
err_alloc_priv:
err_get_irq:
	release_resource(res);
	return ret;
}
예제 #12
0
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
	struct omap4_keypad *keypad_data = dev_id;
	struct input_dev *input_dev = keypad_data->input;
	unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)];
	unsigned int col, row, code, changed;
	u32 *new_state = (u32 *) key_state;

	/* LGE_SJIT 2012-01-05 [[email protected]] wake lock from P940 GB
	 * 2011.12.07 [email protected] For Volume Control.
	 */
	wake_lock_timeout(&keypad_data->wlock, 1 * HZ);

	*new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
	*(new_state + 1) = __raw_readl(keypad_data->base
						+ OMAP4_KBD_FULLCODE63_32);

	// LGE_CHANGE_S [[email protected]] 2012-06-06 , add to check H/W status
	if(debug_mask) {
		printk("========================================================\n");
		printk("%s: [%#x][%#x]\n", __func__, *new_state, *(new_state+1));
		printk("========================================================\n");
	}
	// LGE_CHANGE_E [[email protected]] 2012-06-06

	for (col = 0; col < keypad_data->cols; col++) {
		changed = key_state[col] ^ keypad_data->key_state[col];

		if (!changed)
			continue;
		for (row = 0; row < keypad_data->rows; row++) {
			if (changed & (1 << row)) {
				code = MATRIX_SCAN_CODE(row, col,
						keypad_data->row_shift);

				// LGE_CHANGE_S [[email protected]] 2012-06-06 , add to check H/W status
				if(debug_mask) {
					printk("%s: [changed][col][row][code] = [%#x][%d][%d][%d]\n", __func__, changed, col, row, code);
					printk("========================================================\n");
				}
				// LGE_CHANGE_E [[email protected]] 2012-06-06

                                //[email protected] => [START]  keylock command
#ifdef CONFIG_MACH_LGE_COSMO
				if( keypad_data->keymap[code] && !atcmd_keylock) {
#else
				if( keypad_data->keymap[code] ) {
#endif
                                //[email protected] <= [END]
				    input_event(input_dev, EV_MSC, MSC_SCAN, code);
				    input_report_key(input_dev,
                            keypad_data->keymap[code],
                            (bool)(key_state[col] & (1 << row)));

#ifdef CONFIG_MACH_LGE_U2	/* [email protected] - 2012/05/21 - the HOME_key is added */
                    printk("[omap4-keypad] %s KEY %s\n",
                                                (keypad_data->keymap[code] == KEY_VOLUMEUP) ? "Vol_UP" : ((keypad_data->keymap[code] == KEY_VOLUMEDOWN) ? "Vol_DOWN" : "HOME"),
                                                (key_state[col] & (1 << row)) ? "PRESS" : "RELEASE" );
#else
                    printk("[omap4-keypad] %s KEY %s\n",
						(keypad_data->keymap[code] == KEY_VOLUMEUP) ? "Vol_UP" : ((keypad_data->keymap[code] == KEY_VOLUMEDOWN) ? "Vol_DOWN" : "CAPTURE"),
						(key_state[col] & (1 << row)) ? "PRESS" : "RELEASE" );
#endif

#ifdef CONFIG_INPUT_LGE_GKPD
                    gkpd_report_key(keypad_data->keymap[code], (bool)(key_state[col] & (1 << row)));
#endif

                    break;
				}

				/* LGE_SJIT 2012-01-05 [[email protected]]
				 * for Android SafeMode
				 * [[email protected]] 2011-06-10,
				 * [P940] for enable the saving-mode
				 */
#ifdef CONFIG_KEYBOARD_OMAP4_SAFEMODE
				if (keypad_data->keymap[code] == KEY_VOLUMEUP) {
					safemode_key = !!(key_state[col] & (1 << row));
				}
#endif
			}
		}
	}

	input_sync(input_dev);

	memcpy(keypad_data->key_state, key_state,
		sizeof(keypad_data->key_state));

	/* clear pending interrupts */
	__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
			keypad_data->base + OMAP4_KBD_IRQSTATUS);


	printk("#################################### %s is finished!!!!!\n", __func__);
	return IRQ_HANDLED;
}

static int omap4_keypad_open(struct input_dev *input)
{
	struct omap4_keypad *keypad_data = input_get_drvdata(input);

#ifdef KBD_DEBUG
	printk("omap4-keypad: omap4_keypad_open \n");
#endif

	pm_runtime_get_sync(input->dev.parent);

	disable_irq(keypad_data->irq);

	__raw_writel(OMAP4_DEF_CTRL_NOSOFTMODE |
			(OMAP4_VAL_PVT << OMAP4_DEF_CTRL_PTV),
			keypad_data->base + OMAP4_KBD_CTRL);

	__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
			keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);

	/* Enable event IRQ*/
	__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN,
			keypad_data->base + OMAP4_KBD_IRQENABLE);

	/* Enable event wkup*/
	__raw_writel(OMAP4_DEF_WUP_EVENT_ENA,
			keypad_data->base + OMAP4_KBD_WAKEUPENABLE);

	/* clear pending interrupts */
	__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
			keypad_data->base + OMAP4_KBD_IRQSTATUS);
	enable_irq(keypad_data->irq);

	return 0;
}

static void omap4_keypad_close(struct input_dev *input)
{
	struct omap4_keypad *keypad_data = input_get_drvdata(input);

	disable_irq(keypad_data->irq);

	/* Disable interrupts */
	__raw_writel(OMAP4_VAL_IRQDISABLE,
		     keypad_data->base + OMAP4_KBD_IRQENABLE);

	/* clear pending interrupts */
	__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
			keypad_data->base + OMAP4_KBD_IRQSTATUS);

	enable_irq(keypad_data->irq);

#ifdef KBD_DEBUG
	printk("omap4-keypad: omap4_keypad_close \n");
#endif

	pm_runtime_put_sync(input->dev.parent);
}

static int __devinit omap4_keypad_probe(struct platform_device *pdev)
{
	const struct omap4_keypad_platform_data *pdata;
	struct omap4_keypad *keypad_data;
	struct input_dev *input_dev;
	struct resource *res;
	resource_size_t size;
	unsigned int row_shift, max_keys;
	int irq;
	int error;

	/* platform data */
	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data defined\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no base address specified\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);
	if (!irq) {
		dev_err(&pdev->dev, "no keyboard irq assigned\n");
		return -EINVAL;
	}

	if (!pdata->keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	row_shift = get_count_order(pdata->cols);
	max_keys = pdata->rows << row_shift;

	keypad_data = kzalloc(sizeof(struct omap4_keypad) +
				max_keys * sizeof(keypad_data->keymap[0]),
			      GFP_KERNEL);
	if (!keypad_data) {
		dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
		return -ENOMEM;
	}

	size = resource_size(res);

	res = request_mem_region(res->start, size, pdev->name);
	if (!res) {
		dev_err(&pdev->dev, "can't request mem region\n");
		error = -EBUSY;
		goto err_free_keypad;
	}

	keypad_data->base = ioremap(res->start, resource_size(res));
	if (!keypad_data->base) {
		dev_err(&pdev->dev, "can't ioremap mem resource\n");
		error = -ENOMEM;
		goto err_release_mem;
	}

	keypad_data->irq = irq;
	keypad_data->row_shift = row_shift;
	keypad_data->rows = pdata->rows;
	keypad_data->cols = pdata->cols;
	keypad_data->keypad_pad_wkup = pdata->keypad_pad_wkup;

	/* input device allocation */
	keypad_data->input = input_dev = input_allocate_device();
	if (!input_dev) {
		error = -ENOMEM;
		goto err_unmap;
	}

	input_dev->name = pdev->name;
	input_dev->dev.parent = &pdev->dev;
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0001;

	input_dev->open = omap4_keypad_open;
	input_dev->close = omap4_keypad_close;

	input_dev->keycode	= keypad_data->keymap;
	input_dev->keycodesize	= sizeof(keypad_data->keymap[0]);
	input_dev->keycodemax	= max_keys;

	__set_bit(EV_KEY, input_dev->evbit);
	__set_bit(EV_REP, input_dev->evbit);

	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	input_set_drvdata(input_dev, keypad_data);

	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
			input_dev->keycode, input_dev->keybit);

	/* LGE_SJIT 2011-12-06 [[email protected]] MHL keybits
	 * jk.koo kibu.lee 20110810 MHL RCP codes into media keys and
	 * transfer these to the input manager
	 */
#if defined(CONFIG_MHL_INPUT_RCP)
	hdmi_common_register_keys(input_dev);
#endif
	/* LGE_SJIT 2011-12-09 [[email protected]] for hook key */
#if defined(CONFIG_SND_OMAP_SOC_LGE_JACK)
	__set_bit(KEY_HOOK, input_dev->keybit);
#endif
	/* LGE_SJIT 2011-01-05 [[email protected]] Add wake lock */
	wake_lock_init(&keypad_data->wlock, WAKE_LOCK_SUSPEND, "omap4-keypad");

	/*
	 * Set irq level detection for mpu. Edge event are missed
	 * in gic if the mpu is in low power and keypad event
	 * is a wakeup.
	 */
	error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
			     IRQF_TRIGGER_HIGH,
			     "omap4-keypad", keypad_data);
	if (error) {
		dev_err(&pdev->dev, "failed to register interrupt\n");
		goto err_free_input;
	}
	enable_irq_wake(OMAP44XX_IRQ_KBD_CTL);

	pm_runtime_enable(&pdev->dev);

	error = input_register_device(keypad_data->input);
	if (error < 0) {
		dev_err(&pdev->dev, "failed to register input device\n");
		goto err_pm_disable;
	}

	platform_set_drvdata(pdev, keypad_data);

	/* LGE_SJIT 2012-01-05 [[email protected]] for Android SafeMode
	 * [[email protected]] 2011-06-10, [P940] for enable the saving-mode
	 */
#ifdef CONFIG_KEYBOARD_OMAP4_SAFEMODE
	error = device_create_file(&pdev->dev, &dev_attr_key_saving);
	if (error < 0) {
		dev_warn(&pdev->dev, "failed to create sysfs for key_saving\n");
	}
#endif

// LGE_CHANGE_S [[email protected]] 2012-06-06 , add debug_mask to check the H/W status for keypad immediately
	error = device_create_file(&pdev->dev, &dev_attr_keypad_debug);
	if (error < 0) {
		dev_warn(&pdev->dev, "failed to create sysfs for keypad_debug\n");
	}
// LGE_CHANGE_E [[email protected]] 2012-06-06

//[email protected] => [START]  keylock command
#ifdef CONFIG_MACH_LGE_COSMO
	error = device_create_file(&pdev->dev, &dev_attr_keylock);
	if (error) {
		printk( "keypad: keylock create file: Fail\n");
		device_remove_file(&pdev->dev, &dev_attr_keylock);
	}
#endif
//[email protected] <= [END]

	/* LGE_SJIT 2011-12-06 [[email protected]] export input handle */
#ifdef CONFIG_MACH_LGE
	lge_input_set(input_dev);
#endif

	return 0;

err_pm_disable:
	pm_runtime_disable(&pdev->dev);
	free_irq(keypad_data->irq, keypad_data);
	/* LGE_SJIT 2011-01-05 [[email protected]] Add wake lock */
	wake_lock_destroy(&keypad_data->wlock);
err_free_input:
	input_free_device(input_dev);
err_unmap:
	iounmap(keypad_data->base);
err_release_mem:
	release_mem_region(res->start, size);
err_free_keypad:
	kfree(keypad_data);
	return error;
}

static int __devexit omap4_keypad_remove(struct platform_device *pdev)
{
	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
	struct resource *res;

// LGE_CHANGE_S [[email protected]] 2012-06-06 , add debug_mask to check the H/W status for keypad immediately
	device_remove_file(&pdev->dev, &dev_attr_keypad_debug);
// LGE_CHANGE_E [[email protected]] 2012-06-06

//[email protected] => [START]  keylock command
#ifdef CONFIG_MACH_LGE_COSMO
	device_remove_file(&pdev->dev, &dev_attr_keylock);
#endif
//[email protected] <= [END]

	/* LGE_SJIT 2012-01-05 [[email protected]] for Android SafeMode
	 * [[email protected]] 2011-06-10, [P940] for enable the saving-mode
	 */
#ifdef CONFIG_KEYBOARD_OMAP4_SAFEMODE
	device_remove_file(&pdev->dev, &dev_attr_key_saving);
#endif

	free_irq(keypad_data->irq, keypad_data);

	/* LGE_SJIT 2011-01-05 [[email protected]] Add wake lock */
	wake_lock_destroy(&keypad_data->wlock);

	pm_runtime_disable(&pdev->dev);

	input_unregister_device(keypad_data->input);

	iounmap(keypad_data->base);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	release_mem_region(res->start, resource_size(res));

	kfree(keypad_data);
	platform_set_drvdata(pdev, NULL);

	return 0;
}
static int omap4_keypad_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);

	if (keypad_data->keypad_pad_wkup)
		keypad_data->keypad_pad_wkup(1);

	return 0;
}
static int omap4_keypad_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);

	if (keypad_data->keypad_pad_wkup)
		keypad_data->keypad_pad_wkup(0);

	return 0;
}
static const struct dev_pm_ops omap4_keypad_pm_ops = {
	.suspend = omap4_keypad_suspend,
	.resume = omap4_keypad_resume,
};

static struct platform_driver omap4_keypad_driver = {
	.probe		= omap4_keypad_probe,
	.remove		= __devexit_p(omap4_keypad_remove),
	.driver		= {
		.name	= "omap4-keypad",
		.owner	= THIS_MODULE,
		.pm	= &omap4_keypad_pm_ops,
	},
};

static int __init omap4_keypad_init(void)
{
	return platform_driver_register(&omap4_keypad_driver);
}
module_init(omap4_keypad_init);

static void __exit omap4_keypad_exit(void)
{
	platform_driver_unregister(&omap4_keypad_driver);
}
예제 #13
0
/*
 * keypad controller should be initialized in the following sequence
 * only, otherwise it might get into FSM stuck state.
 *
 * - Initialize keypad control parameters, like no. of rows, columns,
 *   timing values etc.,
 * - configure rows and column gpios pull up/down.
 * - set irq edge type.
 * - enable the keypad controller.
 */
static int pmic8xxx_kp_probe(struct platform_device *pdev)
{
	unsigned int rows, cols;
	bool repeat;
	bool wakeup;
	struct pmic8xxx_kp *kp;
	int rc;
	unsigned int ctrl_val;

	rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols);
	if (rc)
		return rc;

	if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS ||
	    cols < PM8XXX_MIN_COLS) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	repeat = !of_property_read_bool(pdev->dev.of_node,
					"linux,input-no-autorepeat");
	wakeup = of_property_read_bool(pdev->dev.of_node,
					"linux,keypad-wakeup");

	kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	kp->regmap = dev_get_regmap(pdev->dev.parent, NULL);
	if (!kp->regmap)
		return -ENODEV;

	platform_set_drvdata(pdev, kp);

	kp->num_rows	= rows;
	kp->num_cols	= cols;
	kp->dev		= &pdev->dev;

	kp->input = devm_input_allocate_device(&pdev->dev);
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		return -ENOMEM;
	}

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		return kp->key_sense_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		return kp->key_stuck_irq;
	}

	kp->input->name = "PMIC8XXX keypad";
	kp->input->phys = "pmic8xxx_keypad/input0";

	kp->input->id.bustype	= BUS_I2C;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->open		= pmic8xxx_kp_open;
	kp->input->close	= pmic8xxx_kp_close;

	rc = matrix_keypad_build_keymap(NULL, NULL,
					PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS,
					kp->keycodes, kp->input);
	if (rc) {
		dev_err(&pdev->dev, "failed to build keymap\n");
		return rc;
	}

	if (repeat)
		__set_bit(EV_REP, kp->input->evbit);
	input_set_capability(kp->input, EV_MSC, MSC_SCAN);

	input_set_drvdata(kp->input, kp);

	/* initialize keypad state */
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8xxx_kpd_init(kp, pdev);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		return rc;
	}

	rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq,
			pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad",
			kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		return rc;
	}

	rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq,
			pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING,
			"pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		return rc;
	}

	rc = regmap_read(kp->regmap, KEYP_CTRL, &ctrl_val);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
		return rc;
	}

	kp->ctrl_reg = ctrl_val;

	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		return rc;
	}

	device_init_wakeup(&pdev->dev, wakeup);

	return 0;
}
static int spear_kbd_probe(struct platform_device *pdev)
{
	struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev);
	const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL;
	struct spear_kbd *kbd;
	struct input_dev *input_dev;
	struct resource *res;
	int irq;
	int error;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "not able to get irq for the device\n");
		return irq;
	}

	kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL);
	if (!kbd) {
		dev_err(&pdev->dev, "not enough memory for driver data\n");
		return -ENOMEM;
	}

	input_dev = devm_input_allocate_device(&pdev->dev);
	if (!input_dev) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		return -ENOMEM;
	}

	kbd->input = input_dev;
	kbd->irq = irq;

	if (!pdata) {
		error = spear_kbd_parse_dt(pdev, kbd);
		if (error)
			return error;
	} else {
		kbd->mode = pdata->mode;
		kbd->rep = pdata->rep;
		kbd->suspended_rate = pdata->suspended_rate;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	kbd->io_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(kbd->io_base))
		return PTR_ERR(kbd->io_base);

	kbd->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(kbd->clk))
		return PTR_ERR(kbd->clk);

	input_dev->name = "Spear Keyboard";
	input_dev->phys = "keyboard/input0";
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0100;
	input_dev->open = spear_kbd_open;
	input_dev->close = spear_kbd_close;

	error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS,
					   kbd->keycodes, input_dev);
	if (error) {
		dev_err(&pdev->dev, "Failed to build keymap\n");
		return error;
	}

	if (kbd->rep)
		__set_bit(EV_REP, input_dev->evbit);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	input_set_drvdata(input_dev, kbd);

	error = devm_request_irq(&pdev->dev, irq, spear_kbd_interrupt, 0,
			"keyboard", kbd);
	if (error) {
		dev_err(&pdev->dev, "request_irq failed\n");
		return error;
	}

	error = clk_prepare(kbd->clk);
	if (error)
		return error;

	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "Unable to register keyboard device\n");
		clk_unprepare(kbd->clk);
		return error;
	}

	device_init_wakeup(&pdev->dev, 1);
	platform_set_drvdata(pdev, kbd);

	return 0;
}
예제 #15
0
static int __devinit imx_keypad_probe(struct platform_device *pdev)
{
	const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
	struct imx_keypad *keypad;
	struct input_dev *input_dev;
	struct resource *res;
	int irq, error, i;

	if (keymap_data == NULL) {
		dev_err(&pdev->dev, "no keymap defined\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "no irq defined in platform data\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "no I/O memory defined in platform data\n");
		return -EINVAL;
	}

	res = request_mem_region(res->start, resource_size(res), pdev->name);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to request I/O memory\n");
		return -EBUSY;
	}

	input_dev = input_allocate_device();
	if (!input_dev) {
		dev_err(&pdev->dev, "failed to allocate the input device\n");
		error = -ENOMEM;
		goto failed_rel_mem;
	}

	keypad = kzalloc(sizeof(struct imx_keypad), GFP_KERNEL);
	if (!keypad) {
		dev_err(&pdev->dev, "not enough memory for driver data\n");
		error = -ENOMEM;
		goto failed_free_input;
	}

	keypad->input_dev = input_dev;
	keypad->irq = irq;
	keypad->stable_count = 0;

	setup_timer(&keypad->check_matrix_timer,
		    imx_keypad_check_for_events, (unsigned long) keypad);

	keypad->mmio_base = ioremap(res->start, resource_size(res));
	if (keypad->mmio_base == NULL) {
		dev_err(&pdev->dev, "failed to remap I/O memory\n");
		error = -ENOMEM;
		goto failed_free_priv;
	}

	keypad->clk = clk_get(&pdev->dev, "kpp");
	if (IS_ERR(keypad->clk)) {
		dev_err(&pdev->dev, "failed to get keypad clock\n");
		error = PTR_ERR(keypad->clk);
		goto failed_unmap;
	}

	/* Search for rows and cols enabled */
	for (i = 0; i < keymap_data->keymap_size; i++) {
		keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]);
		keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]);
	}

	if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) ||
	   keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) {
		dev_err(&pdev->dev,
			"invalid key data (too many rows or colums)\n");
		error = -EINVAL;
		goto failed_clock_put;
	}
	dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
	dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);

	/* Init the Input device */
	input_dev->name = pdev->name;
	input_dev->id.bustype = BUS_HOST;
	input_dev->dev.parent = &pdev->dev;
	input_dev->open = imx_keypad_open;
	input_dev->close = imx_keypad_close;
	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
	input_dev->keycode = keypad->keycodes;
	input_dev->keycodesize = sizeof(keypad->keycodes[0]);
	input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);

	matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT,
				keypad->keycodes, input_dev->keybit);

	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
	input_set_drvdata(input_dev, keypad);

	/* Ensure that the keypad will stay dormant until opened */
	imx_keypad_inhibit(keypad);

	error = request_irq(irq, imx_keypad_irq_handler, 0,
			    pdev->name, keypad);
	if (error) {
		dev_err(&pdev->dev, "failed to request IRQ\n");
		goto failed_clock_put;
	}

	/* Register the input device */
	error = input_register_device(input_dev);
	if (error) {
		dev_err(&pdev->dev, "failed to register input device\n");
		goto failed_free_irq;
	}

	platform_set_drvdata(pdev, keypad);
	device_init_wakeup(&pdev->dev, 1);

	return 0;

failed_free_irq:
	free_irq(irq, pdev);
failed_clock_put:
	clk_put(keypad->clk);
failed_unmap:
	iounmap(keypad->mmio_base);
failed_free_priv:
	kfree(keypad);
failed_free_input:
	input_free_device(input_dev);
failed_rel_mem:
	release_mem_region(res->start, resource_size(res));
	return error;
}
static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
{
	const struct pm8xxx_keypad_platform_data *pdata =
					dev_get_platdata(&pdev->dev);
	const struct matrix_keymap_data *keymap_data;
	struct pmic8xxx_kp *kp;
	int rc;
	u8 ctrl_val;
	struct device *sec_key;

	struct pm_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
		.output_value	= 0,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= PM_GPIO_VIN_S4,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	struct pm_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_31P5,
		.vin_sel	= PM_GPIO_VIN_S4,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};


	if (!pdata || !pdata->num_cols || !pdata->num_rows ||
		pdata->num_cols > PM8XXX_MAX_COLS ||
		pdata->num_rows > PM8XXX_MAX_ROWS ||
		pdata->num_cols < PM8XXX_MIN_COLS) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	if (!pdata->scan_delay_ms ||
		pdata->scan_delay_ms > MAX_SCAN_DELAY ||
		pdata->scan_delay_ms < MIN_SCAN_DELAY ||
		!is_power_of_2(pdata->scan_delay_ms)) {
		dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
		return -EINVAL;
	}

	if (!pdata->row_hold_ns ||
		pdata->row_hold_ns > MAX_ROW_HOLD_DELAY ||
		pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
		((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
		dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
		return -EINVAL;
	}

	if (!pdata->debounce_ms ||
		((pdata->debounce_ms % 5) != 0) ||
		pdata->debounce_ms > MAX_DEBOUNCE_TIME ||
		pdata->debounce_ms < MIN_DEBOUNCE_TIME) {
		dev_err(&pdev->dev, "invalid debounce time supplied\n");
		return -EINVAL;
	}

	keymap_data = pdata->keymap_data;
	if (!keymap_data) {
		dev_err(&pdev->dev, "no keymap data supplied\n");
		return -EINVAL;
	}

	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	platform_set_drvdata(pdev, kp);

	kp->pdata	= pdata;
	kp->dev		= &pdev->dev;

	kp->input = input_allocate_device();
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		rc = -ENOMEM;
		goto err_alloc_device;
	}

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->input->name = pdata->input_name ? : "PMIC8XXX keypad";
	kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0";

	kp->input->dev.parent	= &pdev->dev;

	kp->input->id.bustype	= BUS_I2C;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->evbit[0]	= BIT_MASK(EV_KEY);

	if (pdata->rep)
		__set_bit(EV_REP, kp->input->evbit);

	kp->input->keycode	= kp->keycodes;
	kp->input->keycodemax	= PM8XXX_MATRIX_MAX_SIZE;
	kp->input->keycodesize	= sizeof(kp->keycodes);
	kp->input->open		= pmic8xxx_kp_open;
	kp->input->close	= pmic8xxx_kp_close;

	matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT,
					kp->input->keycode, kp->input->keybit);

	get_volumekey_matrix(keymap_data,
					&volup_matrix, &voldown_matrix);

	input_set_capability(kp->input, EV_MSC, MSC_SCAN);
	input_set_drvdata(kp->input, kp);

	/* initialize keypad state */
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8xxx_kpd_init(kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		goto err_get_irq;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start,
					pdata->num_cols, kp, &kypd_sns);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
		goto err_gpio_config;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start,
					pdata->num_rows, kp, &kypd_drv);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
		goto err_gpio_config;
	}

	rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		goto err_get_irq;
	}

	rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		goto err_req_stuck_irq;
	}

	rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
		goto err_pmic_reg_read;
	}

	rc = request_threaded_irq(MSM_GPIO_KEY_VOLUP_IRQ ,
		NULL, pmic8058_volume_up_irq, IRQF_TRIGGER_RISING |
		IRQF_TRIGGER_FALLING, "vol_up", kp);

	if (rc < 0) {
				dev_err(&pdev->dev, "failed to request vol_up irq\n");
		goto err_req_sense_irq;
	}

	rc = request_threaded_irq(MSM_GPIO_KEY_VOLDOWN_IRQ ,
		NULL, pmic8058_volume_down_irq, IRQF_TRIGGER_RISING |
		IRQF_TRIGGER_FALLING, "vol_down", kp);

	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request vol_down irq\n");
		goto err_req_sense_irq;
	}
	kp->ctrl_reg = ctrl_val;

#if defined CONFIG_MACH_VITAL2REFRESH


	gpio_tlmm_config(GPIO_CFG(MSM_HALL_IC, 1, GPIO_CFG_INPUT,
		GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE);

	input_set_capability(kp->input, EV_SW, SW_LID);

	if (gpio_get_value(MSM_HALL_IC)) {
		input_report_switch(kp->input, SW_LID, 1);
	}
	else {
		input_report_switch(kp->input, SW_LID, 0);
	}

	input_sync(kp->input);

	printk(KERN_INFO "[input_report_switch] slide_int - !gpio_hall_ic %s\n",
			gpio_get_value(MSM_HALL_IC) == 0 ? "OPEN" : "CLOSE");

	rc = request_threaded_irq(MSM_GPIO_TO_INT(MSM_HALL_IC), NULL,
		hall_ic_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
							"hall_ic", kp);

	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request hall_ic irq\n");
		goto err_hall_ic_irq;
	}

#endif
	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		goto err_pmic_reg_read;
	}

	sec_key = device_create(sec_class, NULL, 0, NULL, "sec_key");
	if (IS_ERR(sec_key))
		pr_err("Failed to create device(sec_key)!\n");

	rc = device_create_file(sec_key, &dev_attr_sec_key_pressed);
	if (rc) {
		pr_err("Failed to create device file - pressed(%s), err(%d)!\n",
				dev_attr_sec_key_pressed.attr.name, rc);
	}

	dev_set_drvdata(sec_key, kp);

	device_init_wakeup(&pdev->dev, pdata->wakeup);

	return 0;

err_pmic_reg_read:
	free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq:
	free_irq(kp->key_sense_irq, kp);
#if defined CONFIG_MACH_VITAL2REFRESH
err_hall_ic_irq:
#endif
err_req_sense_irq:
err_gpio_config:
err_get_irq:
	input_free_device(kp->input);
err_alloc_device:
	platform_set_drvdata(pdev, NULL);
	kfree(kp);
	return rc;
}

static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
{
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);

	device_init_wakeup(&pdev->dev, 0);
	free_irq(kp->key_stuck_irq, kp);
	free_irq(kp->key_sense_irq, kp);
	input_unregister_device(kp->input);
	kfree(kp);

	platform_set_drvdata(pdev, NULL);
	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_kp_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		enable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

#if defined CONFIG_MACH_VITAL2REFRESH
	enable_irq_wake(MSM_GPIO_TO_INT(MSM_HALL_IC));
	/* to wakeup in case of sleep */
#endif
		if (input_dev->users)
			pmic8xxx_kp_disable(kp);

		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}

static int pmic8xxx_kp_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		disable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

#if defined CONFIG_MACH_VITAL2REFRESH
	disable_irq_wake(MSM_GPIO_TO_INT(MSM_HALL_IC)); /* to match irq pair */
#endif
	if (input_dev->users)
		pmic8xxx_kp_enable(kp);
		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
			 pmic8xxx_kp_suspend, pmic8xxx_kp_resume);

static struct platform_driver pmic8xxx_kp_driver = {
	.probe		= pmic8xxx_kp_probe,
	.remove		= __devexit_p(pmic8xxx_kp_remove),
	.driver		= {
		.name = PM8XXX_KEYPAD_DEV_NAME,
		.owner = THIS_MODULE,
		.pm = &pm8xxx_kp_pm_ops,
	},
};

static int __init pmic8xxx_kp_init(void)
{
	return platform_driver_register(&pmic8xxx_kp_driver);
}
module_init(pmic8xxx_kp_init);

static void __exit pmic8xxx_kp_exit(void)
{
	platform_driver_unregister(&pmic8xxx_kp_driver);
}
module_exit(pmic8xxx_kp_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PMIC8XXX keypad driver");
MODULE_VERSION("1.0");
MODULE_ALIAS("platform:pmic8xxx_keypad");
MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
예제 #17
0
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
{
	struct cros_ec_command msg = {
		.version = 0,
		.command = EC_CMD_MKBP_STATE,
		.outdata = NULL,
		.outsize = 0,
		.indata = kb_state,
		.insize = ckdev->cols,
	};

	return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
}

static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
{
	struct cros_ec_keyb *ckdev = data;
	struct cros_ec_device *ec = ckdev->ec;
	int ret;
	uint8_t kb_state[ckdev->cols];

	if (device_may_wakeup(ec->dev))
		pm_wakeup_event(ec->dev, 0);

	ret = cros_ec_keyb_get_state(ckdev, kb_state);
	if (ret >= 0)
		cros_ec_keyb_process(ckdev, kb_state, ret);
	else
		dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);

	return IRQ_HANDLED;
}

static int cros_ec_keyb_open(struct input_dev *dev)
{
	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
	struct cros_ec_device *ec = ckdev->ec;

	return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
					"cros_ec_keyb", ckdev);
}

static void cros_ec_keyb_close(struct input_dev *dev)
{
	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
	struct cros_ec_device *ec = ckdev->ec;

	free_irq(ec->irq, ckdev);
}

static int cros_ec_keyb_probe(struct platform_device *pdev)
{
	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
	struct device *dev = ec->dev;
	struct cros_ec_keyb *ckdev;
	struct input_dev *idev;
	struct device_node *np;
	int err;

	np = pdev->dev.of_node;
	if (!np)
		return -ENODEV;

	ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL);
	if (!ckdev)
		return -ENOMEM;
	err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows,
					    &ckdev->cols);
	if (err)
		return err;
	ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
	if (!ckdev->old_kb_state)
		return -ENOMEM;

	idev = devm_input_allocate_device(&pdev->dev);
	if (!idev)
		return -ENOMEM;

	if (!ec->irq) {
		dev_err(dev, "no EC IRQ specified\n");
		return -EINVAL;
	}

	ckdev->ec = ec;
	ckdev->dev = dev;
	dev_set_drvdata(&pdev->dev, ckdev);

	idev->name = ec->ec_name;
	idev->phys = ec->phys_name;
	__set_bit(EV_REP, idev->evbit);

	idev->id.bustype = BUS_VIRTUAL;
	idev->id.version = 1;
	idev->id.product = 0;
	idev->dev.parent = &pdev->dev;
	idev->open = cros_ec_keyb_open;
	idev->close = cros_ec_keyb_close;

	ckdev->ghost_filter = of_property_read_bool(np,
					"google,needs-ghost-filter");

	err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols,
					 NULL, idev);
	if (err) {
		dev_err(dev, "cannot build key matrix\n");
		return err;
	}

	ckdev->row_shift = get_count_order(ckdev->cols);

	input_set_capability(idev, EV_MSC, MSC_SCAN);
	input_set_drvdata(idev, ckdev);
	ckdev->idev = idev;
	err = input_register_device(ckdev->idev);
	if (err) {
		dev_err(dev, "cannot register input device\n");
		return err;
	}

	return 0;
}

#ifdef CONFIG_PM_SLEEP
/* Clear any keys in the buffer */
static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev)
{
	uint8_t old_state[ckdev->cols];
	uint8_t new_state[ckdev->cols];
	unsigned long duration;
	int i, ret;

	/*
	 * Keep reading until we see that the scan state does not change.
	 * That indicates that we are done.
	 *
	 * Assume that the EC keyscan buffer is at most 32 deep.
	 */
	duration = jiffies;
	ret = cros_ec_keyb_get_state(ckdev, new_state);
	for (i = 1; !ret && i < 32; i++) {
		memcpy(old_state, new_state, sizeof(old_state));
		ret = cros_ec_keyb_get_state(ckdev, new_state);
		if (0 == memcmp(old_state, new_state, sizeof(old_state)))
			break;
	}
	duration = jiffies - duration;
	dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i,
		jiffies_to_usecs(duration));
}
예제 #18
0
static int matrix_keypad_probe(struct platform_device *pdev)
{
	const struct matrix_keypad_platform_data *pdata;
	struct matrix_keypad *keypad;
	struct input_dev *input_dev;
	int err;

	pdata = dev_get_platdata(&pdev->dev);
	if (!pdata) {
		pdata = matrix_keypad_parse_dt(&pdev->dev);
		if (IS_ERR(pdata)) {
			dev_err(&pdev->dev, "no platform data defined\n");
			return PTR_ERR(pdata);
		}
	} else if (!pdata->keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!keypad || !input_dev) {
		err = -ENOMEM;
		goto err_free_mem;
	}

	keypad->input_dev = input_dev;
	keypad->pdata = pdata;
	keypad->row_shift = get_count_order(pdata->num_col_gpios);
	keypad->stopped = true;
	INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
	spin_lock_init(&keypad->lock);

	input_dev->name		= pdev->name;
	input_dev->id.bustype	= BUS_HOST;
	input_dev->dev.parent	= &pdev->dev;
	input_dev->open		= matrix_keypad_start;
	input_dev->close	= matrix_keypad_stop;

	err = matrix_keypad_build_keymap(pdata->keymap_data, NULL,
					 pdata->num_row_gpios,
					 pdata->num_col_gpios,
					 NULL, input_dev);
	if (err) {
		dev_err(&pdev->dev, "failed to build keymap\n");
		goto err_free_mem;
	}

	if (!pdata->no_autorepeat)
		__set_bit(EV_REP, input_dev->evbit);
	input_set_capability(input_dev, EV_MSC, MSC_SCAN);
	input_set_drvdata(input_dev, keypad);

	err = matrix_keypad_init_gpio(pdev, keypad);
	if (err)
		goto err_free_mem;

	err = input_register_device(keypad->input_dev);
	if (err)
		goto err_free_gpio;

	device_init_wakeup(&pdev->dev, pdata->wakeup);
	platform_set_drvdata(pdev, keypad);

	return 0;

err_free_gpio:
	matrix_keypad_free_gpio(keypad);
err_free_mem:
	input_free_device(input_dev);
	kfree(keypad);
	return err;
}
예제 #19
0
static int tc3589x_keypad_probe(struct platform_device *pdev)
{
	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
	struct tc_keypad *keypad;
	struct input_dev *input;
	const struct tc3589x_keypad_platform_data *plat;
	int error, irq;

	plat = tc3589x_keypad_of_probe(&pdev->dev);
	if (IS_ERR(plat)) {
		dev_err(&pdev->dev, "invalid keypad platform data\n");
		return PTR_ERR(plat);
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL);
	input = input_allocate_device();
	if (!keypad || !input) {
		dev_err(&pdev->dev, "failed to allocate keypad memory\n");
		error = -ENOMEM;
		goto err_free_mem;
	}

	keypad->board = plat;
	keypad->input = input;
	keypad->tc3589x = tc3589x;

	input->id.bustype = BUS_I2C;
	input->name = pdev->name;
	input->dev.parent = &pdev->dev;

	input->open = tc3589x_keypad_open;
	input->close = tc3589x_keypad_close;

	error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
					   TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
					   NULL, input);
	if (error) {
		dev_err(&pdev->dev, "Failed to build keymap\n");
		goto err_free_mem;
	}

	keypad->keymap = input->keycode;

	input_set_capability(input, EV_MSC, MSC_SCAN);
	if (!plat->no_autorepeat)
		__set_bit(EV_REP, input->evbit);

	input_set_drvdata(input, keypad);

	error = request_threaded_irq(irq, NULL, tc3589x_keypad_irq,
				     plat->irqtype | IRQF_ONESHOT,
				     "tc3589x-keypad", keypad);
	if (error < 0) {
		dev_err(&pdev->dev,
				"Could not allocate irq %d,error %d\n",
				irq, error);
		goto err_free_mem;
	}

	error = input_register_device(input);
	if (error) {
		dev_err(&pdev->dev, "Could not register input device\n");
		goto err_free_irq;
	}

	/* let platform decide if keypad is a wakeup source or not */
	device_init_wakeup(&pdev->dev, plat->enable_wakeup);
	device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup);

	platform_set_drvdata(pdev, keypad);

	return 0;

err_free_irq:
	free_irq(irq, keypad);
err_free_mem:
	input_free_device(input);
	kfree(keypad);
	return error;
}
예제 #20
0
파일: cros_ec_keyb.c 프로젝트: 020gzh/linux
static int cros_ec_keyb_probe(struct platform_device *pdev)
{
	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
	struct device *dev = ec->dev;
	struct cros_ec_keyb *ckdev;
	struct input_dev *idev;
	struct device_node *np;
	int err;

	np = pdev->dev.of_node;
	if (!np)
		return -ENODEV;

	ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL);
	if (!ckdev)
		return -ENOMEM;
	err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows,
					    &ckdev->cols);
	if (err)
		return err;

	ckdev->valid_keys = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
	if (!ckdev->valid_keys)
		return -ENOMEM;

	ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
	if (!ckdev->old_kb_state)
		return -ENOMEM;

	idev = devm_input_allocate_device(&pdev->dev);
	if (!idev)
		return -ENOMEM;

	if (!ec->irq) {
		dev_err(dev, "no EC IRQ specified\n");
		return -EINVAL;
	}

	ckdev->ec = ec;
	ckdev->dev = dev;
	dev_set_drvdata(&pdev->dev, ckdev);

	idev->name = CROS_EC_DEV_NAME;
	idev->phys = ec->phys_name;
	__set_bit(EV_REP, idev->evbit);

	idev->id.bustype = BUS_VIRTUAL;
	idev->id.version = 1;
	idev->id.product = 0;
	idev->dev.parent = &pdev->dev;
	idev->open = cros_ec_keyb_open;
	idev->close = cros_ec_keyb_close;

	ckdev->ghost_filter = of_property_read_bool(np,
					"google,needs-ghost-filter");

	err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols,
					 NULL, idev);
	if (err) {
		dev_err(dev, "cannot build key matrix\n");
		return err;
	}

	ckdev->row_shift = get_count_order(ckdev->cols);

	input_set_capability(idev, EV_MSC, MSC_SCAN);
	input_set_drvdata(idev, ckdev);
	ckdev->idev = idev;
	cros_ec_keyb_compute_valid_keys(ckdev);

	err = input_register_device(ckdev->idev);
	if (err) {
		dev_err(dev, "cannot register input device\n");
		return err;
	}

	return 0;
}
/**
 * db5500_keypad_probe() - Initialze the the keypad driver
 * @pdev: pointer to platform device structure
 *
 * This function will allocate and initialize the instance
 * data and request the irq and register to input subsystem driver.
 */
static int __devinit db5500_keypad_probe(struct platform_device *pdev)
{
	struct db5500_keypad_platform_data *plat;
	struct db5500_keypad *keypad;
	struct resource *res;
	struct input_dev *input;
	void __iomem *base;
	struct clk *clk;
	int ret;
	int irq;
	int i;

	plat = pdev->dev.platform_data;
	if (!plat) {
		dev_err(&pdev->dev, "invalid keypad platform data\n");
		ret = -EINVAL;
		goto out_ret;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "failed to get keypad irq\n");
		ret = -EINVAL;
		goto out_ret;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "missing platform resources\n");
		ret = -EINVAL;
		goto out_ret;
	}

	res = request_mem_region(res->start, resource_size(res), pdev->name);
	if (!res) {
		dev_err(&pdev->dev, "failed to request I/O memory\n");
		ret = -EBUSY;
		goto out_ret;
	}

	base = ioremap(res->start, resource_size(res));
	if (!base) {
		dev_err(&pdev->dev, "failed to remap I/O memory\n");
		ret = -ENXIO;
		goto out_freerequest_memregions;
	}

	clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(clk)) {
		dev_err(&pdev->dev, "failed to clk_get\n");
		ret = PTR_ERR(clk);
		goto out_iounmap;
	}

	keypad = kzalloc(sizeof(struct db5500_keypad), GFP_KERNEL);
	if (!keypad) {
		dev_err(&pdev->dev, "failed to allocate keypad memory\n");
		ret = -ENOMEM;
		goto out_freeclk;
	}

	input = input_allocate_device();
	if (!input) {
		dev_err(&pdev->dev, "failed to input_allocate_device\n");
		ret = -ENOMEM;
		goto out_freekeypad;
	}

	keypad->regulator = regulator_get(&pdev->dev, "v-ape");
	if (IS_ERR(keypad->regulator)) {
		dev_err(&pdev->dev, "regulator_get failed\n");
		keypad->regulator = NULL;
		ret = -EINVAL;
		goto out_regulator_get;
	} else {
		ret = regulator_enable(keypad->regulator);
		if (ret < 0) {
			dev_err(&pdev->dev, "regulator_enable failed\n");
			goto out_regulator_enable;
		}
	}

	input->id.bustype = BUS_HOST;
	input->name = "db5500-keypad";
	input->dev.parent = &pdev->dev;

	input->keycode = keypad->keymap;
	input->keycodesize = sizeof(keypad->keymap[0]);
	input->keycodemax = ARRAY_SIZE(keypad->keymap);

	input_set_capability(input, EV_MSC, MSC_SCAN);

	__set_bit(EV_KEY, input->evbit);
	if (!plat->no_autorepeat)
		__set_bit(EV_REP, input->evbit);

	matrix_keypad_build_keymap(plat->keymap_data, KEYPAD_ROW_SHIFT,
				   input->keycode, input->keybit);

	ret = input_register_device(input);
	if (ret) {
		dev_err(&pdev->dev,
			"unable to register input device: %d\n", ret);
		goto out_freeinput;
	}

	keypad->irq	= irq;
	keypad->board	= plat;
	keypad->input	= input;
	keypad->base	= base;
	keypad->clk	= clk;

	INIT_DELAYED_WORK(&keypad->switch_work, db5500_gpio_switch_work);
	INIT_DELAYED_WORK(&keypad->gpio_work, db5500_gpio_release_work);

	clk_enable(keypad->clk);
if (!keypad->board->init) {
		dev_err(&pdev->dev, "init funtion not defined\n");
		ret = -EINVAL;
		goto out_unregisterinput;
	}

	if (keypad->board->init() < 0) {
		dev_err(&pdev->dev, "keyboard init config failed\n");
		ret = -EINVAL;
		goto out_unregisterinput;
	}

	if (!keypad->board->exit) {
		dev_err(&pdev->dev, "exit funtion not defined\n");
		ret = -EINVAL;
		goto out_unregisterinput;
	}

	if (keypad->board->exit() < 0) {
		dev_err(&pdev->dev,  "keyboard exit config failed\n");
		ret = -EINVAL;
		goto out_unregisterinput;
	}

	for (i = 0; i < keypad->board->krow; i++) {
		keypad->db5500_rows[i] = *plat->gpio_input_pins;
		keypad->gpio_input_irq[i] =
				GPIO_TO_IRQ(keypad->db5500_rows[i]);
		plat->gpio_input_pins++;
	}

	for (i = 0; i < keypad->board->kcol; i++) {
		keypad->db5500_cols[i] = *plat->gpio_output_pins;
		plat->gpio_output_pins++;
	}

	for (i = 0; i < keypad->board->krow; i++) {
		ret =  request_threaded_irq(keypad->gpio_input_irq[i],
				NULL, db5500_keypad_gpio_irq,
				IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND,
				"db5500-keypad-gpio", keypad);
		if (ret) {
			dev_err(&pdev->dev, "allocate gpio irq %d failed\n",
						keypad->gpio_input_irq[i]);
			goto out_unregisterinput;
		}
		enable_irq_wake(keypad->gpio_input_irq[i]);
	}

	ret = request_threaded_irq(keypad->irq, NULL, db5500_keypad_irq,
				   IRQF_ONESHOT, "db5500-keypad", keypad);
	if (ret) {
		dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
		goto out_unregisterinput;
	}

	platform_set_drvdata(pdev, keypad);

	clk_disable(keypad->clk);
	regulator_disable(keypad->regulator);
	return 0;

out_unregisterinput:
	input_unregister_device(input);
	input = NULL;
	clk_disable(keypad->clk);
out_freeinput:
	input_free_device(input);
out_regulator_enable:
	regulator_put(keypad->regulator);
out_regulator_get:
	input_free_device(input);
out_freekeypad:
	kfree(keypad);
out_freeclk:
	clk_put(clk);
out_iounmap:
	iounmap(base);
out_freerequest_memregions:
	release_mem_region(res->start, resource_size(res));
out_ret:
	return ret;
}
예제 #22
0
/*
 * keypad controller should be initialized in the following sequence
 * only, otherwise it might get into FSM stuck state.
 *
 * - Initialize keypad control parameters, like no. of rows, columns,
 *   timing values etc.,
 * - configure rows and column gpios pull up/down.
 * - set irq edge type.
 * - enable the keypad controller.
 */
static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
{
	const struct pm8xxx_keypad_platform_data *pdata =
					dev_get_platdata(&pdev->dev);
	const struct matrix_keymap_data *keymap_data;
	struct pmic8xxx_kp *kp;
	int rc;
	u8 ctrl_val;

	struct pm_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
		.output_value	= 0,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= PM_GPIO_VIN_S3,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	struct pm_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_31P5,
		.vin_sel	= PM_GPIO_VIN_S3,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};


	if (!pdata || !pdata->num_cols || !pdata->num_rows ||
		pdata->num_cols > PM8XXX_MAX_COLS ||
		pdata->num_rows > PM8XXX_MAX_ROWS ||
		pdata->num_cols < PM8XXX_MIN_COLS) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	if (!pdata->scan_delay_ms ||
		pdata->scan_delay_ms > MAX_SCAN_DELAY ||
		pdata->scan_delay_ms < MIN_SCAN_DELAY ||
		!is_power_of_2(pdata->scan_delay_ms)) {
		dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
		return -EINVAL;
	}

	if (!pdata->row_hold_ns ||
		pdata->row_hold_ns > MAX_ROW_HOLD_DELAY ||
		pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
		((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
		dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
		return -EINVAL;
	}

	if (!pdata->debounce_ms ||
		((pdata->debounce_ms % 5) != 0) ||
		pdata->debounce_ms > MAX_DEBOUNCE_TIME ||
		pdata->debounce_ms < MIN_DEBOUNCE_TIME) {
		dev_err(&pdev->dev, "invalid debounce time supplied\n");
		return -EINVAL;
	}

	keymap_data = pdata->keymap_data;
	if (!keymap_data) {
		dev_err(&pdev->dev, "no keymap data supplied\n");
		return -EINVAL;
	}

	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	platform_set_drvdata(pdev, kp);

	kp->pdata	= pdata;
	kp->dev		= &pdev->dev;

	kp->input = input_allocate_device();
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		rc = -ENOMEM;
		goto err_alloc_device;
	}

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->input->name = pdata->input_name ? : "PMIC8XXX keypad";
	kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0";

	kp->input->dev.parent	= &pdev->dev;

	kp->input->id.bustype	= BUS_I2C;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->evbit[0]	= BIT_MASK(EV_KEY);

	if (pdata->rep)
		__set_bit(EV_REP, kp->input->evbit);

	kp->input->keycode	= kp->keycodes;
	kp->input->keycodemax	= PM8XXX_MATRIX_MAX_SIZE;
	kp->input->keycodesize	= sizeof(kp->keycodes);
	kp->input->open		= pmic8xxx_kp_open;
	kp->input->close	= pmic8xxx_kp_close;

	matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT,
					kp->input->keycode, kp->input->keybit);

	input_set_capability(kp->input, EV_MSC, MSC_SCAN);
	input_set_drvdata(kp->input, kp);

	/* initialize keypad state */
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8xxx_kpd_init(kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		goto err_get_irq;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start,
					pdata->num_cols, kp, &kypd_sns);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
		goto err_gpio_config;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start,
					pdata->num_rows, kp, &kypd_drv);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
		goto err_gpio_config;
	}

	rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		goto err_get_irq;
	}

	rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		goto err_req_stuck_irq;
	}

	rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
		goto err_pmic_reg_read;
	}

	kp->ctrl_reg = ctrl_val;

	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		goto err_pmic_reg_read;
	}

	device_init_wakeup(&pdev->dev, pdata->wakeup);

	return 0;

err_pmic_reg_read:
	free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq:
	free_irq(kp->key_sense_irq, kp);
err_gpio_config:
err_get_irq:
	input_free_device(kp->input);
err_alloc_device:
	platform_set_drvdata(pdev, NULL);
	kfree(kp);
	return rc;
}

static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
{
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);

	device_init_wakeup(&pdev->dev, 0);
	free_irq(kp->key_stuck_irq, kp);
	free_irq(kp->key_sense_irq, kp);
	input_unregister_device(kp->input);
	kfree(kp);

	platform_set_drvdata(pdev, NULL);
	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_kp_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		enable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

		if (input_dev->users)
			pmic8xxx_kp_disable(kp);

		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}

static int pmic8xxx_kp_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		disable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

		if (input_dev->users)
			pmic8xxx_kp_enable(kp);

		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
			 pmic8xxx_kp_suspend, pmic8xxx_kp_resume);

static struct platform_driver pmic8xxx_kp_driver = {
	.probe		= pmic8xxx_kp_probe,
	.remove		= __devexit_p(pmic8xxx_kp_remove),
	.driver		= {
		.name = PM8XXX_KEYPAD_DEV_NAME,
		.owner = THIS_MODULE,
		.pm = &pm8xxx_kp_pm_ops,
	},
};

static int __init pmic8xxx_kp_init(void)
{
	return platform_driver_register(&pmic8xxx_kp_driver);
}
module_init(pmic8xxx_kp_init);

static void __exit pmic8xxx_kp_exit(void)
{
	platform_driver_unregister(&pmic8xxx_kp_driver);
}
module_exit(pmic8xxx_kp_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PMIC8XXX keypad driver");
MODULE_VERSION("1.0");
MODULE_ALIAS("platform:pmic8xxx_keypad");
MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
예제 #23
0
static int pm8058_kp_config_drv(int gpio_start, int num_gpios)
{
    int	rc;
    struct pm8058_gpio kypd_drv = {
        .direction	= PM_GPIO_DIR_OUT,
        .output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
        .output_value	= 0,
        .pull		= PM_GPIO_PULL_NO,
        .vin_sel	= 2,
        .out_strength	= PM_GPIO_STRENGTH_LOW,
        .function	= PM_GPIO_FUNC_1,
        .inv_int_pol	= 1,
    };

    if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS)
        return -EINVAL;

    while (num_gpios--) {
        rc = pm8058_gpio_config(gpio_start++, &kypd_drv);
        if (rc) {
            pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n",
                   __func__, rc);
            return rc;
        }
    }

    return 0;
}

static int pm8058_kp_config_sns(int gpio_start, int num_gpios)
{
    int	rc;
    struct pm8058_gpio kypd_sns = {
        .direction	= PM_GPIO_DIR_IN,
        .pull		= PM_GPIO_PULL_UP_31P5,
        .vin_sel	= 2,
        .out_strength	= PM_GPIO_STRENGTH_NO,
        .function	= PM_GPIO_FUNC_NORMAL,
        .inv_int_pol	= 1,
    };

    if (gpio_start < 0 || num_gpios < 0 || num_gpios > PM8058_GPIOS)
        return -EINVAL;

    while (num_gpios--) {
        rc = pm8058_gpio_config(gpio_start++, &kypd_sns);
        if (rc) {
            pr_err("%s: FAIL pm8058_gpio_config(): rc=%d.\n",
                   __func__, rc);
            return rc;
        }
    }

    return 0;
}

/*
 * keypad controller should be initialized in the following sequence
 * only, otherwise it might get into FSM stuck state.
 *
 * - Initialize keypad control parameters, like no. of rows, columns,
 *   timing values etc.,
 * - configure rows and column gpios pull up/down.
 * - set irq edge type.
 * - enable the keypad controller.
 */
static int __devinit pmic8058_kp_probe(struct platform_device *pdev)
{
    struct pmic8058_keypad_data *pdata = pdev->dev.platform_data;
    const struct matrix_keymap_data *keymap_data;
    struct pmic8058_kp *kp;
    int rc;
    unsigned short *keycodes;
    u8 ctrl_val;
    struct pm8058_chip	*pm_chip;

    pm_chip = platform_get_drvdata(pdev);
    if (pm_chip == NULL) {
        dev_err(&pdev->dev, "no parent data passed in\n");
        return -EFAULT;
    }

    if (!pdata || !pdata->num_cols || !pdata->num_rows ||
            pdata->num_cols > PM8058_MAX_COLS ||
            pdata->num_rows > PM8058_MAX_ROWS ||
            pdata->num_cols < PM8058_MIN_COLS
#if 0
            ||	pdata->num_rows < PM8058_MIN_ROWS
#endif
       ) {
        dev_err(&pdev->dev, "invalid platform data\n");
        return -EINVAL;
    }

    if (pdata->rows_gpio_start < 0 || pdata->cols_gpio_start < 0) {
        dev_err(&pdev->dev, "invalid gpio_start platform data\n");
        return -EINVAL;
    }

    if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY
            || pdata->scan_delay_ms < MIN_SCAN_DELAY ||
            !is_power_of_2(pdata->scan_delay_ms)) {
        dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
        return -EINVAL;
    }

    if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY
            || pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
            ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
        dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
        return -EINVAL;
    }

    if (pm8058_rev(pm_chip) == PM_8058_REV_1p0) {
        if (!pdata->debounce_ms
                || !is_power_of_2(pdata->debounce_ms[0])
                || pdata->debounce_ms[0] > MAX_DEBOUNCE_A0_TIME
                || pdata->debounce_ms[0] < MIN_DEBOUNCE_A0_TIME) {
            dev_err(&pdev->dev, "invalid debounce time supplied\n");
            return -EINVAL;
        }
    } else {
        if (!pdata->debounce_ms
                || ((pdata->debounce_ms[1] % 5) != 0)
                || pdata->debounce_ms[1] > MAX_DEBOUNCE_B0_TIME
                || pdata->debounce_ms[1] < MIN_DEBOUNCE_B0_TIME) {
            dev_err(&pdev->dev, "invalid debounce time supplied\n");
            return -EINVAL;
        }
    }

    keymap_data = pdata->keymap_data;
    if (!keymap_data) {
        dev_err(&pdev->dev, "no keymap data supplied\n");
        return -EINVAL;
    }

    kp = kzalloc(sizeof(*kp), GFP_KERNEL);
    if (!kp)
        return -ENOMEM;

    keycodes = kzalloc(PM8058_MATRIX_MAX_SIZE * sizeof(*keycodes),
                       GFP_KERNEL);
    if (!keycodes) {
        rc = -ENOMEM;
        goto err_alloc_mem;
    }

    platform_set_drvdata(pdev, kp);
    mutex_init(&kp->mutex);

    kp->pdata	= pdata;
    kp->dev		= &pdev->dev;
    kp->keycodes	= keycodes;
    kp->pm_chip	= pm_chip;

    if (pm8058_rev(pm_chip) == PM_8058_REV_1p0)
        kp->flags |= KEYF_FIX_LAST_ROW;

    kp->input = input_allocate_device();
    if (!kp->input) {
        dev_err(&pdev->dev, "unable to allocate input device\n");
        rc = -ENOMEM;
        goto err_alloc_device;
    }

    /* Enable runtime PM ops, start in ACTIVE mode */
    rc = pm_runtime_set_active(&pdev->dev);
    if (rc < 0)
        dev_dbg(&pdev->dev, "unable to set runtime pm state\n");
    pm_runtime_enable(&pdev->dev);

    kp->key_sense_irq = platform_get_irq(pdev, 0);
    if (kp->key_sense_irq < 0) {
        dev_err(&pdev->dev, "unable to get keypad sense irq\n");
        rc = -ENXIO;
        goto err_get_irq;
    }

    kp->key_stuck_irq = platform_get_irq(pdev, 1);
    if (kp->key_stuck_irq < 0) {
        dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
        rc = -ENXIO;
        goto err_get_irq;
    }

    if (pdata->input_name)
        kp->input->name = pdata->input_name;
    else
        kp->input->name = "PMIC8058 keypad";

    if (pdata->input_phys_device)
        kp->input->phys = pdata->input_phys_device;
    else
        kp->input->phys = "pmic8058_keypad/input0";

    kp->input->dev.parent	= &pdev->dev;

    kp->input->id.bustype	= BUS_HOST;
    kp->input->id.version	= 0x0001;
    kp->input->id.product	= 0x0001;
    kp->input->id.vendor	= 0x0001;

    kp->input->evbit[0]	= BIT_MASK(EV_KEY);

    if (pdata->rep)
        __set_bit(EV_REP, kp->input->evbit);

    kp->input->keycode	= keycodes;
    kp->input->keycodemax	= PM8058_MATRIX_MAX_SIZE;
    kp->input->keycodesize	= sizeof(*keycodes);

    matrix_keypad_build_keymap(keymap_data, PM8058_ROW_SHIFT,
                               kp->input->keycode, kp->input->keybit);

    input_set_capability(kp->input, EV_MSC, MSC_SCAN);
    input_set_drvdata(kp->input, kp);

    rc = input_register_device(kp->input);
    if (rc < 0) {
        dev_err(&pdev->dev, "unable to register keypad input device\n");
        goto err_get_irq;
    }

    /* initialize keypad state */
    memset(kp->keystate, 0xff, sizeof(kp->keystate));
    memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

    rc = pmic8058_kpd_init(kp);
    if (rc < 0) {
        dev_err(&pdev->dev, "unable to initialize keypad controller\n");
        goto err_kpd_init;
    }

    rc = pm8058_kp_config_sns(pdata->cols_gpio_start,
                              pdata->num_cols);
    if (rc < 0) {
        dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
        goto err_gpio_config;
    }

    rc = pm8058_kp_config_drv(pdata->rows_gpio_start,
                              pdata->num_rows);
    if (rc < 0) {
        dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
        goto err_gpio_config;
    }

    rc = request_threaded_irq(kp->key_sense_irq, NULL, pmic8058_kp_irq,
                              IRQF_TRIGGER_RISING, "pmic-keypad", kp);
    if (rc < 0) {
        dev_err(&pdev->dev, "failed to request keypad sense irq\n");
        goto err_req_sense_irq;
    }

    rc = request_threaded_irq(kp->key_stuck_irq, NULL,
                              pmic8058_kp_stuck_irq, IRQF_TRIGGER_RISING,
                              "pmic-keypad-stuck", kp);
    if (rc < 0) {
        dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
        goto err_req_stuck_irq;
    }

    rc = pmic8058_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
    ctrl_val |= KEYP_CTRL_KEYP_EN;
    rc = pmic8058_kp_write_u8(kp, ctrl_val, KEYP_CTRL);

    kp->ctrl_reg = ctrl_val;

    __dump_kp_regs(kp, "probe");

    rc = device_create_file(&pdev->dev, &dev_attr_key_pressed);
    if (rc < 0)
        goto err_create_file;

    rc = device_create_file(&pdev->dev, &dev_attr_disable_kp);
    if (rc < 0)
        goto err_create_file;

    device_init_wakeup(&pdev->dev, pdata->wakeup);

    return 0;

err_create_file:
    free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq:
    free_irq(kp->key_sense_irq, kp);
err_req_sense_irq:
err_gpio_config:
err_kpd_init:
    input_unregister_device(kp->input);
    kp->input = NULL;
err_get_irq:
    pm_runtime_set_suspended(&pdev->dev);
    pm_runtime_disable(&pdev->dev);
    input_free_device(kp->input);
err_alloc_device:
    kfree(keycodes);
err_alloc_mem:
    kfree(kp);
    return rc;
}

static int __devexit pmic8058_kp_remove(struct platform_device *pdev)
{
    struct pmic8058_kp *kp = platform_get_drvdata(pdev);

//	sysfs_remove_group(&pdev->dev.kobj, &pmic8058_keys_attr_group);
    pm_runtime_set_suspended(&pdev->dev);
    pm_runtime_disable(&pdev->dev);
    device_remove_file(&pdev->dev, &dev_attr_key_pressed);
    device_remove_file(&pdev->dev, &dev_attr_disable_kp);
    device_init_wakeup(&pdev->dev, 0);
    free_irq(kp->key_stuck_irq, kp);
    free_irq(kp->key_sense_irq, kp);
    input_unregister_device(kp->input);
    platform_set_drvdata(pdev, NULL);
    kfree(kp->input->keycode);
    kfree(kp);

    return 0;
}

#ifdef CONFIG_PM
static int pmic8058_kp_suspend(struct device *dev)
{
    struct pmic8058_kp *kp = dev_get_drvdata(dev);

    if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp)) {
        enable_irq_wake(kp->key_sense_irq);
    } else {
        mutex_lock(&kp->mutex);
        pmic8058_kp_disable(kp);
        mutex_unlock(&kp->mutex);
    }

    return 0;
}

static int pmic8058_kp_resume(struct device *dev)
{
    struct pmic8058_kp *kp = dev_get_drvdata(dev);

    if (device_may_wakeup(dev) && !pmic8058_kp_disabled(kp)) {
        disable_irq_wake(kp->key_sense_irq);
    } else {
        mutex_lock(&kp->mutex);
        pmic8058_kp_enable(kp);
        mutex_unlock(&kp->mutex);
    }

    return 0;
}

static struct dev_pm_ops pm8058_kp_pm_ops = {
    .suspend	= pmic8058_kp_suspend,
    .resume		= pmic8058_kp_resume,
};
#endif

static struct platform_driver pmic8058_kp_driver = {
    .probe		= pmic8058_kp_probe,
    .remove		= __devexit_p(pmic8058_kp_remove),
    .driver		= {
        .name = "pm8058-keypad",
        .owner = THIS_MODULE,
#ifdef CONFIG_PM
        .pm = &pm8058_kp_pm_ops,
#endif
    },
};

static int __init pmic8058_kp_init(void)
{
    return platform_driver_register(&pmic8058_kp_driver);
}
module_init(pmic8058_kp_init);

static void __exit pmic8058_kp_exit(void)
{
    platform_driver_unregister(&pmic8058_kp_driver);
}
예제 #24
0
static int __devinit omap4_keypad_probe(struct platform_device *pdev)
{
	const struct omap4_keypad_platform_data *pdata;
	struct omap4_keypad *keypad_data;
	struct input_dev *input_dev;
	struct resource *res;
	resource_size_t size;
	unsigned int row_shift, max_keys;
	int irq;
	int error;

	/* platform data */
	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data defined\n");
		return -EINVAL;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "no base address specified\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);
	if (!irq) {
		dev_err(&pdev->dev, "no keyboard irq assigned\n");
		return -EINVAL;
	}

	if (!pdata->keymap_data) {
		dev_err(&pdev->dev, "no keymap data defined\n");
		return -EINVAL;
	}

	row_shift = get_count_order(pdata->cols);
	max_keys = pdata->rows << row_shift;

	keypad_data = kzalloc(sizeof(struct omap4_keypad) +
				max_keys * sizeof(keypad_data->keymap[0]),
			      GFP_KERNEL);
	if (!keypad_data) {
		dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
		return -ENOMEM;
	}

	size = resource_size(res);

	res = request_mem_region(res->start, size, pdev->name);
	if (!res) {
		dev_err(&pdev->dev, "can't request mem region\n");
		error = -EBUSY;
		goto err_free_keypad;
	}

	keypad_data->base = ioremap(res->start, resource_size(res));
	if (!keypad_data->base) {
		dev_err(&pdev->dev, "can't ioremap mem resource\n");
		error = -ENOMEM;
		goto err_release_mem;
	}

	keypad_data->irq = irq;
	keypad_data->row_shift = row_shift;
	keypad_data->rows = pdata->rows;
	keypad_data->cols = pdata->cols;

	/* input device allocation */
	keypad_data->input = input_dev = input_allocate_device();
	if (!input_dev) {
		error = -ENOMEM;
		goto err_unmap;
	}

	input_dev->name = pdev->name;
	input_dev->dev.parent = &pdev->dev;
	input_dev->id.bustype = BUS_HOST;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = 0x0001;
	input_dev->id.version = 0x0001;

	input_dev->open = omap4_keypad_open;
	input_dev->close = omap4_keypad_close;

	input_dev->keycode	= keypad_data->keymap;
	input_dev->keycodesize	= sizeof(keypad_data->keymap[0]);
	input_dev->keycodemax	= max_keys;

	__set_bit(EV_KEY, input_dev->evbit);
	__set_bit(EV_REP, input_dev->evbit);

	input_set_capability(input_dev, EV_MSC, MSC_SCAN);

	input_set_drvdata(input_dev, keypad_data);

	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
			input_dev->keycode, input_dev->keybit);

	error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
			     IRQF_TRIGGER_RISING,
			     "omap4-keypad", keypad_data);
	if (error) {
		dev_err(&pdev->dev, "failed to register interrupt\n");
		goto err_free_input;
	}

	pm_runtime_enable(&pdev->dev);

	error = input_register_device(keypad_data->input);
	if (error < 0) {
		dev_err(&pdev->dev, "failed to register input device\n");
		goto err_pm_disable;
	}

	platform_set_drvdata(pdev, keypad_data);
	return 0;

err_pm_disable:
	pm_runtime_disable(&pdev->dev);
	free_irq(keypad_data->irq, keypad_data);
err_free_input:
	input_free_device(input_dev);
err_unmap:
	iounmap(keypad_data->base);
err_release_mem:
	release_mem_region(res->start, size);
err_free_keypad:
	kfree(keypad_data);
	return error;
}