1*243a738cSVladislav Kulikov // SPDX-License-Identifier: GPL-2.0-only 2*243a738cSVladislav Kulikov /* 3*243a738cSVladislav Kulikov * MMC5983 - MEMSIC 3-axis Magnetic Sensor 4*243a738cSVladislav Kulikov * 5*243a738cSVladislav Kulikov * Copyright (c) 2026, Vlad Kulikov <vlad.kulikov.c@gmail.com> 6*243a738cSVladislav Kulikov * 7*243a738cSVladislav Kulikov * IIO driver for MMC5983 8*243a738cSVladislav Kulikov */ 9*243a738cSVladislav Kulikov 10*243a738cSVladislav Kulikov #include <linux/array_size.h> 11*243a738cSVladislav Kulikov #include <linux/bits.h> 12*243a738cSVladislav Kulikov #include <linux/cleanup.h> 13*243a738cSVladislav Kulikov #include <linux/delay.h> 14*243a738cSVladislav Kulikov #include <linux/dev_printk.h> 15*243a738cSVladislav Kulikov #include <linux/err.h> 16*243a738cSVladislav Kulikov #include <linux/i2c.h> 17*243a738cSVladislav Kulikov #include <linux/iio/iio.h> 18*243a738cSVladislav Kulikov #include <linux/mod_devicetable.h> 19*243a738cSVladislav Kulikov #include <linux/module.h> 20*243a738cSVladislav Kulikov #include <linux/mutex.h> 21*243a738cSVladislav Kulikov #include <linux/regmap.h> 22*243a738cSVladislav Kulikov #include <linux/time.h> 23*243a738cSVladislav Kulikov #include <linux/types.h> 24*243a738cSVladislav Kulikov 25*243a738cSVladislav Kulikov #define MMC5983_REG_XOUT0 0x00 26*243a738cSVladislav Kulikov #define MMC5983_REG_XOUT1 0x01 27*243a738cSVladislav Kulikov #define MMC5983_REG_YOUT0 0x02 28*243a738cSVladislav Kulikov #define MMC5983_REG_YOUT1 0x03 29*243a738cSVladislav Kulikov #define MMC5983_REG_ZOUT0 0x04 30*243a738cSVladislav Kulikov #define MMC5983_REG_ZOUT1 0x05 31*243a738cSVladislav Kulikov #define MMC5983_REG_XYZOUT2 0x06 32*243a738cSVladislav Kulikov 33*243a738cSVladislav Kulikov #define MMC5983_REG_STATUS 0x08 34*243a738cSVladislav Kulikov 35*243a738cSVladislav Kulikov #define MMC5983_REG_CTRL0 0x09 36*243a738cSVladislav Kulikov #define MMC5983_REG_CTRL1 0x0A 37*243a738cSVladislav Kulikov #define MMC5983_REG_CTRL2 0x0B 38*243a738cSVladislav Kulikov #define MMC5983_REG_CTRL3 0x0C 39*243a738cSVladislav Kulikov 40*243a738cSVladislav Kulikov #define MMC5983_REG_ID 0x2F 41*243a738cSVladislav Kulikov 42*243a738cSVladislav Kulikov #define MMC5983_PRODUCT_ID 0x30 43*243a738cSVladislav Kulikov 44*243a738cSVladislav Kulikov #define MMC5983_STATUS_MEAS_M_DONE_BIT BIT(0) 45*243a738cSVladislav Kulikov #define MMC5983_STATUS_OTP_RD_DONE_BIT BIT(4) 46*243a738cSVladislav Kulikov 47*243a738cSVladislav Kulikov #define MMC5983_CTRL0_TM_M_BIT BIT(0) 48*243a738cSVladislav Kulikov #define MMC5983_CTRL0_SET_BIT BIT(3) 49*243a738cSVladislav Kulikov #define MMC5983_CTRL0_RESET_BIT BIT(4) 50*243a738cSVladislav Kulikov #define MMC5983_CTRL0_OTP_RD_BIT BIT(6) 51*243a738cSVladislav Kulikov 52*243a738cSVladislav Kulikov #define MMC5983_CTRL1_SW_RST_BIT BIT(7) 53*243a738cSVladislav Kulikov 54*243a738cSVladislav Kulikov enum mmc5983_axis { 55*243a738cSVladislav Kulikov MMC5983_AXIS_X, 56*243a738cSVladislav Kulikov MMC5983_AXIS_Y, 57*243a738cSVladislav Kulikov MMC5983_AXIS_Z, 58*243a738cSVladislav Kulikov }; 59*243a738cSVladislav Kulikov 60*243a738cSVladislav Kulikov struct mmc5983_data { 61*243a738cSVladislav Kulikov struct regmap *regmap; 62*243a738cSVladislav Kulikov /* Protects chip access during SET/RESET measurement sequence */ 63*243a738cSVladislav Kulikov struct mutex mutex; 64*243a738cSVladislav Kulikov }; 65*243a738cSVladislav Kulikov 66*243a738cSVladislav Kulikov #define MMC5983_CHANNEL(_axis) { \ 67*243a738cSVladislav Kulikov .type = IIO_MAGN, \ 68*243a738cSVladislav Kulikov .modified = 1, \ 69*243a738cSVladislav Kulikov .channel2 = IIO_MOD_##_axis, \ 70*243a738cSVladislav Kulikov .address = MMC5983_AXIS_##_axis, \ 71*243a738cSVladislav Kulikov .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 72*243a738cSVladislav Kulikov .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 73*243a738cSVladislav Kulikov } 74*243a738cSVladislav Kulikov 75*243a738cSVladislav Kulikov static const struct iio_chan_spec mmc5983_channels[] = { 76*243a738cSVladislav Kulikov MMC5983_CHANNEL(X), 77*243a738cSVladislav Kulikov MMC5983_CHANNEL(Y), 78*243a738cSVladislav Kulikov MMC5983_CHANNEL(Z), 79*243a738cSVladislav Kulikov }; 80*243a738cSVladislav Kulikov 81*243a738cSVladislav Kulikov static int mmc5983_pulse_coil(struct mmc5983_data *data, unsigned int coil_bit) 82*243a738cSVladislav Kulikov { 83*243a738cSVladislav Kulikov int ret; 84*243a738cSVladislav Kulikov 85*243a738cSVladislav Kulikov ret = regmap_write(data->regmap, MMC5983_REG_CTRL0, coil_bit); 86*243a738cSVladislav Kulikov if (ret) 87*243a738cSVladislav Kulikov return ret; 88*243a738cSVladislav Kulikov 89*243a738cSVladislav Kulikov /* 90*243a738cSVladislav Kulikov * Datasheet page 15: SET/RESET coil pulse is 500 ns. 91*243a738cSVladislav Kulikov * Vendor sample code waits 500 us before the next operation. 92*243a738cSVladislav Kulikov */ 93*243a738cSVladislav Kulikov fsleep(500); 94*243a738cSVladislav Kulikov 95*243a738cSVladislav Kulikov return 0; 96*243a738cSVladislav Kulikov } 97*243a738cSVladislav Kulikov 98*243a738cSVladislav Kulikov static int mmc5983_take_measurement(struct mmc5983_data *data, int m[3]) 99*243a738cSVladislav Kulikov { 100*243a738cSVladislav Kulikov unsigned int status; 101*243a738cSVladislav Kulikov u8 buf[7]; 102*243a738cSVladislav Kulikov int ret; 103*243a738cSVladislav Kulikov 104*243a738cSVladislav Kulikov ret = regmap_write(data->regmap, MMC5983_REG_CTRL0, 105*243a738cSVladislav Kulikov MMC5983_CTRL0_TM_M_BIT); 106*243a738cSVladislav Kulikov if (ret) 107*243a738cSVladislav Kulikov return ret; 108*243a738cSVladislav Kulikov 109*243a738cSVladislav Kulikov /* 110*243a738cSVladislav Kulikov * Datasheet page 15: measurement time is 8 ms at BW=00 (default, 111*243a738cSVladislav Kulikov * slowest setting). Use a 50 ms timeout for margin. 112*243a738cSVladislav Kulikov */ 113*243a738cSVladislav Kulikov ret = regmap_read_poll_timeout(data->regmap, MMC5983_REG_STATUS, 114*243a738cSVladislav Kulikov status, 115*243a738cSVladislav Kulikov status & MMC5983_STATUS_MEAS_M_DONE_BIT, 116*243a738cSVladislav Kulikov 10 * USEC_PER_MSEC, 117*243a738cSVladislav Kulikov 50 * USEC_PER_MSEC); 118*243a738cSVladislav Kulikov if (ret) 119*243a738cSVladislav Kulikov return ret; 120*243a738cSVladislav Kulikov 121*243a738cSVladislav Kulikov ret = regmap_bulk_read(data->regmap, MMC5983_REG_XOUT0, buf, 122*243a738cSVladislav Kulikov sizeof(buf)); 123*243a738cSVladislav Kulikov if (ret) 124*243a738cSVladislav Kulikov return ret; 125*243a738cSVladislav Kulikov 126*243a738cSVladislav Kulikov m[0] = (buf[0] << 10) | (buf[1] << 2) | ((buf[6] >> 6) & 0x3); 127*243a738cSVladislav Kulikov m[1] = (buf[2] << 10) | (buf[3] << 2) | ((buf[6] >> 4) & 0x3); 128*243a738cSVladislav Kulikov m[2] = (buf[4] << 10) | (buf[5] << 2) | ((buf[6] >> 2) & 0x3); 129*243a738cSVladislav Kulikov 130*243a738cSVladislav Kulikov return 0; 131*243a738cSVladislav Kulikov } 132*243a738cSVladislav Kulikov 133*243a738cSVladislav Kulikov static int mmc5983_read_raw(struct iio_dev *indio_dev, 134*243a738cSVladislav Kulikov const struct iio_chan_spec *chan, int *val, 135*243a738cSVladislav Kulikov int *val2, long mask) 136*243a738cSVladislav Kulikov { 137*243a738cSVladislav Kulikov struct mmc5983_data *data = iio_priv(indio_dev); 138*243a738cSVladislav Kulikov int m1[3], m2[3]; 139*243a738cSVladislav Kulikov int ret; 140*243a738cSVladislav Kulikov 141*243a738cSVladislav Kulikov switch (mask) { 142*243a738cSVladislav Kulikov case IIO_CHAN_INFO_RAW: { 143*243a738cSVladislav Kulikov guard(mutex)(&data->mutex); 144*243a738cSVladislav Kulikov 145*243a738cSVladislav Kulikov /* SET: magnetize sensor elements in forward direction */ 146*243a738cSVladislav Kulikov ret = mmc5983_pulse_coil(data, MMC5983_CTRL0_SET_BIT); 147*243a738cSVladislav Kulikov if (ret) 148*243a738cSVladislav Kulikov return ret; 149*243a738cSVladislav Kulikov 150*243a738cSVladislav Kulikov ret = mmc5983_take_measurement(data, m1); 151*243a738cSVladislav Kulikov if (ret) 152*243a738cSVladislav Kulikov return ret; 153*243a738cSVladislav Kulikov 154*243a738cSVladislav Kulikov /* RESET: magnetize sensor elements in reverse direction */ 155*243a738cSVladislav Kulikov ret = mmc5983_pulse_coil(data, MMC5983_CTRL0_RESET_BIT); 156*243a738cSVladislav Kulikov if (ret) 157*243a738cSVladislav Kulikov return ret; 158*243a738cSVladislav Kulikov 159*243a738cSVladislav Kulikov ret = mmc5983_take_measurement(data, m2); 160*243a738cSVladislav Kulikov if (ret) 161*243a738cSVladislav Kulikov return ret; 162*243a738cSVladislav Kulikov 163*243a738cSVladislav Kulikov *val = (m1[chan->address] - m2[chan->address]) / 2; 164*243a738cSVladislav Kulikov return IIO_VAL_INT; 165*243a738cSVladislav Kulikov } 166*243a738cSVladislav Kulikov case IIO_CHAN_INFO_SCALE: 167*243a738cSVladislav Kulikov *val = 0; 168*243a738cSVladislav Kulikov *val2 = 61035; 169*243a738cSVladislav Kulikov return IIO_VAL_INT_PLUS_NANO; 170*243a738cSVladislav Kulikov default: 171*243a738cSVladislav Kulikov return -EINVAL; 172*243a738cSVladislav Kulikov } 173*243a738cSVladislav Kulikov } 174*243a738cSVladislav Kulikov 175*243a738cSVladislav Kulikov static const struct iio_info mmc5983_info = { 176*243a738cSVladislav Kulikov .read_raw = mmc5983_read_raw, 177*243a738cSVladislav Kulikov }; 178*243a738cSVladislav Kulikov 179*243a738cSVladislav Kulikov static bool mmc5983_is_writeable_reg(struct device *dev, unsigned int reg) 180*243a738cSVladislav Kulikov { 181*243a738cSVladislav Kulikov switch (reg) { 182*243a738cSVladislav Kulikov case MMC5983_REG_CTRL0: 183*243a738cSVladislav Kulikov case MMC5983_REG_CTRL1: 184*243a738cSVladislav Kulikov case MMC5983_REG_CTRL2: 185*243a738cSVladislav Kulikov case MMC5983_REG_CTRL3: 186*243a738cSVladislav Kulikov return true; 187*243a738cSVladislav Kulikov default: 188*243a738cSVladislav Kulikov return false; 189*243a738cSVladislav Kulikov } 190*243a738cSVladislav Kulikov } 191*243a738cSVladislav Kulikov 192*243a738cSVladislav Kulikov static bool mmc5983_is_readable_reg(struct device *dev, unsigned int reg) 193*243a738cSVladislav Kulikov { 194*243a738cSVladislav Kulikov switch (reg) { 195*243a738cSVladislav Kulikov case MMC5983_REG_XOUT0: 196*243a738cSVladislav Kulikov case MMC5983_REG_XOUT1: 197*243a738cSVladislav Kulikov case MMC5983_REG_YOUT0: 198*243a738cSVladislav Kulikov case MMC5983_REG_YOUT1: 199*243a738cSVladislav Kulikov case MMC5983_REG_ZOUT0: 200*243a738cSVladislav Kulikov case MMC5983_REG_ZOUT1: 201*243a738cSVladislav Kulikov case MMC5983_REG_XYZOUT2: 202*243a738cSVladislav Kulikov case MMC5983_REG_STATUS: 203*243a738cSVladislav Kulikov case MMC5983_REG_CTRL0: 204*243a738cSVladislav Kulikov case MMC5983_REG_CTRL1: 205*243a738cSVladislav Kulikov case MMC5983_REG_CTRL2: 206*243a738cSVladislav Kulikov case MMC5983_REG_CTRL3: 207*243a738cSVladislav Kulikov case MMC5983_REG_ID: 208*243a738cSVladislav Kulikov return true; 209*243a738cSVladislav Kulikov default: 210*243a738cSVladislav Kulikov return false; 211*243a738cSVladislav Kulikov } 212*243a738cSVladislav Kulikov } 213*243a738cSVladislav Kulikov 214*243a738cSVladislav Kulikov static bool mmc5983_is_volatile_reg(struct device *dev, unsigned int reg) 215*243a738cSVladislav Kulikov { 216*243a738cSVladislav Kulikov switch (reg) { 217*243a738cSVladislav Kulikov case MMC5983_REG_XOUT0: 218*243a738cSVladislav Kulikov case MMC5983_REG_XOUT1: 219*243a738cSVladislav Kulikov case MMC5983_REG_YOUT0: 220*243a738cSVladislav Kulikov case MMC5983_REG_YOUT1: 221*243a738cSVladislav Kulikov case MMC5983_REG_ZOUT0: 222*243a738cSVladislav Kulikov case MMC5983_REG_ZOUT1: 223*243a738cSVladislav Kulikov case MMC5983_REG_XYZOUT2: 224*243a738cSVladislav Kulikov case MMC5983_REG_STATUS: 225*243a738cSVladislav Kulikov case MMC5983_REG_CTRL0: 226*243a738cSVladislav Kulikov case MMC5983_REG_CTRL1: 227*243a738cSVladislav Kulikov return true; 228*243a738cSVladislav Kulikov default: 229*243a738cSVladislav Kulikov return false; 230*243a738cSVladislav Kulikov } 231*243a738cSVladislav Kulikov } 232*243a738cSVladislav Kulikov 233*243a738cSVladislav Kulikov static const struct regmap_config mmc5983_regmap_config = { 234*243a738cSVladislav Kulikov .name = "mmc5983_regmap", 235*243a738cSVladislav Kulikov .reg_bits = 8, 236*243a738cSVladislav Kulikov .val_bits = 8, 237*243a738cSVladislav Kulikov .max_register = MMC5983_REG_ID, 238*243a738cSVladislav Kulikov .writeable_reg = mmc5983_is_writeable_reg, 239*243a738cSVladislav Kulikov .readable_reg = mmc5983_is_readable_reg, 240*243a738cSVladislav Kulikov .volatile_reg = mmc5983_is_volatile_reg, 241*243a738cSVladislav Kulikov }; 242*243a738cSVladislav Kulikov 243*243a738cSVladislav Kulikov static int mmc5983_init(struct mmc5983_data *data) 244*243a738cSVladislav Kulikov { 245*243a738cSVladislav Kulikov struct regmap *regmap = data->regmap; 246*243a738cSVladislav Kulikov struct device *dev = regmap_get_device(regmap); 247*243a738cSVladislav Kulikov unsigned int reg_id, status; 248*243a738cSVladislav Kulikov int ret; 249*243a738cSVladislav Kulikov 250*243a738cSVladislav Kulikov ret = regmap_read(regmap, MMC5983_REG_ID, ®_id); 251*243a738cSVladislav Kulikov if (ret) 252*243a738cSVladislav Kulikov return dev_err_probe(dev, ret, "Error reading product id\n"); 253*243a738cSVladislav Kulikov 254*243a738cSVladislav Kulikov if (reg_id != MMC5983_PRODUCT_ID) 255*243a738cSVladislav Kulikov dev_info(dev, "unexpected product id 0x%02x\n", reg_id); 256*243a738cSVladislav Kulikov 257*243a738cSVladislav Kulikov ret = regmap_write(regmap, MMC5983_REG_CTRL1, MMC5983_CTRL1_SW_RST_BIT); 258*243a738cSVladislav Kulikov if (ret) 259*243a738cSVladislav Kulikov return ret; 260*243a738cSVladislav Kulikov 261*243a738cSVladislav Kulikov /* Datasheet page 15: power-on time after SW_RST is 10 ms */ 262*243a738cSVladislav Kulikov fsleep(10 * USEC_PER_MSEC); 263*243a738cSVladislav Kulikov 264*243a738cSVladislav Kulikov ret = regmap_write(regmap, MMC5983_REG_CTRL0, MMC5983_CTRL0_OTP_RD_BIT); 265*243a738cSVladislav Kulikov if (ret) 266*243a738cSVladislav Kulikov return ret; 267*243a738cSVladislav Kulikov 268*243a738cSVladislav Kulikov /* 269*243a738cSVladislav Kulikov * Datasheet page 15: OTP read completes and self-clears. No separate 270*243a738cSVladislav Kulikov * OTP refresh timeout is specified, so use the 10 ms power-on time as 271*243a738cSVladislav Kulikov * a conservative upper bound. 272*243a738cSVladislav Kulikov */ 273*243a738cSVladislav Kulikov ret = regmap_read_poll_timeout(regmap, MMC5983_REG_STATUS, status, 274*243a738cSVladislav Kulikov status & MMC5983_STATUS_OTP_RD_DONE_BIT, 275*243a738cSVladislav Kulikov USEC_PER_MSEC, 276*243a738cSVladislav Kulikov 10 * USEC_PER_MSEC); 277*243a738cSVladislav Kulikov if (ret) 278*243a738cSVladislav Kulikov return ret; 279*243a738cSVladislav Kulikov 280*243a738cSVladislav Kulikov /* SET: magnetize sensor elements in forward direction */ 281*243a738cSVladislav Kulikov ret = mmc5983_pulse_coil(data, MMC5983_CTRL0_SET_BIT); 282*243a738cSVladislav Kulikov if (ret) 283*243a738cSVladislav Kulikov return ret; 284*243a738cSVladislav Kulikov 285*243a738cSVladislav Kulikov /* RESET: magnetize sensor elements in reverse direction */ 286*243a738cSVladislav Kulikov return mmc5983_pulse_coil(data, MMC5983_CTRL0_RESET_BIT); 287*243a738cSVladislav Kulikov } 288*243a738cSVladislav Kulikov 289*243a738cSVladislav Kulikov static int mmc5983_probe(struct i2c_client *i2c) 290*243a738cSVladislav Kulikov { 291*243a738cSVladislav Kulikov struct device *dev = &i2c->dev; 292*243a738cSVladislav Kulikov struct mmc5983_data *data; 293*243a738cSVladislav Kulikov struct iio_dev *indio_dev; 294*243a738cSVladislav Kulikov int ret; 295*243a738cSVladislav Kulikov 296*243a738cSVladislav Kulikov indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 297*243a738cSVladislav Kulikov if (!indio_dev) 298*243a738cSVladislav Kulikov return -ENOMEM; 299*243a738cSVladislav Kulikov 300*243a738cSVladislav Kulikov data = iio_priv(indio_dev); 301*243a738cSVladislav Kulikov 302*243a738cSVladislav Kulikov ret = devm_mutex_init(dev, &data->mutex); 303*243a738cSVladislav Kulikov if (ret) 304*243a738cSVladislav Kulikov return ret; 305*243a738cSVladislav Kulikov 306*243a738cSVladislav Kulikov data->regmap = devm_regmap_init_i2c(i2c, &mmc5983_regmap_config); 307*243a738cSVladislav Kulikov if (IS_ERR(data->regmap)) 308*243a738cSVladislav Kulikov return dev_err_probe(dev, PTR_ERR(data->regmap), 309*243a738cSVladislav Kulikov "failed to allocate register map\n"); 310*243a738cSVladislav Kulikov 311*243a738cSVladislav Kulikov indio_dev->info = &mmc5983_info; 312*243a738cSVladislav Kulikov indio_dev->modes = INDIO_DIRECT_MODE; 313*243a738cSVladislav Kulikov indio_dev->name = "mmc5983"; 314*243a738cSVladislav Kulikov indio_dev->channels = mmc5983_channels; 315*243a738cSVladislav Kulikov indio_dev->num_channels = ARRAY_SIZE(mmc5983_channels); 316*243a738cSVladislav Kulikov 317*243a738cSVladislav Kulikov ret = mmc5983_init(data); 318*243a738cSVladislav Kulikov if (ret) 319*243a738cSVladislav Kulikov return dev_err_probe(dev, ret, "mmc5983 chip init failed\n"); 320*243a738cSVladislav Kulikov 321*243a738cSVladislav Kulikov return devm_iio_device_register(dev, indio_dev); 322*243a738cSVladislav Kulikov } 323*243a738cSVladislav Kulikov 324*243a738cSVladislav Kulikov static const struct of_device_id mmc5983_of_match[] = { 325*243a738cSVladislav Kulikov { .compatible = "memsic,mmc5983" }, 326*243a738cSVladislav Kulikov { } 327*243a738cSVladislav Kulikov }; 328*243a738cSVladislav Kulikov MODULE_DEVICE_TABLE(of, mmc5983_of_match); 329*243a738cSVladislav Kulikov 330*243a738cSVladislav Kulikov static const struct i2c_device_id mmc5983_id[] = { 331*243a738cSVladislav Kulikov { "mmc5983" }, 332*243a738cSVladislav Kulikov { } 333*243a738cSVladislav Kulikov }; 334*243a738cSVladislav Kulikov MODULE_DEVICE_TABLE(i2c, mmc5983_id); 335*243a738cSVladislav Kulikov 336*243a738cSVladislav Kulikov static struct i2c_driver mmc5983_driver = { 337*243a738cSVladislav Kulikov .driver = { 338*243a738cSVladislav Kulikov .name = "mmc5983", 339*243a738cSVladislav Kulikov .of_match_table = mmc5983_of_match, 340*243a738cSVladislav Kulikov }, 341*243a738cSVladislav Kulikov .probe = mmc5983_probe, 342*243a738cSVladislav Kulikov .id_table = mmc5983_id, 343*243a738cSVladislav Kulikov }; 344*243a738cSVladislav Kulikov module_i2c_driver(mmc5983_driver); 345*243a738cSVladislav Kulikov 346*243a738cSVladislav Kulikov MODULE_AUTHOR("Vladislav Kulikov <vlad.kulikov.c@gmail.com>"); 347*243a738cSVladislav Kulikov MODULE_DESCRIPTION("MEMSIC MMC5983 magnetic sensor driver"); 348*243a738cSVladislav Kulikov MODULE_LICENSE("GPL"); 349