Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2020 Marek Vasut <marex@denx.de>
0004  *
0005  * Based on rpi_touchscreen.c by Eric Anholt <eric@anholt.net>
0006  */
0007 
0008 #include <linux/backlight.h>
0009 #include <linux/err.h>
0010 #include <linux/gpio.h>
0011 #include <linux/gpio/driver.h>
0012 #include <linux/i2c.h>
0013 #include <linux/init.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/module.h>
0016 #include <linux/regmap.h>
0017 #include <linux/regulator/driver.h>
0018 #include <linux/regulator/machine.h>
0019 #include <linux/regulator/of_regulator.h>
0020 #include <linux/slab.h>
0021 
0022 /* I2C registers of the Atmel microcontroller. */
0023 #define REG_ID      0x80
0024 #define REG_PORTA   0x81
0025 #define REG_PORTB   0x82
0026 #define REG_PORTC   0x83
0027 #define REG_POWERON 0x85
0028 #define REG_PWM     0x86
0029 #define REG_ADDR_L  0x8c
0030 #define REG_ADDR_H  0x8d
0031 #define REG_WRITE_DATA_H    0x90
0032 #define REG_WRITE_DATA_L    0x91
0033 
0034 #define PA_LCD_DITHB        BIT(0)
0035 #define PA_LCD_MODE     BIT(1)
0036 #define PA_LCD_LR       BIT(2)
0037 #define PA_LCD_UD       BIT(3)
0038 
0039 #define PB_BRIDGE_PWRDNX_N  BIT(0)
0040 #define PB_LCD_VCC_N        BIT(1)
0041 #define PB_LCD_MAIN     BIT(7)
0042 
0043 #define PC_LED_EN       BIT(0)
0044 #define PC_RST_TP_N     BIT(1)
0045 #define PC_RST_LCD_N        BIT(2)
0046 #define PC_RST_BRIDGE_N     BIT(3)
0047 
0048 enum gpio_signals {
0049     RST_BRIDGE_N,   /* TC358762 bridge reset */
0050     RST_TP_N,   /* Touch controller reset */
0051     NUM_GPIO
0052 };
0053 
0054 struct gpio_signal_mappings {
0055     unsigned int reg;
0056     unsigned int mask;
0057 };
0058 
0059 static const struct gpio_signal_mappings mappings[NUM_GPIO] = {
0060     [RST_BRIDGE_N] = { REG_PORTC, PC_RST_BRIDGE_N | PC_RST_LCD_N  },
0061     [RST_TP_N] = { REG_PORTC, PC_RST_TP_N },
0062 };
0063 
0064 struct attiny_lcd {
0065     /* lock to serialise overall accesses to the Atmel */
0066     struct mutex    lock;
0067     struct regmap   *regmap;
0068     bool gpio_states[NUM_GPIO];
0069     u8 port_states[3];
0070 
0071     struct gpio_chip gc;
0072 };
0073 
0074 static const struct regmap_config attiny_regmap_config = {
0075     .reg_bits = 8,
0076     .val_bits = 8,
0077     .disable_locking = 1,
0078     .max_register = REG_WRITE_DATA_L,
0079     .cache_type = REGCACHE_RBTREE,
0080 };
0081 
0082 static int attiny_set_port_state(struct attiny_lcd *state, int reg, u8 val)
0083 {
0084     state->port_states[reg - REG_PORTA] = val;
0085     return regmap_write(state->regmap, reg, val);
0086 };
0087 
0088 static u8 attiny_get_port_state(struct attiny_lcd *state, int reg)
0089 {
0090     return state->port_states[reg - REG_PORTA];
0091 };
0092 
0093 static int attiny_lcd_power_enable(struct regulator_dev *rdev)
0094 {
0095     struct attiny_lcd *state = rdev_get_drvdata(rdev);
0096 
0097     mutex_lock(&state->lock);
0098 
0099     /* Ensure bridge, and tp stay in reset */
0100     attiny_set_port_state(state, REG_PORTC, 0);
0101     usleep_range(5000, 10000);
0102 
0103     /* Default to the same orientation as the closed source
0104      * firmware used for the panel.  Runtime rotation
0105      * configuration will be supported using VC4's plane
0106      * orientation bits.
0107      */
0108     attiny_set_port_state(state, REG_PORTA, PA_LCD_LR);
0109     usleep_range(5000, 10000);
0110     /* Main regulator on, and power to the panel (LCD_VCC_N) */
0111     attiny_set_port_state(state, REG_PORTB, PB_LCD_MAIN);
0112     usleep_range(5000, 10000);
0113     /* Bring controllers out of reset */
0114     attiny_set_port_state(state, REG_PORTC, PC_LED_EN);
0115 
0116     msleep(80);
0117 
0118     mutex_unlock(&state->lock);
0119 
0120     return 0;
0121 }
0122 
0123 static int attiny_lcd_power_disable(struct regulator_dev *rdev)
0124 {
0125     struct attiny_lcd *state = rdev_get_drvdata(rdev);
0126 
0127     mutex_lock(&state->lock);
0128 
0129     regmap_write(rdev->regmap, REG_PWM, 0);
0130     usleep_range(5000, 10000);
0131 
0132     attiny_set_port_state(state, REG_PORTA, 0);
0133     usleep_range(5000, 10000);
0134     attiny_set_port_state(state, REG_PORTB, PB_LCD_VCC_N);
0135     usleep_range(5000, 10000);
0136     attiny_set_port_state(state, REG_PORTC, 0);
0137     msleep(30);
0138 
0139     mutex_unlock(&state->lock);
0140 
0141     return 0;
0142 }
0143 
0144 static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev)
0145 {
0146     struct attiny_lcd *state = rdev_get_drvdata(rdev);
0147     unsigned int data;
0148     int ret, i;
0149 
0150     mutex_lock(&state->lock);
0151 
0152     for (i = 0; i < 10; i++) {
0153         ret = regmap_read(rdev->regmap, REG_PORTC, &data);
0154         if (!ret)
0155             break;
0156         usleep_range(10000, 12000);
0157     }
0158 
0159     mutex_unlock(&state->lock);
0160 
0161     if (ret < 0)
0162         return ret;
0163 
0164     return data & PC_RST_BRIDGE_N;
0165 }
0166 
0167 static const struct regulator_init_data attiny_regulator_default = {
0168     .constraints = {
0169         .valid_ops_mask = REGULATOR_CHANGE_STATUS,
0170     },
0171 };
0172 
0173 static const struct regulator_ops attiny_regulator_ops = {
0174     .enable = attiny_lcd_power_enable,
0175     .disable = attiny_lcd_power_disable,
0176     .is_enabled = attiny_lcd_power_is_enabled,
0177 };
0178 
0179 static const struct regulator_desc attiny_regulator = {
0180     .name   = "tc358762-power",
0181     .ops    = &attiny_regulator_ops,
0182     .type   = REGULATOR_VOLTAGE,
0183     .owner  = THIS_MODULE,
0184 };
0185 
0186 static int attiny_update_status(struct backlight_device *bl)
0187 {
0188     struct attiny_lcd *state = bl_get_data(bl);
0189     struct regmap *regmap = state->regmap;
0190     int brightness = backlight_get_brightness(bl);
0191     int ret, i;
0192 
0193     mutex_lock(&state->lock);
0194 
0195     for (i = 0; i < 10; i++) {
0196         ret = regmap_write(regmap, REG_PWM, brightness);
0197         if (!ret)
0198             break;
0199     }
0200 
0201     mutex_unlock(&state->lock);
0202 
0203     return ret;
0204 }
0205 
0206 static const struct backlight_ops attiny_bl = {
0207     .update_status  = attiny_update_status,
0208 };
0209 
0210 static int attiny_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
0211 {
0212     return GPIO_LINE_DIRECTION_OUT;
0213 }
0214 
0215 static void attiny_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
0216 {
0217     struct attiny_lcd *state = gpiochip_get_data(gc);
0218     u8 last_val;
0219 
0220     if (off >= NUM_GPIO)
0221         return;
0222 
0223     mutex_lock(&state->lock);
0224 
0225     last_val = attiny_get_port_state(state, mappings[off].reg);
0226     if (val)
0227         last_val |= mappings[off].mask;
0228     else
0229         last_val &= ~mappings[off].mask;
0230 
0231     attiny_set_port_state(state, mappings[off].reg, last_val);
0232 
0233     if (off == RST_BRIDGE_N && val) {
0234         usleep_range(5000, 8000);
0235         regmap_write(state->regmap, REG_ADDR_H, 0x04);
0236         usleep_range(5000, 8000);
0237         regmap_write(state->regmap, REG_ADDR_L, 0x7c);
0238         usleep_range(5000, 8000);
0239         regmap_write(state->regmap, REG_WRITE_DATA_H, 0x00);
0240         usleep_range(5000, 8000);
0241         regmap_write(state->regmap, REG_WRITE_DATA_L, 0x00);
0242 
0243         msleep(100);
0244     }
0245 
0246     mutex_unlock(&state->lock);
0247 }
0248 
0249 static int attiny_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf)
0250 {
0251     struct i2c_msg msgs[1];
0252     u8 addr_buf[1] = { reg };
0253     u8 data_buf[1] = { 0, };
0254     int ret;
0255 
0256     /* Write register address */
0257     msgs[0].addr = client->addr;
0258     msgs[0].flags = 0;
0259     msgs[0].len = ARRAY_SIZE(addr_buf);
0260     msgs[0].buf = addr_buf;
0261 
0262     ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
0263     if (ret != ARRAY_SIZE(msgs))
0264         return -EIO;
0265 
0266     usleep_range(5000, 10000);
0267 
0268     /* Read data from register */
0269     msgs[0].addr = client->addr;
0270     msgs[0].flags = I2C_M_RD;
0271     msgs[0].len = 1;
0272     msgs[0].buf = data_buf;
0273 
0274     ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
0275     if (ret != ARRAY_SIZE(msgs))
0276         return -EIO;
0277 
0278     *buf = data_buf[0];
0279     return 0;
0280 }
0281 
0282 /*
0283  * I2C driver interface functions
0284  */
0285 static int attiny_i2c_probe(struct i2c_client *i2c,
0286         const struct i2c_device_id *id)
0287 {
0288     struct backlight_properties props = { };
0289     struct regulator_config config = { };
0290     struct backlight_device *bl;
0291     struct regulator_dev *rdev;
0292     struct attiny_lcd *state;
0293     struct regmap *regmap;
0294     unsigned int data;
0295     int ret;
0296 
0297     state = devm_kzalloc(&i2c->dev, sizeof(*state), GFP_KERNEL);
0298     if (!state)
0299         return -ENOMEM;
0300 
0301     mutex_init(&state->lock);
0302     i2c_set_clientdata(i2c, state);
0303 
0304     regmap = devm_regmap_init_i2c(i2c, &attiny_regmap_config);
0305     if (IS_ERR(regmap)) {
0306         ret = PTR_ERR(regmap);
0307         dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
0308             ret);
0309         goto error;
0310     }
0311 
0312     ret = attiny_i2c_read(i2c, REG_ID, &data);
0313     if (ret < 0) {
0314         dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret);
0315         goto error;
0316     }
0317 
0318     switch (data) {
0319     case 0xde: /* ver 1 */
0320     case 0xc3: /* ver 2 */
0321         break;
0322     default:
0323         dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data);
0324         ret = -ENODEV;
0325         goto error;
0326     }
0327 
0328     regmap_write(regmap, REG_POWERON, 0);
0329     msleep(30);
0330     regmap_write(regmap, REG_PWM, 0);
0331 
0332     config.dev = &i2c->dev;
0333     config.regmap = regmap;
0334     config.of_node = i2c->dev.of_node;
0335     config.init_data = &attiny_regulator_default;
0336     config.driver_data = state;
0337 
0338     rdev = devm_regulator_register(&i2c->dev, &attiny_regulator, &config);
0339     if (IS_ERR(rdev)) {
0340         dev_err(&i2c->dev, "Failed to register ATTINY regulator\n");
0341         ret = PTR_ERR(rdev);
0342         goto error;
0343     }
0344 
0345     props.type = BACKLIGHT_RAW;
0346     props.max_brightness = 0xff;
0347 
0348     state->regmap = regmap;
0349 
0350     bl = devm_backlight_device_register(&i2c->dev, dev_name(&i2c->dev),
0351                         &i2c->dev, state, &attiny_bl,
0352                         &props);
0353     if (IS_ERR(bl)) {
0354         ret = PTR_ERR(bl);
0355         goto error;
0356     }
0357 
0358     bl->props.brightness = 0xff;
0359 
0360     state->gc.parent = &i2c->dev;
0361     state->gc.label = i2c->name;
0362     state->gc.owner = THIS_MODULE;
0363     state->gc.base = -1;
0364     state->gc.ngpio = NUM_GPIO;
0365 
0366     state->gc.set = attiny_gpio_set;
0367     state->gc.get_direction = attiny_gpio_get_direction;
0368     state->gc.can_sleep = true;
0369 
0370     ret = devm_gpiochip_add_data(&i2c->dev, &state->gc, state);
0371     if (ret) {
0372         dev_err(&i2c->dev, "Failed to create gpiochip: %d\n", ret);
0373         goto error;
0374     }
0375 
0376     return 0;
0377 
0378 error:
0379     mutex_destroy(&state->lock);
0380 
0381     return ret;
0382 }
0383 
0384 static int attiny_i2c_remove(struct i2c_client *client)
0385 {
0386     struct attiny_lcd *state = i2c_get_clientdata(client);
0387 
0388     mutex_destroy(&state->lock);
0389 
0390     return 0;
0391 }
0392 
0393 static const struct of_device_id attiny_dt_ids[] = {
0394     { .compatible = "raspberrypi,7inch-touchscreen-panel-regulator" },
0395     {},
0396 };
0397 MODULE_DEVICE_TABLE(of, attiny_dt_ids);
0398 
0399 static struct i2c_driver attiny_regulator_driver = {
0400     .driver = {
0401         .name = "rpi_touchscreen_attiny",
0402         .of_match_table = of_match_ptr(attiny_dt_ids),
0403     },
0404     .probe = attiny_i2c_probe,
0405     .remove = attiny_i2c_remove,
0406 };
0407 
0408 module_i2c_driver(attiny_regulator_driver);
0409 
0410 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
0411 MODULE_DESCRIPTION("Regulator device driver for Raspberry Pi 7-inch touchscreen");
0412 MODULE_LICENSE("GPL v2");