^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/mfd/ucb1x00-assabet.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2001-2003 Russell King, All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * We handle the machine-specific bits of the UCB1x00 driver here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/gpio_keys.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mfd/ucb1x00.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define UCB1X00_ATTR(name,input)\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct ucb1x00 *ucb = classdev_to_ucb1x00(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) int val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ucb1x00_adc_enable(ucb); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) val = ucb1x00_adc_read(ucb, input, UCB_NOSYNC); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ucb1x00_adc_disable(ucb); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return sprintf(buf, "%d\n", val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static DEVICE_ATTR(name,0444,name##_show,NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) UCB1X00_ATTR(vbatt, UCB_ADC_INP_AD1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) UCB1X00_ATTR(vcharger, UCB_ADC_INP_AD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static int ucb1x00_assabet_add(struct ucb1x00_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct ucb1x00 *ucb = dev->ucb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct gpio_keys_platform_data keys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static struct gpio_keys_button buttons[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) memset(buttons, 0, sizeof(buttons));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) memset(&keys, 0, sizeof(keys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for (i = 0; i < ARRAY_SIZE(buttons); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) buttons[i].code = BTN_0 + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) buttons[i].gpio = ucb->gpio.base + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) buttons[i].type = EV_KEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) buttons[i].can_disable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) keys.buttons = buttons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) keys.nbuttons = ARRAY_SIZE(buttons);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) keys.poll_interval = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) keys.name = "ucb1x00";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) pdev = platform_device_register_data(&ucb->dev, "gpio-keys", -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) &keys, sizeof(keys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) device_create_file(&ucb->dev, &dev_attr_vbatt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) device_create_file(&ucb->dev, &dev_attr_vcharger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) device_create_file(&ucb->dev, &dev_attr_batt_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) dev->priv = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct platform_device *pdev = dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!IS_ERR(pdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) platform_device_unregister(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) device_remove_file(&dev->ucb->dev, &dev_attr_vcharger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) device_remove_file(&dev->ucb->dev, &dev_attr_vbatt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static struct ucb1x00_driver ucb1x00_assabet_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .add = ucb1x00_assabet_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .remove = ucb1x00_assabet_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int __init ucb1x00_assabet_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ucb1x00_register_driver(&ucb1x00_assabet_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void __exit ucb1x00_assabet_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ucb1x00_unregister_driver(&ucb1x00_assabet_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) module_init(ucb1x00_assabet_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) module_exit(ucb1x00_assabet_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) MODULE_DESCRIPTION("Assabet noddy testing only example ADC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) MODULE_LICENSE("GPL");