platform: tegra: add cy8c_panel driver
[linux-3.10.git] / drivers / platform / tegra / panel-cy8c.c
1 /*
2  * CY8C4014-based display power sequence driver
3  *
4  * Copyright (C) 2015 NVIDIA Corporation. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/err.h>
25 #include <linux/slab.h>
26 #include <linux/i2c.h>
27 #include <linux/regmap.h>
28 #include <linux/debugfs.h>
29 #include <linux/mutex.h>
30 #include <linux/miscdevice.h>
31 #include <linux/uaccess.h>
32 #include <linux/delay.h>
33 #include <linux/gpio.h>
34 #include <linux/of_gpio.h>
35 #include <linux/platform/tegra/panel-cy8c.h>
36
37 /* register definitions */
38 #define CY8C_REG_CMD                    0x00
39 #define         CY8C_CMD_GOTO_BOOT      0x01
40 #define         CY8C_CMD_RESET          0x02
41 #define         CY8C_CMD_WRITE_DAT      0x05
42 #define         CY8C_CMD_SLEEP          0x06
43 #define         CY8C_CMD_LCD_ON         0x07
44 #define         CY8C_CMD_LCD_OFF        0x08
45 #define CY8C_REG_CMD_DAT                0x01
46 #define CY8C_REG_CMD_STATUS             0x02
47 #define         CY8C_STATUS_GOOD        0x00
48 #define         CY8C_STATUS_BUSY        0x01
49 #define         CY8C_STATUS_ERR         0x02
50 #define CY8C_REG_APP_MINOR_REV  0x03
51 #define CY8C_REG_APP_MAJOR_REV  0x04
52 #define CY8C_REG_PWR_SEQ_STATE  0x05
53 #define         CY8C_LCD_STATE_PWRING_ON        0x01
54 #define         CY8C_LCD_STATE_PWRING_OFF       0x02
55 #define         CY8C_LCD_STATE_ON       0x03
56 #define         CY8C_LCD_STATE_OFF      0x04
57 #define CY8C_REG_1V8_ON_DLY_LSB         0x06
58 #define CY8C_REG_1V8_ON_DLY_MSB         0x07
59 #define CY8C_REG_3V3_ON_DLY_LSB         0x08
60 #define CY8C_REG_3V3_ON_DLY_MSB         0x09
61 #define CY8C_REG_3V0_ON_DLY_LSB         0x0A
62 #define CY8C_REG_3V0_ON_DLY_MSB         0x0B
63 #define CY8C_REG_VPP_ON_DLY_LSB         0x0C
64 #define CY8C_REG_VPP_ON_DLY_MSB         0x0D
65 #define CY8C_REG_VMM_ON_DLY_LSB         0x0E
66 #define CY8C_REG_VMM_ON_DLY_MSB         0x0F
67 #define CY8C_REG_RST_ON_DLY_LSB         0x10
68 #define CY8C_REG_RST_ON_DLY_MSB         0x11
69 #define CY8C_REG_1V8_OFF_DLY_LSB        0x12
70 #define CY8C_REG_1V8_OFF_DLY_MSB        0x13
71 #define CY8C_REG_3V3_OFF_DLY_LSB        0x14
72 #define CY8C_REG_3V3_OFF_DLY_MSB        0x15
73 #define CY8C_REG_3V0_OFF_DLY_LSB        0x16
74 #define CY8C_REG_3V0_OFF_DLY_MSB        0x17
75 #define CY8C_REG_VPP_OFF_DLY_LSB        0x18
76 #define CY8C_REG_VPP_OFF_DLY_MSB        0x19
77 #define CY8C_REG_VMM_OFF_DLY_LSB        0x1A
78 #define CY8C_REG_VMM_OFF_DLY_MSB        0x1B
79 #define CY8C_REG_RST_OFF_DLY_LSB        0x1C
80 #define CY8C_REG_RST_OFF_DLY_MSB        0x1D
81 #define CY8C_REG_GPIO_STATE                     0x1E
82 #define         CY8C_REG_GPIO_LO                0x00
83 #define         CY8C_REG_GPIO_HI                0x01
84 #define CY8C_REG_MAX    0x1F
85
86 /* boot device mode address */
87 #define CY8C_BOOT_DEV_ADDR                      0x08
88
89 #define MAX_COMMAND_SIZE                        512
90 #define BASE_CMD_SIZE                           0x07
91 #define CMD_START                                       0x01
92 #define CMD_ENTER_BOOTLOADER            0x38
93 #define CMD_EXIT_BOOTLOADER                     0x3B
94 #define CMD_STOP                                        0x17
95 #define COMMAND_DATA_SIZE                       0x01
96 #define RESET                                           0x00
97 #define COMMAND_SIZE (BASE_CMD_SIZE + COMMAND_DATA_SIZE)
98
99 #define DEVICE_MODE_INVALID             0
100 #define DEVICE_MODE_APP                 1
101 #define DEVICE_MODE_BOOT                2
102
103 /* Expected amount of time that the panel
104  * may be in use by userspace for flashing*/
105 #define PANEL_LOCK_POLL_MS 1000
106 #define PANEL_LOCK_POLL_TIMEOUT_MS 30000
107
108 /* Expected amount of time for panel state change */
109 #define PANEL_STATE_POLL_MS 50
110 #define PANEL_STATE_POLL_TIMEOUT_MS 1000
111
112 #define CY8C_BOOT_DEV_NAME "cy8c_panel_boot"
113 #define CY8C_APP_DEV_NAME "cy8c_panel_app"
114
115 struct cy8c_data {
116         /* app device */
117         struct i2c_client *client;
118         struct regmap *regmap;
119         struct miscdevice miscdev_app;
120
121         /* boot device */
122         struct miscdevice miscdev_boot;
123         struct i2c_client *client_boot;
124         struct i2c_adapter *adap;
125         struct i2c_board_info brd_boot;
126
127         struct mutex lock;
128         struct dentry *debugdir;
129         int device_mode;
130         int en_gpio;
131 };
132
133 static struct cy8c_data *drvdata;
134
135 typedef unsigned short (*cy8c_crc_algo_t)(
136         unsigned char *buf, unsigned long size);
137
138 static int of_cy8c_panel_parse_pdata(struct i2c_client *client,
139         struct cy8c_data *data)
140 {
141         struct device_node *np = client->dev.of_node;
142         int en_gpio;
143         int ret;
144
145         en_gpio = of_get_named_gpio(np, "enable-gpio", 0);
146         if (en_gpio < 0) {
147                 dev_err(&data->client->dev,
148                         "enable-gpio property not found\n");
149                 return en_gpio;
150         }
151
152         if (gpio_is_valid(en_gpio)) {
153                 ret = devm_gpio_request_one(&client->dev, en_gpio,
154                         GPIOF_OUT_INIT_HIGH, CY8C_APP_DEV_NAME);
155                 if (ret) {
156                         dev_err(&data->client->dev, "enable-gpio is unavailable\n");
157                         return ret;
158                 }
159                 data->en_gpio = en_gpio;
160         } else {
161                 dev_err(&data->client->dev, "enable-gpio is invalid\n");
162                 return -EINVAL;
163         }
164
165         return 0;
166 }
167
168 static int _cy8c_poll_device(struct cy8c_data *data, u32 reg, u32 mask,
169                 u32 exp_val, u32 poll_interval_ms, u32 timeout_ms)
170 {
171         unsigned long timeout_jf = jiffies + msecs_to_jiffies(timeout_ms);
172         struct regmap *regmap = drvdata->regmap;
173         u32 reg_val = 0;
174         int ret;
175
176         do {
177                 ret = regmap_read(regmap, reg, &reg_val);
178                 if (unlikely(ret)) {
179                         dev_err(&data->client->dev,
180                                 "failed to read device register\n");
181                         return ret;
182                 }
183
184                 if ((reg_val & mask) != exp_val)
185                         msleep(poll_interval_ms);
186                 else
187                         return 0;
188
189         } while (time_after(timeout_jf, jiffies));
190
191         dev_err(&data->client->dev, "device poll timeout\n");
192
193         return -ETIMEDOUT;
194 }
195
196 static int _cy8c_wait_for_pwr_state(struct cy8c_data *data, int state)
197 {
198         return _cy8c_poll_device(data, CY8C_REG_PWR_SEQ_STATE, 0xff,
199                 state, PANEL_STATE_POLL_MS, PANEL_STATE_POLL_TIMEOUT_MS);
200 }
201
202 static int _cy8c_panel_set_state(struct cy8c_data *data, bool enable)
203 {
204         struct regmap *regmap = data->regmap;
205         int ret;
206         int reg;
207         int target_state = enable ? CY8C_LCD_STATE_ON : CY8C_LCD_STATE_OFF;
208         int target_cmd = enable ? CY8C_CMD_LCD_ON : CY8C_CMD_LCD_OFF;
209
210         if (data->device_mode != DEVICE_MODE_APP) {
211                 dev_err(&data->client->dev,
212                         "can't set panel state, device not in app mode\n");
213                 ret = -EBUSY;
214                 goto end;
215         }
216
217         ret = regmap_read(regmap, CY8C_REG_PWR_SEQ_STATE, &reg);
218         if (ret) {
219                 dev_err(&data->client->dev,
220                         "failed to read panel power state\n");
221                 goto end;
222         }
223
224         /* Wait for ongoing state transitions to finish */
225         if (reg == CY8C_LCD_STATE_PWRING_ON) {
226                 ret = _cy8c_wait_for_pwr_state(data, CY8C_LCD_STATE_ON);
227                 if (ret)
228                         goto end;
229
230                 reg = CY8C_LCD_STATE_ON;
231         } else if (reg == CY8C_LCD_STATE_PWRING_OFF) {
232                 ret = _cy8c_wait_for_pwr_state(data, CY8C_LCD_STATE_OFF);
233                 if (ret)
234                         goto end;
235
236                 reg = CY8C_LCD_STATE_OFF;
237         }
238
239         if (reg == target_state)
240                 goto end;
241
242         /* en_gpio must be asserted while the panel is on */
243         if (enable) {
244                 ret = gpio_direction_output(data->en_gpio, 1);
245                 if (ret)
246                         goto end;
247         }
248
249         ret = regmap_write(regmap, CY8C_REG_CMD, target_cmd);
250         if (ret)
251                 goto end;
252
253         /* Wait until transition is complete */
254         ret = _cy8c_wait_for_pwr_state(data, target_state);
255         if (ret) {
256                 dev_err(&data->client->dev,
257                         "timedout while setting panel state\n");
258                 goto end;
259         }
260
261         if (!enable) {
262                 ret = gpio_direction_output(data->en_gpio, 0);
263                 if (ret)
264                         goto end;
265         }
266
267 end:
268         /* If panel disable failed, deassert en_gpio anyway; if cy8c app
269          * is still responsive, it should still disable the panel */
270         if (!enable && ret)
271                 gpio_direction_output(data->en_gpio, 0);
272         return ret;
273 }
274
275 int cy8c_panel_set_state(bool enable)
276 {
277         int ret = 0;
278         struct cy8c_data *data;
279
280         /* drvdata will be null if device isn't present on this platform
281          * (no compatible node found), or -ENODATA if probe ran but failed. */
282         if (!drvdata) {
283                 pr_debug("cy8c not present\n");
284                 return -ENODEV;
285         } else if (IS_ERR(drvdata)) {
286                 pr_err("cy8c uninitialized\n");
287                 return PTR_ERR(drvdata);
288         }
289
290         data = drvdata;
291
292         mutex_lock(&data->lock);
293
294         ret = _cy8c_panel_set_state(data, enable);
295         if (ret)
296                 dev_err(&data->client->dev,
297                         "failed to set panel state, error %d\n", ret);
298
299         mutex_unlock(&data->lock);
300         return ret;
301 }
302 EXPORT_SYMBOL(cy8c_panel_set_state);
303
304 static int cy8c_panel_pwr_state_get(void *vdata, u64 *val)
305 {
306         struct cy8c_data *data = vdata;
307         int ret;
308         u32 reg_val;
309
310         if (!data) {
311                 dev_err(&data->client->dev, "no device\n");
312                 return -ENODEV;
313         }
314
315         mutex_lock(&data->lock);
316
317         if (data->device_mode != DEVICE_MODE_APP) {
318                 dev_err(&data->client->dev,
319                         "can't get panel state, device in boot mode\n");
320                 ret = -EBUSY;
321                 goto unlock;
322         }
323
324         ret = regmap_read(data->regmap, CY8C_REG_PWR_SEQ_STATE,
325                 &reg_val);
326         if (ret) {
327                 dev_err(&data->client->dev,
328                         "failed to read device register\n");
329                 goto unlock;
330         }
331
332         *val = reg_val;
333
334 unlock:
335         mutex_unlock(&data->lock);
336         return ret;
337 }
338
339 static int cy8c_panel_pwr_state_set(void *vdata, u64 val)
340 {
341         struct cy8c_data *data = vdata;
342
343         /* val must be 1 (on) or 0 (off) */
344         if (val > 1) {
345                 dev_err(&data->client->dev,
346                         "invalid panel power state requested\n");
347                 return -EINVAL;
348         }
349
350         return cy8c_panel_set_state(val);
351 }
352 DEFINE_SIMPLE_ATTRIBUTE(cy8c_panel_pwr_state_fops,
353         cy8c_panel_pwr_state_get, cy8c_panel_pwr_state_set, "%llu\n");
354
355 static unsigned short cy8c_crc_algo_sum(
356         unsigned char *buf, unsigned long size)
357 {
358         unsigned short sum = 0;
359         while (size-- > 0)
360                 sum += *buf++;
361
362         return 1 + ~sum;
363 }
364
365 static unsigned short cy8c_crc_algo_crc(
366         unsigned char *buf, unsigned long size)
367 {
368         unsigned short crc = 0xffff;
369         unsigned short tmp;
370         int i;
371
372         if (size == 0)
373                 return ~crc;
374
375         do {
376                 for (i = 0, tmp = 0x00ff & *buf++;
377                         i < 8;
378                         i++, tmp >>= 1) {
379                         if ((crc & 0x0001) ^ (tmp & 0x0001))
380                                 crc = (crc >> 1) ^ 0x8408;
381                         else
382                                 crc >>= 1;
383                 }
384         } while (--size);
385
386         crc = ~crc;
387         tmp = crc;
388         crc = (crc << 8) | (tmp >> 8 & 0xFF);
389
390         return crc;
391 }
392
393 static cy8c_crc_algo_t crc_algos[] = {
394         &cy8c_crc_algo_sum,
395         &cy8c_crc_algo_crc,
396 };
397
398 static int _cy8c_send_app_mode(struct cy8c_data *data,
399                 cy8c_crc_algo_t crc_func)
400 {
401         unsigned char cmd_buf[COMMAND_SIZE] = {0, };
402         unsigned short checksum;
403         unsigned long res_size;
404         unsigned long cmd_size;
405         int ret;
406
407         if (COMMAND_SIZE < 3)
408                 return -EINVAL;
409
410         res_size = BASE_CMD_SIZE;
411         cmd_size = COMMAND_SIZE;
412         cmd_buf[0] = CMD_START;
413         cmd_buf[1] = CMD_EXIT_BOOTLOADER;
414         cmd_buf[2] = (unsigned char)COMMAND_DATA_SIZE;
415         cmd_buf[3] = (unsigned char)(COMMAND_DATA_SIZE >> 8);
416         cmd_buf[4] = RESET;
417         checksum = (*crc_func)(cmd_buf, COMMAND_SIZE - 3);
418         cmd_buf[5] = (unsigned char)checksum;
419         cmd_buf[6] = (unsigned char)(checksum >> 8);
420         cmd_buf[7] = CMD_STOP;
421
422         ret = i2c_master_send(data->client_boot, cmd_buf, cmd_size);
423
424         return ret;
425 }
426
427 /* Called from probe path only, so left unlocked */
428 static int cy8c_boot_mode_enter(struct cy8c_data *data,
429                 cy8c_crc_algo_t crc_func)
430 {
431         const unsigned long RESULT_DATA_SIZE = 8;
432         unsigned short checksum;
433         unsigned char cmd_buf[BASE_CMD_SIZE];
434         unsigned char res_buf[BASE_CMD_SIZE + RESULT_DATA_SIZE];
435         int res_size, cmd_size;
436         int ret;
437
438         if (COMMAND_SIZE < 3)
439                 return -EINVAL;
440
441         res_size = BASE_CMD_SIZE + RESULT_DATA_SIZE;
442         cmd_size = BASE_CMD_SIZE;
443         cmd_buf[0] = CMD_START;
444         cmd_buf[1] = CMD_ENTER_BOOTLOADER;
445         cmd_buf[2] = 0;
446         cmd_buf[3] = 0;
447         checksum = (*crc_func)(cmd_buf, BASE_CMD_SIZE - 3);
448         cmd_buf[4] = (unsigned char)checksum;
449         cmd_buf[5] = (unsigned char)(checksum >> 8);
450         cmd_buf[6] = CMD_STOP;
451
452         ret = i2c_master_send(data->client_boot, cmd_buf, cmd_size);
453         if (ret < 0)
454                 return ret;
455
456         ret = i2c_master_recv(data->client_boot, res_buf, res_size);
457
458         return ret;
459 }
460
461 /* Called from probe path only, so left unlocked */
462 static int cy8c_boot_mode_test(struct cy8c_data *data)
463 {
464         int i, ret;
465         for (i = 0; i < ARRAY_SIZE(crc_algos); i++) {
466                 ret = cy8c_boot_mode_enter(data, crc_algos[i]);
467                 if (ret > 0)
468                         ret = 0;
469                 else
470                         dev_err(&data->client->dev,
471                                 "device not in boot mode\n");
472
473                 if (ret == 0)
474                         break;
475         }
476
477         return ret;
478 }
479
480 static int _cy8c_app_mode_test(struct cy8c_data *data)
481 {
482         int ret, reg;
483         ret = regmap_read(data->regmap, CY8C_REG_APP_MINOR_REV, &reg);
484         return ret;
485 }
486
487 /*
488         app mode
489         called from user space
490
491         The packet sent to device in boot mode needs a crc value
492         as parameter. There are 2 algorithms to compute the crc
493         according to the content of the fw file in user space code
494         implementation at vendor/bin/vendor/nvidia/loki/utils/cyload.
495
496         In the current design the 'sum' algo is used to compute
497         crc, but we will support both of the ALGOes just in case.
498 */
499 static int _cy8c_boot_to_app(struct cy8c_data *data)
500 {
501         int i, ret;
502
503         for (i = 0; i < ARRAY_SIZE(crc_algos); i++) {
504                 ret = _cy8c_send_app_mode(data, crc_algos[i]);
505                 if (ret > 0)
506                         ret = 0;
507                 else
508                         dev_err(&data->client->dev,
509                                 "cannot put device to app mode\n");
510
511                 if (ret == 0) {
512
513                         /* 100 ms is enough in test */
514                         msleep(100);
515
516                         ret = _cy8c_app_mode_test(data);
517                         if (unlikely(ret))
518                                 dev_err(&data->client->dev,
519                                         "device not in app mode %d\n", i);
520                 }
521
522                 if (ret == 0)
523                         break;
524         }
525
526         return ret;
527 }
528
529 static ssize_t cy8c_boot_mode_show(struct device *dev,
530         struct device_attribute *attr,
531         char *buf)
532 {
533         struct miscdevice *miscdev_app_cdev = dev_get_drvdata(dev);
534         struct cy8c_data *data = NULL;
535         char *name = "unknown";
536
537         data = container_of(miscdev_app_cdev, struct cy8c_data, miscdev_app);
538
539         /* Lock to make sure device_mode isn't undergoing a state transition */
540         mutex_lock(&data->lock);
541
542         if (data->device_mode == DEVICE_MODE_APP)
543                 name = "app";
544         else if (data->device_mode == DEVICE_MODE_BOOT)
545                 name = "boot";
546
547         mutex_unlock(&data->lock);
548
549         return sprintf(buf, "%s\n", name);
550 }
551
552 int _cy8c_mode_set(struct cy8c_data *data, int mode)
553 {
554         int ret;
555
556         switch (mode) {
557         case DEVICE_MODE_APP:
558                 /* cy8c is already be in app mode if this is called
559                  * from cyload */
560                 ret = _cy8c_app_mode_test(data);
561                 if (ret) {
562                         dev_err(&data->client->dev, "trying to jump to app\n");
563                         ret = _cy8c_boot_to_app(data);
564                         if (ret) {
565                                 dev_err(&data->client->dev, "failed jumping to app\n");
566                                 return ret;
567                         }
568                 }
569
570                 data->device_mode = DEVICE_MODE_APP;
571                 break;
572         case DEVICE_MODE_BOOT:
573                 /* Try disabling the panel before resetting the uC.
574                  * If this command fails then either 1) uC is already
575                  * in boot mode, or 2) uC will take care of disabling the
576                  * panel before reset */
577                 ret = _cy8c_panel_set_state(data, false);
578                 if (ret)
579                         dev_err(&data->client->dev,
580                                 "can't disable panel before entering boot\n");
581
582                 ret = regmap_write(data->regmap, CY8C_REG_CMD,
583                         CY8C_CMD_GOTO_BOOT);
584                 if (ret) {
585                         dev_err(&data->client->dev,
586                                 "cannot put dev to boot mode\n");
587                         return ret;
588                 }
589
590                 data->device_mode = DEVICE_MODE_BOOT;
591                 break;
592         default:
593                 dev_err(&data->client->dev,
594                         "unknown mode %d requested\n", mode);
595                 ret = -EINVAL;
596         }
597
598         return ret;
599 }
600
601 int cy8c_mode_set(struct cy8c_data *data, int mode)
602 {
603         int ret;
604
605         mutex_lock(&data->lock);
606         ret = _cy8c_mode_set(data, mode);
607         mutex_unlock(&data->lock);
608
609         return ret;
610 }
611
612 /*
613         0 -> APP mode
614         1 -> Boot mode
615 */
616 static ssize_t cy8c_boot_mode_set(struct device *dev,
617         struct device_attribute *attr,
618         const char *buf, size_t size)
619 {
620         struct miscdevice *miscdev_app_cdev = dev_get_drvdata(dev);
621         struct cy8c_data *data = NULL;
622         ssize_t ret = -EINVAL;
623         int action = -1;
624
625         data = container_of(miscdev_app_cdev, struct cy8c_data, miscdev_app);
626
627         if (buf == NULL || buf[0] == 0) {
628                 dev_err(&data->client->dev, "input buf invalid\n");
629                 return -EINVAL;
630         }
631
632         if (sscanf(buf, "%d", &action) != 1) {
633                 dev_err(&data->client->dev, "input data format invalid\n");
634                 return -EINVAL;
635         }
636
637         if (action != 0 && action != 1) {
638                 dev_err(&data->client->dev, "input data format value\n");
639                 return -EINVAL;
640         }
641
642         ret = cy8c_mode_set(data, action ? DEVICE_MODE_BOOT :
643                 DEVICE_MODE_APP);
644
645         return ret == 0 ? size : ret;
646 }
647
648 static ssize_t cy8c_version_show(struct device *dev,
649         struct device_attribute *attr,
650         char *buf)
651 {
652         struct miscdevice *miscdev_app_cdev = dev_get_drvdata(dev);
653         struct cy8c_data *data = NULL;
654         ssize_t ret = 0;
655         ssize_t count = 0;
656         int version = -1;
657         data = container_of(miscdev_app_cdev, struct cy8c_data, miscdev_app);
658
659         mutex_lock(&data->lock);
660
661         if (data->device_mode != DEVICE_MODE_APP) {
662                 dev_err(&data->client->dev, "device not in app mode %s\n",
663                         __func__);
664                 ret = -EAGAIN;
665                 goto end;
666         }
667
668         ret = regmap_read(data->regmap,
669                 CY8C_REG_APP_MINOR_REV,
670                 &version);
671         if (unlikely(ret)) {
672                 dev_err(&data->client->dev, "device in boot mode?\n");
673                 goto end;
674         }
675         count += sprintf(buf, "%02x: %02x\n", CY8C_REG_APP_MINOR_REV, version);
676
677         ret = regmap_read(data->regmap,
678                 CY8C_REG_APP_MAJOR_REV,
679                 &version);
680         if (unlikely(ret)) {
681                 dev_err(&data->client->dev, "device in boot mode?\n");
682                 goto end;
683         }
684         count += sprintf(buf + count, "%02x: %02x\n",
685                 CY8C_REG_APP_MAJOR_REV, version);
686
687 end:
688         mutex_unlock(&data->lock);
689
690         return count;
691 }
692
693 static ssize_t cy8c_version_set(struct device *dev,
694                                   struct device_attribute *attr,
695                                   const char *buf, size_t size)
696 {
697         struct miscdevice *miscdev_app_cdev = dev_get_drvdata(dev);
698         struct cy8c_data *data = NULL;
699         data = container_of(miscdev_app_cdev, struct cy8c_data, miscdev_app);
700         dev_err(&data->client->dev, "not implemented\n");
701         return -ENOSYS;
702 }
703
704 static DEVICE_ATTR(boot_mode, S_IRUGO|S_IWUSR,
705                 cy8c_boot_mode_show, cy8c_boot_mode_set);
706 static DEVICE_ATTR(version, S_IRUGO|S_IWUSR,
707                 cy8c_version_show, cy8c_version_set);
708
709 static int cy8c_boot_open(struct inode *inode, struct file *file)
710 {
711         struct miscdevice *miscdev_boot =
712                 (struct miscdevice *)file->private_data;
713         struct cy8c_data *data = NULL;
714         data = container_of(miscdev_boot, struct cy8c_data, miscdev_boot);
715
716         if (!mutex_trylock(&data->lock)) {
717                 dev_err(&data->client->dev, "already opened\n");
718                 return -EBUSY;
719         }
720
721         if (data->device_mode != DEVICE_MODE_BOOT) {
722                 dev_err(&data->client->dev,
723                         "wait for device in boot mode\n");
724
725                 mutex_unlock(&data->lock);
726                 return -EIO;
727         }
728
729         file->private_data = data;
730         dev_err(&data->client->dev, "opened\n");
731         /* mutex is unlocked in cy8c_boot_release */
732         return 0;
733 }
734
735 static int cy8c_boot_release(struct inode *inode, struct file *file)
736 {
737         int ret;
738         struct cy8c_data *data = file->private_data;
739         file->private_data = NULL;
740
741         /* cyload doesn't restore uC to app state, driver is responsible
742          * for that. */
743         ret = _cy8c_mode_set(data, DEVICE_MODE_APP);
744
745         /* acquired in cy8c_boot_open */
746         mutex_unlock(&data->lock);
747
748         dev_err(&data->client->dev, "released\n");
749
750         return ret;
751 }
752
753 static ssize_t _cy8c_boot_read(struct file *filp, char __user *buf,
754                                   size_t count, loff_t *offset)
755 {
756         struct cy8c_data *data = filp->private_data;
757         unsigned char *p = NULL;
758         int ret;
759
760         if (data->device_mode != DEVICE_MODE_BOOT) {
761                 dev_err(&data->client->dev, "device not in boot mode\n");
762                 ret = -EINVAL;
763                 goto end;
764         }
765
766         if (count == 0) {
767                 dev_err(&data->client->dev, "no data\n");
768                 ret = -EINVAL;
769                 goto end;
770         }
771
772         p = kzalloc(count, GFP_KERNEL);
773
774         if (p == NULL) {
775                 dev_err(&data->client->dev, "no memory\n");
776                 ret = -ENOMEM;
777                 goto end;
778         }
779
780         /* Read data */
781         ret = i2c_master_recv(data->client_boot, p, count);
782         if (ret != count) {
783                 dev_err(&data->client->dev,
784                         "failed to read %d\n", ret);
785                 ret = -EIO;
786                 goto end;
787         }
788
789         ret = copy_to_user(buf, p, count);
790         if (ret) {
791                 dev_err(&data->client->dev,
792                         "failed to copy from user space\n");
793         }
794
795 end:
796
797         /* kfree(NULL) is safe */
798         kfree(p);
799
800         return ret == 0 ? count : ret;
801 }
802
803 static ssize_t _cy8c_boot_write(struct file *filp, const char __user *buf,
804                                    size_t count, loff_t *offset)
805 {
806         struct cy8c_data *data = filp->private_data;
807         unsigned char *p = NULL;
808         int ret;
809
810         if (data->device_mode != DEVICE_MODE_BOOT) {
811                 dev_err(&data->client->dev, "device not in boot mode\n");
812                 ret = -EINVAL;
813                 goto end;
814         }
815
816         if (count == 0) {
817                 dev_err(&data->client->dev, "no data\n");
818                 ret = -EINVAL;
819                 goto end;
820         }
821
822         p = kzalloc(count, GFP_KERNEL);
823
824         if (p == NULL) {
825                 dev_err(&data->client->dev, "no memory\n");
826                 ret = -ENOMEM;
827                 goto end;
828         }
829
830         if (copy_from_user(p, buf, count)) {
831                 dev_err(&data->client->dev,
832                         "failed to copy from user space\n");
833                 ret = -EFAULT;
834                 goto end;
835         }
836
837         /* Write data */
838         ret = i2c_master_send(data->client_boot, p, count);
839         if (ret != count) {
840                 dev_err(&data->client->dev,
841                         "failed to write %d\n", ret);
842                 ret = -EIO;
843         }
844
845 end:
846
847         /* kfree(NULL) is safe */
848         kfree(p);
849
850         return ret;
851 }
852
853 /* Read and write ops must be done in locked context to avoid clashes with
854  * cy8c state changes triggered by other sources. Acquiring/releasing
855  * the mutex is done by the open and release ops.
856  *
857  * This interface is to be used for sideloading firmware only.
858  */
859 static const struct file_operations cy8c_boot_fileops = {
860         .owner = THIS_MODULE,
861         .open = cy8c_boot_open,
862         .release = cy8c_boot_release,
863         .read = _cy8c_boot_read,
864         .write = _cy8c_boot_write,
865 };
866
867 static int cy8c_panel_create_sysfs(struct cy8c_data *data)
868 {
869         int ret;
870         struct i2c_client *client = data->client;
871
872         ret = device_create_file(data->miscdev_app.this_device,
873                 &dev_attr_boot_mode);
874         if (ret) {
875                 dev_err(&client->dev, "Failed to register boot sys node\n");
876                 goto err1;
877         }
878
879         ret = device_create_file(data->miscdev_app.this_device,
880                 &dev_attr_version);
881         if (ret) {
882                 dev_err(&client->dev, "Failed to register version sys node\n");
883                 goto err2;
884         }
885
886         return ret;
887
888 err2:
889         device_remove_file(data->miscdev_app.this_device, &dev_attr_boot_mode);
890
891 err1:
892         return ret;
893 }
894
895 static void cy8c_panel_remove_sysfs(struct cy8c_data *data)
896 {
897         device_remove_file(data->miscdev_app.this_device, &dev_attr_boot_mode);
898         device_remove_file(data->miscdev_app.this_device, &dev_attr_version);
899 }
900
901 #ifdef CONFIG_DEBUG_FS
902 static void cy8c_panel_remove_debugfs(struct cy8c_data *data)
903 {
904         /* debugfs_remove_recursive(NULL) is safe */
905         debugfs_remove_recursive(data->debugdir);
906         data->debugdir = NULL;
907 }
908
909 static void cy8c_panel_create_debugfs(struct cy8c_data *data)
910 {
911         struct dentry *ret;
912
913         data->debugdir = debugfs_create_dir(CY8C_APP_DEV_NAME, NULL);
914         if (!data->debugdir)
915                 goto err;
916
917         ret = debugfs_create_file("panel_pwr_state", S_IRUGO,
918                 data->debugdir, data, &cy8c_panel_pwr_state_fops);
919         if (!ret)
920                 goto err;
921
922         return;
923
924 err:
925         cy8c_panel_remove_debugfs(data);
926         dev_err(&data->client->dev, "Failed to create debugfs\n");
927         return;
928 }
929 #else
930 static void cy8c_panel_create_debugfs(struct cy8c_data *data) { }
931 static void cy8c_panel_remove_debugfs(struct cy8c_data *data) { }
932 #endif
933
934 static int cy8c_panel_probe(struct i2c_client *client,
935                                         const struct i2c_device_id *id)
936 {
937         struct i2c_adapter *adapter = client->adapter;
938         struct cy8c_data *data;
939         struct regmap_config rconfig;
940         int ret, reg;
941
942         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
943                 dev_err(&client->dev, "i2c functionality check fail.\n");
944                 ret = -ENODEV;
945                 goto err1;
946         }
947
948         data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
949         if (!data) {
950                 ret = -ENOMEM;
951                 goto err1;
952         }
953
954         /* enable print in show/get */
955         data->client = client;
956
957         ret = of_cy8c_panel_parse_pdata(client, data);
958         if (ret) {
959                 dev_err(&client->dev, "of data parse failed\n");
960                 goto err2;
961         }
962
963         memset(&rconfig, 0, sizeof(rconfig));
964         rconfig.reg_bits = 8;
965         rconfig.val_bits = 8;
966         rconfig.cache_type = REGCACHE_NONE;
967         rconfig.max_register = CY8C_REG_MAX-1;
968
969         /*This should happen before set clientdata*/
970         data->regmap = regmap_init_i2c(client, &rconfig);
971         if (!data->regmap) {
972                 devm_kfree(&client->dev, data);
973                 dev_err(&client->dev, "Failed to allocate register map\n");
974                 ret = -ENOMEM;
975                 goto err2;
976         }
977
978         /* boot device I2C client */
979         data->adap = i2c_get_adapter(client->adapter->nr);
980         memset(&data->brd_boot, 0, sizeof(data->brd_boot));
981         strncpy(data->brd_boot.type, CY8C_BOOT_DEV_NAME,
982                 sizeof(data->brd_boot.type));
983         data->brd_boot.addr = CY8C_BOOT_DEV_ADDR;
984         data->client_boot = i2c_new_device(data->adap, &data->brd_boot);
985
986         i2c_set_clientdata(client, data);
987
988         data->device_mode = DEVICE_MODE_INVALID;
989
990         /*
991                 Sometimes the app fw is broken or out of integration,
992                 so we will detect app mode first then boot mode
993         */
994         ret = regmap_read(data->regmap, CY8C_REG_APP_MAJOR_REV, &reg);
995         if (ret == 0) {
996                 dev_dbg(&client->dev, "rev: 0x%02x ", reg);
997
998                 ret = regmap_read(data->regmap, CY8C_REG_APP_MINOR_REV, &reg);
999                 if (ret) {
1000                         dev_err(&client->dev, "Failed to read revision-minor\n");
1001                         goto err3;
1002                 }
1003
1004                 dev_dbg(&client->dev, "0x%02x\n", reg);
1005                 data->device_mode = DEVICE_MODE_APP;
1006         } else {
1007                 dev_dbg(&client->dev, "not detect app device\n");
1008                 dev_dbg(&client->dev, "continue to detect boot device\n");
1009
1010                 /* Detect whether boot device is available */
1011                 ret = cy8c_boot_mode_test(data);
1012                 if (ret == 0) {
1013                         dev_dbg(&client->dev, "boot device detected\n");
1014                         data->device_mode = DEVICE_MODE_BOOT;
1015                 } else {
1016                         dev_dbg(&client->dev, "boot device not detected\n");
1017                         goto err3;
1018                 }
1019         }
1020
1021         /* boot device */
1022         data->miscdev_boot.name = CY8C_BOOT_DEV_NAME;
1023         data->miscdev_boot.fops = &cy8c_boot_fileops;
1024         data->miscdev_boot.minor = MISC_DYNAMIC_MINOR;
1025         ret = misc_register(&data->miscdev_boot);
1026         if (ret) {
1027                 dev_err(&client->dev, "%s unable to register misc device %s\n",
1028                         __func__, CY8C_BOOT_DEV_NAME);
1029                 goto err3;
1030         }
1031
1032         /* app device */
1033         data->miscdev_app.name = CY8C_APP_DEV_NAME;
1034         data->miscdev_app.minor = MISC_DYNAMIC_MINOR;
1035         data->miscdev_app.parent = &client->dev;
1036         ret = misc_register(&data->miscdev_app);
1037         if (ret) {
1038                 dev_err(&client->dev, "%s unable to register misc device %s\n",
1039                         __func__, CY8C_APP_DEV_NAME);
1040                 goto err4;
1041         }
1042
1043         ret = cy8c_panel_create_sysfs(data);
1044         if (ret)
1045                 goto err5;
1046
1047         cy8c_panel_create_debugfs(data);
1048
1049         mutex_init(&data->lock);
1050
1051         /* cache for calls from other modules */
1052         drvdata = data;
1053
1054         return ret;
1055
1056 err5:
1057         misc_deregister(&data->miscdev_app);
1058
1059 err4:
1060         misc_deregister(&data->miscdev_boot);
1061
1062 err3:
1063         if (data->client_boot)
1064                 i2c_unregister_device(data->client_boot);
1065         if (data->adap)
1066                 i2c_put_adapter(data->adap);
1067
1068 err2:
1069         devm_kfree(&client->dev, data);
1070 err1:
1071         drvdata = (struct cy8c_data *)-ENODATA;
1072         return ret;
1073 }
1074
1075 static int cy8c_panel_remove(struct i2c_client *client)
1076 {
1077         struct cy8c_data *data = i2c_get_clientdata(client);
1078
1079         devm_gpio_free(&client->dev, data->en_gpio);
1080
1081         cy8c_panel_remove_sysfs(data);
1082         cy8c_panel_remove_debugfs(data);
1083
1084         if (data->miscdev_boot.this_device)
1085                 misc_deregister(&data->miscdev_app);
1086
1087         if (data->miscdev_boot.this_device)
1088                 misc_deregister(&data->miscdev_boot);
1089
1090         if (data->client_boot)
1091                 i2c_unregister_device(data->client_boot);
1092
1093         if (data->adap)
1094                 i2c_put_adapter(data->adap);
1095
1096         mutex_destroy(&data->lock);
1097         drvdata = NULL;
1098
1099         return 0;
1100 }
1101
1102 static const struct i2c_device_id cy8c_panel_id[] = {
1103         {"cy8c_panel", 0},
1104         { }
1105 };
1106 MODULE_DEVICE_TABLE(i2c, cy8c_panel_id);
1107
1108 #ifdef CONFIG_OF
1109 static struct of_device_id cy8c_of_match[] = {
1110         {.compatible = "nvidia,cy8c_panel", },
1111         { },
1112 };
1113 #endif
1114
1115 static struct i2c_driver cy8c_panel_driver = {
1116         .driver = {
1117                 .name   = "cy8c_panel",
1118                 .owner  = THIS_MODULE,
1119 #ifdef CONFIG_OF
1120                 .of_match_table =
1121                         of_match_ptr(cy8c_of_match),
1122 #endif
1123         },
1124         .probe    = cy8c_panel_probe,
1125         .remove  = cy8c_panel_remove,
1126         .id_table   = cy8c_panel_id,
1127 };
1128
1129 module_i2c_driver(cy8c_panel_driver);
1130
1131 MODULE_AUTHOR("Daniel Solomon <daniels@nvidia.com>");
1132 MODULE_DESCRIPTION("CY8C I2C based display power sequence driver");
1133 MODULE_LICENSE("GPL");