cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lm3630a_bl.c (16022B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3* Simple driver for Texas Instruments LM3630A Backlight driver chip
      4* Copyright (C) 2012 Texas Instruments
      5*/
      6#include <linux/module.h>
      7#include <linux/slab.h>
      8#include <linux/i2c.h>
      9#include <linux/backlight.h>
     10#include <linux/err.h>
     11#include <linux/delay.h>
     12#include <linux/uaccess.h>
     13#include <linux/interrupt.h>
     14#include <linux/regmap.h>
     15#include <linux/gpio/consumer.h>
     16#include <linux/pwm.h>
     17#include <linux/platform_data/lm3630a_bl.h>
     18
     19#define REG_CTRL	0x00
     20#define REG_BOOST	0x02
     21#define REG_CONFIG	0x01
     22#define REG_BRT_A	0x03
     23#define REG_BRT_B	0x04
     24#define REG_I_A		0x05
     25#define REG_I_B		0x06
     26#define REG_INT_STATUS	0x09
     27#define REG_INT_EN	0x0A
     28#define REG_FAULT	0x0B
     29#define REG_PWM_OUTLOW	0x12
     30#define REG_PWM_OUTHIGH	0x13
     31#define REG_FILTER_STRENGTH	0x50
     32#define REG_MAX		0x50
     33
     34#define INT_DEBOUNCE_MSEC	10
     35
     36#define LM3630A_BANK_0		0
     37#define LM3630A_BANK_1		1
     38
     39#define LM3630A_NUM_SINKS	2
     40#define LM3630A_SINK_0		0
     41#define LM3630A_SINK_1		1
     42
     43struct lm3630a_chip {
     44	struct device *dev;
     45	struct delayed_work work;
     46
     47	int irq;
     48	struct workqueue_struct *irqthread;
     49	struct lm3630a_platform_data *pdata;
     50	struct backlight_device *bleda;
     51	struct backlight_device *bledb;
     52	struct gpio_desc *enable_gpio;
     53	struct regmap *regmap;
     54	struct pwm_device *pwmd;
     55	struct pwm_state pwmd_state;
     56};
     57
     58/* i2c access */
     59static int lm3630a_read(struct lm3630a_chip *pchip, unsigned int reg)
     60{
     61	int rval;
     62	unsigned int reg_val;
     63
     64	rval = regmap_read(pchip->regmap, reg, &reg_val);
     65	if (rval < 0)
     66		return rval;
     67	return reg_val & 0xFF;
     68}
     69
     70static int lm3630a_write(struct lm3630a_chip *pchip,
     71			 unsigned int reg, unsigned int data)
     72{
     73	return regmap_write(pchip->regmap, reg, data);
     74}
     75
     76static int lm3630a_update(struct lm3630a_chip *pchip,
     77			  unsigned int reg, unsigned int mask,
     78			  unsigned int data)
     79{
     80	return regmap_update_bits(pchip->regmap, reg, mask, data);
     81}
     82
     83/* initialize chip */
     84static int lm3630a_chip_init(struct lm3630a_chip *pchip)
     85{
     86	int rval;
     87	struct lm3630a_platform_data *pdata = pchip->pdata;
     88
     89	usleep_range(1000, 2000);
     90	/* set Filter Strength Register */
     91	rval = lm3630a_write(pchip, REG_FILTER_STRENGTH, 0x03);
     92	/* set Cofig. register */
     93	rval |= lm3630a_update(pchip, REG_CONFIG, 0x07, pdata->pwm_ctrl);
     94	/* set boost control */
     95	rval |= lm3630a_write(pchip, REG_BOOST, 0x38);
     96	/* set current A */
     97	rval |= lm3630a_update(pchip, REG_I_A, 0x1F, 0x1F);
     98	/* set current B */
     99	rval |= lm3630a_write(pchip, REG_I_B, 0x1F);
    100	/* set control */
    101	rval |= lm3630a_update(pchip, REG_CTRL, 0x14, pdata->leda_ctrl);
    102	rval |= lm3630a_update(pchip, REG_CTRL, 0x0B, pdata->ledb_ctrl);
    103	usleep_range(1000, 2000);
    104	/* set brightness A and B */
    105	rval |= lm3630a_write(pchip, REG_BRT_A, pdata->leda_init_brt);
    106	rval |= lm3630a_write(pchip, REG_BRT_B, pdata->ledb_init_brt);
    107
    108	if (rval < 0)
    109		dev_err(pchip->dev, "i2c failed to access register\n");
    110	return rval;
    111}
    112
    113/* interrupt handling */
    114static void lm3630a_delayed_func(struct work_struct *work)
    115{
    116	int rval;
    117	struct lm3630a_chip *pchip;
    118
    119	pchip = container_of(work, struct lm3630a_chip, work.work);
    120
    121	rval = lm3630a_read(pchip, REG_INT_STATUS);
    122	if (rval < 0) {
    123		dev_err(pchip->dev,
    124			"i2c failed to access REG_INT_STATUS Register\n");
    125		return;
    126	}
    127
    128	dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", rval);
    129}
    130
    131static irqreturn_t lm3630a_isr_func(int irq, void *chip)
    132{
    133	int rval;
    134	struct lm3630a_chip *pchip = chip;
    135	unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC);
    136
    137	queue_delayed_work(pchip->irqthread, &pchip->work, delay);
    138
    139	rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
    140	if (rval < 0) {
    141		dev_err(pchip->dev, "i2c failed to access register\n");
    142		return IRQ_NONE;
    143	}
    144	return IRQ_HANDLED;
    145}
    146
    147static int lm3630a_intr_config(struct lm3630a_chip *pchip)
    148{
    149	int rval;
    150
    151	rval = lm3630a_write(pchip, REG_INT_EN, 0x87);
    152	if (rval < 0)
    153		return rval;
    154
    155	INIT_DELAYED_WORK(&pchip->work, lm3630a_delayed_func);
    156	pchip->irqthread = create_singlethread_workqueue("lm3630a-irqthd");
    157	if (!pchip->irqthread) {
    158		dev_err(pchip->dev, "create irq thread fail\n");
    159		return -ENOMEM;
    160	}
    161	if (request_threaded_irq
    162	    (pchip->irq, NULL, lm3630a_isr_func,
    163	     IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630a_irq", pchip)) {
    164		dev_err(pchip->dev, "request threaded irq fail\n");
    165		destroy_workqueue(pchip->irqthread);
    166		return -ENOMEM;
    167	}
    168	return rval;
    169}
    170
    171static int lm3630a_pwm_ctrl(struct lm3630a_chip *pchip, int br, int br_max)
    172{
    173	int err;
    174
    175	pchip->pwmd_state.period = pchip->pdata->pwm_period;
    176
    177	err = pwm_set_relative_duty_cycle(&pchip->pwmd_state, br, br_max);
    178	if (err)
    179		return err;
    180
    181	pchip->pwmd_state.enabled = pchip->pwmd_state.duty_cycle ? true : false;
    182
    183	return pwm_apply_state(pchip->pwmd, &pchip->pwmd_state);
    184}
    185
    186/* update and get brightness */
    187static int lm3630a_bank_a_update_status(struct backlight_device *bl)
    188{
    189	int ret;
    190	struct lm3630a_chip *pchip = bl_get_data(bl);
    191	enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
    192
    193	/* pwm control */
    194	if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0)
    195		return lm3630a_pwm_ctrl(pchip, bl->props.brightness,
    196					bl->props.max_brightness);
    197
    198	/* disable sleep */
    199	ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
    200	if (ret < 0)
    201		goto out_i2c_err;
    202	usleep_range(1000, 2000);
    203	/* minimum brightness is 0x04 */
    204	ret = lm3630a_write(pchip, REG_BRT_A, bl->props.brightness);
    205	if (bl->props.brightness < 0x4)
    206		ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDA_ENABLE, 0);
    207	else
    208		ret |= lm3630a_update(pchip, REG_CTRL,
    209				      LM3630A_LEDA_ENABLE, LM3630A_LEDA_ENABLE);
    210	if (ret < 0)
    211		goto out_i2c_err;
    212	return 0;
    213
    214out_i2c_err:
    215	dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret));
    216	return ret;
    217}
    218
    219static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
    220{
    221	int brightness, rval;
    222	struct lm3630a_chip *pchip = bl_get_data(bl);
    223	enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
    224
    225	if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) {
    226		rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
    227		if (rval < 0)
    228			goto out_i2c_err;
    229		brightness = (rval & 0x01) << 8;
    230		rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
    231		if (rval < 0)
    232			goto out_i2c_err;
    233		brightness |= rval;
    234		goto out;
    235	}
    236
    237	/* disable sleep */
    238	rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
    239	if (rval < 0)
    240		goto out_i2c_err;
    241	usleep_range(1000, 2000);
    242	rval = lm3630a_read(pchip, REG_BRT_A);
    243	if (rval < 0)
    244		goto out_i2c_err;
    245	brightness = rval;
    246
    247out:
    248	bl->props.brightness = brightness;
    249	return bl->props.brightness;
    250out_i2c_err:
    251	dev_err(pchip->dev, "i2c failed to access register\n");
    252	return 0;
    253}
    254
    255static const struct backlight_ops lm3630a_bank_a_ops = {
    256	.options = BL_CORE_SUSPENDRESUME,
    257	.update_status = lm3630a_bank_a_update_status,
    258	.get_brightness = lm3630a_bank_a_get_brightness,
    259};
    260
    261/* update and get brightness */
    262static int lm3630a_bank_b_update_status(struct backlight_device *bl)
    263{
    264	int ret;
    265	struct lm3630a_chip *pchip = bl_get_data(bl);
    266	enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
    267
    268	/* pwm control */
    269	if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0)
    270		return lm3630a_pwm_ctrl(pchip, bl->props.brightness,
    271					bl->props.max_brightness);
    272
    273	/* disable sleep */
    274	ret = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
    275	if (ret < 0)
    276		goto out_i2c_err;
    277	usleep_range(1000, 2000);
    278	/* minimum brightness is 0x04 */
    279	ret = lm3630a_write(pchip, REG_BRT_B, bl->props.brightness);
    280	if (bl->props.brightness < 0x4)
    281		ret |= lm3630a_update(pchip, REG_CTRL, LM3630A_LEDB_ENABLE, 0);
    282	else
    283		ret |= lm3630a_update(pchip, REG_CTRL,
    284				      LM3630A_LEDB_ENABLE, LM3630A_LEDB_ENABLE);
    285	if (ret < 0)
    286		goto out_i2c_err;
    287	return 0;
    288
    289out_i2c_err:
    290	dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret));
    291	return ret;
    292}
    293
    294static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
    295{
    296	int brightness, rval;
    297	struct lm3630a_chip *pchip = bl_get_data(bl);
    298	enum lm3630a_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl;
    299
    300	if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) {
    301		rval = lm3630a_read(pchip, REG_PWM_OUTHIGH);
    302		if (rval < 0)
    303			goto out_i2c_err;
    304		brightness = (rval & 0x01) << 8;
    305		rval = lm3630a_read(pchip, REG_PWM_OUTLOW);
    306		if (rval < 0)
    307			goto out_i2c_err;
    308		brightness |= rval;
    309		goto out;
    310	}
    311
    312	/* disable sleep */
    313	rval = lm3630a_update(pchip, REG_CTRL, 0x80, 0x00);
    314	if (rval < 0)
    315		goto out_i2c_err;
    316	usleep_range(1000, 2000);
    317	rval = lm3630a_read(pchip, REG_BRT_B);
    318	if (rval < 0)
    319		goto out_i2c_err;
    320	brightness = rval;
    321
    322out:
    323	bl->props.brightness = brightness;
    324	return bl->props.brightness;
    325out_i2c_err:
    326	dev_err(pchip->dev, "i2c failed to access register\n");
    327	return 0;
    328}
    329
    330static const struct backlight_ops lm3630a_bank_b_ops = {
    331	.options = BL_CORE_SUSPENDRESUME,
    332	.update_status = lm3630a_bank_b_update_status,
    333	.get_brightness = lm3630a_bank_b_get_brightness,
    334};
    335
    336static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
    337{
    338	struct lm3630a_platform_data *pdata = pchip->pdata;
    339	struct backlight_properties props;
    340	const char *label;
    341
    342	props.type = BACKLIGHT_RAW;
    343	if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
    344		props.brightness = pdata->leda_init_brt;
    345		props.max_brightness = pdata->leda_max_brt;
    346		label = pdata->leda_label ? pdata->leda_label : "lm3630a_leda";
    347		pchip->bleda =
    348		    devm_backlight_device_register(pchip->dev, label,
    349						   pchip->dev, pchip,
    350						   &lm3630a_bank_a_ops, &props);
    351		if (IS_ERR(pchip->bleda))
    352			return PTR_ERR(pchip->bleda);
    353	}
    354
    355	if ((pdata->ledb_ctrl != LM3630A_LEDB_DISABLE) &&
    356	    (pdata->ledb_ctrl != LM3630A_LEDB_ON_A)) {
    357		props.brightness = pdata->ledb_init_brt;
    358		props.max_brightness = pdata->ledb_max_brt;
    359		label = pdata->ledb_label ? pdata->ledb_label : "lm3630a_ledb";
    360		pchip->bledb =
    361		    devm_backlight_device_register(pchip->dev, label,
    362						   pchip->dev, pchip,
    363						   &lm3630a_bank_b_ops, &props);
    364		if (IS_ERR(pchip->bledb))
    365			return PTR_ERR(pchip->bledb);
    366	}
    367	return 0;
    368}
    369
    370static const struct regmap_config lm3630a_regmap = {
    371	.reg_bits = 8,
    372	.val_bits = 8,
    373	.max_register = REG_MAX,
    374};
    375
    376static int lm3630a_parse_led_sources(struct fwnode_handle *node,
    377				     int default_led_sources)
    378{
    379	u32 sources[LM3630A_NUM_SINKS];
    380	int ret, num_sources, i;
    381
    382	num_sources = fwnode_property_count_u32(node, "led-sources");
    383	if (num_sources < 0)
    384		return default_led_sources;
    385	else if (num_sources > ARRAY_SIZE(sources))
    386		return -EINVAL;
    387
    388	ret = fwnode_property_read_u32_array(node, "led-sources", sources,
    389					     num_sources);
    390	if (ret)
    391		return ret;
    392
    393	for (i = 0; i < num_sources; i++) {
    394		if (sources[i] != LM3630A_SINK_0 && sources[i] != LM3630A_SINK_1)
    395			return -EINVAL;
    396
    397		ret |= BIT(sources[i]);
    398	}
    399
    400	return ret;
    401}
    402
    403static int lm3630a_parse_bank(struct lm3630a_platform_data *pdata,
    404			      struct fwnode_handle *node, int *seen_led_sources)
    405{
    406	int led_sources, ret;
    407	const char *label;
    408	u32 bank, val;
    409	bool linear;
    410
    411	ret = fwnode_property_read_u32(node, "reg", &bank);
    412	if (ret)
    413		return ret;
    414
    415	if (bank != LM3630A_BANK_0 && bank != LM3630A_BANK_1)
    416		return -EINVAL;
    417
    418	led_sources = lm3630a_parse_led_sources(node, BIT(bank));
    419	if (led_sources < 0)
    420		return led_sources;
    421
    422	if (*seen_led_sources & led_sources)
    423		return -EINVAL;
    424
    425	*seen_led_sources |= led_sources;
    426
    427	linear = fwnode_property_read_bool(node,
    428					   "ti,linear-mapping-mode");
    429	if (bank) {
    430		if (led_sources & BIT(LM3630A_SINK_0) ||
    431		    !(led_sources & BIT(LM3630A_SINK_1)))
    432			return -EINVAL;
    433
    434		pdata->ledb_ctrl = linear ?
    435			LM3630A_LEDB_ENABLE_LINEAR :
    436			LM3630A_LEDB_ENABLE;
    437	} else {
    438		if (!(led_sources & BIT(LM3630A_SINK_0)))
    439			return -EINVAL;
    440
    441		pdata->leda_ctrl = linear ?
    442			LM3630A_LEDA_ENABLE_LINEAR :
    443			LM3630A_LEDA_ENABLE;
    444
    445		if (led_sources & BIT(LM3630A_SINK_1))
    446			pdata->ledb_ctrl = LM3630A_LEDB_ON_A;
    447	}
    448
    449	ret = fwnode_property_read_string(node, "label", &label);
    450	if (!ret) {
    451		if (bank)
    452			pdata->ledb_label = label;
    453		else
    454			pdata->leda_label = label;
    455	}
    456
    457	ret = fwnode_property_read_u32(node, "default-brightness",
    458				       &val);
    459	if (!ret) {
    460		if (bank)
    461			pdata->ledb_init_brt = val;
    462		else
    463			pdata->leda_init_brt = val;
    464	}
    465
    466	ret = fwnode_property_read_u32(node, "max-brightness", &val);
    467	if (!ret) {
    468		if (bank)
    469			pdata->ledb_max_brt = val;
    470		else
    471			pdata->leda_max_brt = val;
    472	}
    473
    474	return 0;
    475}
    476
    477static int lm3630a_parse_node(struct lm3630a_chip *pchip,
    478			      struct lm3630a_platform_data *pdata)
    479{
    480	int ret = -ENODEV, seen_led_sources = 0;
    481	struct fwnode_handle *node;
    482
    483	device_for_each_child_node(pchip->dev, node) {
    484		ret = lm3630a_parse_bank(pdata, node, &seen_led_sources);
    485		if (ret) {
    486			fwnode_handle_put(node);
    487			return ret;
    488		}
    489	}
    490
    491	return ret;
    492}
    493
    494static int lm3630a_probe(struct i2c_client *client,
    495			 const struct i2c_device_id *id)
    496{
    497	struct lm3630a_platform_data *pdata = dev_get_platdata(&client->dev);
    498	struct lm3630a_chip *pchip;
    499	int rval;
    500
    501	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
    502		dev_err(&client->dev, "fail : i2c functionality check\n");
    503		return -EOPNOTSUPP;
    504	}
    505
    506	pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630a_chip),
    507			     GFP_KERNEL);
    508	if (!pchip)
    509		return -ENOMEM;
    510	pchip->dev = &client->dev;
    511
    512	pchip->regmap = devm_regmap_init_i2c(client, &lm3630a_regmap);
    513	if (IS_ERR(pchip->regmap)) {
    514		rval = PTR_ERR(pchip->regmap);
    515		dev_err(&client->dev, "fail : allocate reg. map: %d\n", rval);
    516		return rval;
    517	}
    518
    519	i2c_set_clientdata(client, pchip);
    520	if (pdata == NULL) {
    521		pdata = devm_kzalloc(pchip->dev,
    522				     sizeof(struct lm3630a_platform_data),
    523				     GFP_KERNEL);
    524		if (pdata == NULL)
    525			return -ENOMEM;
    526
    527		/* default values */
    528		pdata->leda_max_brt = LM3630A_MAX_BRIGHTNESS;
    529		pdata->ledb_max_brt = LM3630A_MAX_BRIGHTNESS;
    530		pdata->leda_init_brt = LM3630A_MAX_BRIGHTNESS;
    531		pdata->ledb_init_brt = LM3630A_MAX_BRIGHTNESS;
    532
    533		rval = lm3630a_parse_node(pchip, pdata);
    534		if (rval) {
    535			dev_err(&client->dev, "fail : parse node\n");
    536			return rval;
    537		}
    538	}
    539	pchip->pdata = pdata;
    540
    541	pchip->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
    542						GPIOD_OUT_HIGH);
    543	if (IS_ERR(pchip->enable_gpio)) {
    544		rval = PTR_ERR(pchip->enable_gpio);
    545		return rval;
    546	}
    547
    548	/* chip initialize */
    549	rval = lm3630a_chip_init(pchip);
    550	if (rval < 0) {
    551		dev_err(&client->dev, "fail : init chip\n");
    552		return rval;
    553	}
    554	/* backlight register */
    555	rval = lm3630a_backlight_register(pchip);
    556	if (rval < 0) {
    557		dev_err(&client->dev, "fail : backlight register.\n");
    558		return rval;
    559	}
    560	/* pwm */
    561	if (pdata->pwm_ctrl != LM3630A_PWM_DISABLE) {
    562		pchip->pwmd = devm_pwm_get(pchip->dev, "lm3630a-pwm");
    563		if (IS_ERR(pchip->pwmd)) {
    564			dev_err(&client->dev, "fail : get pwm device\n");
    565			return PTR_ERR(pchip->pwmd);
    566		}
    567
    568		pwm_init_state(pchip->pwmd, &pchip->pwmd_state);
    569	}
    570
    571	/* interrupt enable  : irq 0 is not allowed */
    572	pchip->irq = client->irq;
    573	if (pchip->irq) {
    574		rval = lm3630a_intr_config(pchip);
    575		if (rval < 0)
    576			return rval;
    577	}
    578	dev_info(&client->dev, "LM3630A backlight register OK.\n");
    579	return 0;
    580}
    581
    582static int lm3630a_remove(struct i2c_client *client)
    583{
    584	int rval;
    585	struct lm3630a_chip *pchip = i2c_get_clientdata(client);
    586
    587	rval = lm3630a_write(pchip, REG_BRT_A, 0);
    588	if (rval < 0)
    589		dev_err(pchip->dev, "i2c failed to access register\n");
    590
    591	rval = lm3630a_write(pchip, REG_BRT_B, 0);
    592	if (rval < 0)
    593		dev_err(pchip->dev, "i2c failed to access register\n");
    594
    595	if (pchip->irq) {
    596		free_irq(pchip->irq, pchip);
    597		destroy_workqueue(pchip->irqthread);
    598	}
    599	return 0;
    600}
    601
    602static const struct i2c_device_id lm3630a_id[] = {
    603	{LM3630A_NAME, 0},
    604	{}
    605};
    606
    607MODULE_DEVICE_TABLE(i2c, lm3630a_id);
    608
    609static const struct of_device_id lm3630a_match_table[] = {
    610	{ .compatible = "ti,lm3630a", },
    611	{ },
    612};
    613
    614MODULE_DEVICE_TABLE(of, lm3630a_match_table);
    615
    616static struct i2c_driver lm3630a_i2c_driver = {
    617	.driver = {
    618		   .name = LM3630A_NAME,
    619		   .of_match_table = lm3630a_match_table,
    620		   },
    621	.probe = lm3630a_probe,
    622	.remove = lm3630a_remove,
    623	.id_table = lm3630a_id,
    624};
    625
    626module_i2c_driver(lm3630a_i2c_driver);
    627
    628MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630A");
    629MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
    630MODULE_AUTHOR("LDD MLP <ldd-mlp@list.ti.com>");
    631MODULE_LICENSE("GPL v2");