static irqreturn_t fsa9485_irq_thread(int irq, void *data) { struct fsa9485_usbsw *usbsw = data; struct i2c_client *client = usbsw->client; int intr, intr2, detect; /* FSA9480 : Read interrupt -> Read Device * FSA9485 : Read Device -> Read interrupt */ dev_info(&usbsw->client->dev, "%s\n", __func__); /* read and clear interrupt status bits */ intr = i2c_smbus_read_word_data(client, FSA9485_REG_INT1); intr2 = intr >> 8; dev_info(&client->dev, "%s: intr : 0x%02x intr2 : 0x%02x\n", __func__, intr & 0xff, intr2); /* device detection */ mutex_lock(&usbsw->mutex); #ifdef CONFIG_MUIC_FSA9485_SUPPORT_LANHUB if((intr&0xff) == 0x00 && intr2 == 0x04) detect = fsa9485_detect_lanhub(usbsw); else detect = fsa9485_detect_dev(usbsw); #else detect = fsa9485_detect_dev(usbsw); #endif mutex_unlock(&usbsw->mutex); pr_info("%s: detect dev_adc: 0x%02x\n", __func__, detect); if (intr < 0) { msleep(100); dev_err(&client->dev, "%s: err 0x%02x\n", __func__, intr); intr = i2c_smbus_read_word_data(client, FSA9485_REG_INT1); if (intr < 0) dev_err(&client->dev, "%s: err at read 0x%02x\n", __func__, intr); fsa9485_reg_init(usbsw); return IRQ_HANDLED; } else if (intr == 0) { /* interrupt was fired, but no status bits were set, so device was reset. In this case, the registers were reset to defaults so they need to be reinitialised. */ fsa9485_reg_init(usbsw); } return IRQ_HANDLED; }
static ssize_t fsa9485_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct fsa9485_usbsw *usbsw = dev_get_drvdata(dev); struct i2c_client *client = usbsw->client; int ret; if (!strncmp(buf, "1", 1)) { dev_info(&client->dev, "fsa9480 reset after delay 1000 msec.\n"); mdelay(1000); ret = i2c_smbus_write_byte_data(client, FSA9485_REG_MANUAL_OVERRIDES1, 0x01); if (ret < 0) dev_err(&client->dev, "cannot soft reset, err %d\n", ret); dev_info(&client->dev, "fsa9480_reset_control done!\n"); } else { dev_info(&client->dev, "fsa9480_reset_control, but not reset_value!\n"); } fsa9485_reg_init(usbsw); return count; }
static int __devinit fsa9485_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct fsa9485_usbsw *usbsw; int ret = 0; struct input_dev *input; struct device *switch_dev; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; input = input_allocate_device(); usbsw = kzalloc(sizeof(struct fsa9485_usbsw), GFP_KERNEL); if (!usbsw || !input) { dev_err(&client->dev, "failed to allocate driver data\n"); kfree(usbsw); return -ENOMEM; } usbsw->input = input; input->name = client->name; input->phys = "deskdock-key/input0"; input->dev.parent = &client->dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0001; /* Enable auto repeat feature of Linux input subsystem */ __set_bit(EV_REP, input->evbit); input_set_capability(input, EV_KEY, KEY_VOLUMEUP); input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN); input_set_capability(input, EV_KEY, KEY_PLAYPAUSE); input_set_capability(input, EV_KEY, KEY_PREVIOUSSONG); input_set_capability(input, EV_KEY, KEY_NEXTSONG); ret = input_register_device(input); if (ret) { dev_err(&client->dev, "input_register_device %s: err %d\n", __func__, ret); input_free_device(input); kfree(usbsw); return ret; } usbsw->client = client; usbsw->pdata = client->dev.platform_data; if (!usbsw->pdata) goto fail1; i2c_set_clientdata(client, usbsw); mutex_init(&usbsw->mutex); local_usbsw = usbsw; if (usbsw->pdata->cfg_gpio) usbsw->pdata->cfg_gpio(); fsa9485_reg_init(usbsw); uart_connecting = 0; ret = sysfs_create_group(&client->dev.kobj, &fsa9485_group); if (ret) { dev_err(&client->dev, "failed to create fsa9485 attribute group\n"); goto fail2; } /* make sysfs node /sys/class/sec/switch/usb_state */ switch_dev = device_create(sec_class, NULL, 0, NULL, "switch"); if (IS_ERR(switch_dev)) { pr_err("[FSA9485] Failed to create device (switch_dev)!\n"); ret = PTR_ERR(switch_dev); goto fail2; } ret = device_create_file(switch_dev, &dev_attr_usb_state); if (ret < 0) { pr_err("[FSA9485] Failed to create file (usb_state)!\n"); goto err_create_file_state; } ret = device_create_file(switch_dev, &dev_attr_adc); if (ret < 0) { pr_err("[FSA9485] Failed to create file (adc)!\n"); goto err_create_file_adc; } ret = device_create_file(switch_dev, &dev_attr_reset_switch); if (ret < 0) { pr_err("[FSA9485] Failed to create file (reset_switch)!\n"); goto err_create_file_reset_switch; } dev_set_drvdata(switch_dev, usbsw); /* fsa9485 dock init*/ if (usbsw->pdata->dock_init) usbsw->pdata->dock_init(); /* fsa9485 reset */ if (usbsw->pdata->reset_cb) usbsw->pdata->reset_cb(); /* set fsa9485 init flag. */ if (usbsw->pdata->set_init_flag) usbsw->pdata->set_init_flag(); /* initial cable detection */ INIT_DELAYED_WORK(&usbsw->init_work, fsa9485_init_detect); schedule_delayed_work(&usbsw->init_work, msecs_to_jiffies(2700)); return 0; err_create_file_reset_switch: device_remove_file(switch_dev, &dev_attr_reset_switch); err_create_file_adc: device_remove_file(switch_dev, &dev_attr_adc); err_create_file_state: device_remove_file(switch_dev, &dev_attr_usb_state); fail2: if (client->irq) free_irq(client->irq, usbsw); fail1: input_unregister_device(input); mutex_destroy(&usbsw->mutex); i2c_set_clientdata(client, NULL); kfree(usbsw); return ret; }
static irqreturn_t fsa9485_irq_thread(int irq, void *data) { struct fsa9485_usbsw *usbsw = data; struct i2c_client *client = usbsw->client; int intr, intr2, detect; /* FSA9485 : Read interrupt -> Read Device FSA9485 : Read Device -> Read interrupt */ pr_info("fsa9485_irq_thread is called\n"); /* device detection */ mutex_lock(&usbsw->mutex); detect = fsa9485_detect_dev(usbsw); mutex_unlock(&usbsw->mutex); pr_info("%s: detect dev_adc: %x\n", __func__, detect); /* read and clear interrupt status bits */ intr = i2c_smbus_read_word_data(client, FSA9485_REG_INT1); dev_info(&client->dev, "%s: intr : 0x%x intr2 : 0x%x\n", __func__, intr & 0xff, intr >> 8); intr2 = intr >> 8; if (intr < 0) { msleep(100); dev_err(&client->dev, "%s: err %d\n", __func__, intr); intr = i2c_smbus_read_word_data(client, FSA9485_REG_INT1); if (intr < 0) dev_err(&client->dev, "%s: err at read %d\n", __func__, intr); fsa9485_reg_init(usbsw); return IRQ_HANDLED; } else if (intr == 0) { /* interrupt was fired, but no status bits were set, so device was reset. In this case, the registers were reset to defaults so they need to be reinitialised. */ fsa9485_reg_init(usbsw); } /* ADC_value(key pressed) changed at AV_Dock.*/ if (intr2) { if (intr2 & 0x4) { /* for adc change */ fsa9485_handle_dock_vol_key(usbsw, detect); dev_info(&client->dev, "intr2: 0x%x, adc_val: %x\n", intr2, detect); } else if (intr2 & 0x2) { /* for smart dock */ i2c_smbus_read_word_data(client, FSA9485_REG_INT1); } else if (intr2 & 0x1) { /* for av change (desk dock, hdmi) */ dev_info(&client->dev, "%s enter Av charing\n", __func__); fsa9485_detect_dev(usbsw); } else { dev_info(&client->dev, "%s intr2 but, nothing happend, intr2: 0x%x\n", __func__, intr2); } return IRQ_HANDLED; } return IRQ_HANDLED; }
static int __devinit fsa9485_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct fsa9485_usbsw *usbsw; int ret = 0; struct input_dev *input; struct device *switch_dev; struct fsa9485_platform_data *pdata; dev_info(&client->dev, "%s\n", __func__); if (client->dev.of_node) { pdata = devm_kzalloc(&client->dev, sizeof(struct fsa9485_platform_data), GFP_KERNEL); if (!pdata) { dev_err(&client->dev, "Failed to allocate memory\n"); return -ENOMEM; } pdata = &fsa9485_pdata; fsa9485_parse_dt(&client->dev, pdata); client->irq = gpio_to_irq(pdata->gpio_int); } else pdata = client->dev.platform_data; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; input = input_allocate_device(); if (!input) { dev_err(&client->dev, "failed to allocate input device data\n"); return -ENOMEM; } usbsw = kzalloc(sizeof(struct fsa9485_usbsw), GFP_KERNEL); if (!usbsw) { dev_err(&client->dev, "failed to allocate driver data\n"); input_free_device(input); return -ENOMEM; } usbsw->input = input; input->name = client->name; input->phys = "deskdock-key/input0"; input->dev.parent = &client->dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0001; /* Enable auto repeat feature of Linux input subsystem */ __set_bit(EV_REP, input->evbit); input_set_capability(input, EV_KEY, KEY_VOLUMEUP); input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN); input_set_capability(input, EV_KEY, KEY_PLAYPAUSE); input_set_capability(input, EV_KEY, KEY_PREVIOUSSONG); input_set_capability(input, EV_KEY, KEY_NEXTSONG); ret = input_register_device(input); if (ret) { dev_err(&client->dev, "input_register_device %s: err %d\n", __func__, ret); input_free_device(input); kfree(usbsw); return ret; } usbsw->client = client; usbsw->pdata = pdata; if (!usbsw->pdata) goto fail1; #if !defined(CONFIG_MUIC_FSA9485_SUPPORT_CAR_DOCK) usbsw->is_factory_start = false; #endif /* !CONFIG_MUIC_FSA9485_SUPPORT_CAR_DOCK */ i2c_set_clientdata(client, usbsw); mutex_init(&usbsw->mutex); local_usbsw = usbsw; if (usbsw->pdata->cfg_gpio) usbsw->pdata->cfg_gpio(); fsa9485_reg_init(usbsw); uart_connecting = 0; ret = sysfs_create_group(&client->dev.kobj, &fsa9485_group); if (ret) { dev_err(&client->dev, "failed to create fsa9485 attribute group\n"); goto fail2; } /* make sysfs node /sys/class/sec/switch/usb_state */ switch_dev = device_create(sec_class, NULL, 0, NULL, "switch"); if (IS_ERR(switch_dev)) { pr_err("[FSA9485] Failed to create device (switch_dev)!\n"); ret = PTR_ERR(switch_dev); goto fail2; } ret = device_create_file(switch_dev, &dev_attr_usb_state); if (ret < 0) { pr_err("[FSA9485] Failed to create file (usb_state)!\n"); goto fail2; } ret = device_create_file(switch_dev, &dev_attr_adc); if (ret < 0) { pr_err("[FSA9485] Failed to create file (adc)!\n"); goto err_create_file_state; } ret = device_create_file(switch_dev, &dev_attr_reset_switch); if (ret < 0) { pr_err("[FSA9485] Failed to create file (reset_switch)!\n"); goto err_create_file_adc; } #if !defined(CONFIG_MUIC_FSA9485_SUPPORT_CAR_DOCK) ret = device_create_file(switch_dev, &dev_attr_apo_factory); if (ret < 0) { pr_err("[FSA9485] Failed to create file (apo_factory)!\n"); goto err_create_file_reset_switch; } #endif dev_set_drvdata(switch_dev, usbsw); /* fsa9485 dock init*/ if (usbsw->pdata->dock_init) usbsw->pdata->dock_init(); /* fsa9485 reset */ if (usbsw->pdata->reset_cb) usbsw->pdata->reset_cb(); /* set fsa9485 init flag. */ if (usbsw->pdata->set_init_flag) usbsw->pdata->set_init_flag(); local_usbsw->dock_ready = 0; local_usbsw->mhl_ready = 0; #ifdef CONFIG_MUIC_FSA9485_SUPPORT_LANHUB local_usbsw->previous_dock = 0; local_usbsw->lanhub_ta_status = 0; #endif /* initial cable detection */ INIT_DELAYED_WORK(&usbsw->init_work, fsa9485_init_detect); if(poweroff_charging) schedule_delayed_work(&usbsw->init_work, msecs_to_jiffies(1000)); else #ifdef CONFIG_SEC_BERLUTI_PROJECT schedule_delayed_work(&usbsw->init_work, msecs_to_jiffies(100)); #else schedule_delayed_work(&usbsw->init_work, msecs_to_jiffies(3000)); #endif INIT_DELAYED_WORK(&usbsw->audio_work, fsa9485_delayed_audio); schedule_delayed_work(&usbsw->audio_work, msecs_to_jiffies(20000)); #if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2) INIT_DELAYED_WORK(&usbsw->mhl_work, fsa9485_mhl_detect); #endif return 0; err_create_file_reset_switch: device_remove_file(switch_dev, &dev_attr_reset_switch); err_create_file_adc: device_remove_file(switch_dev, &dev_attr_adc); err_create_file_state: device_remove_file(switch_dev, &dev_attr_usb_state); fail2: if (client->irq) free_irq(client->irq, usbsw); fail1: input_unregister_device(input); mutex_destroy(&usbsw->mutex); i2c_set_clientdata(client, NULL); input_free_device(input); kfree(usbsw); return ret; }
static int __devinit fsa9485_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct fsa9485_usbsw *usbsw; int ret = 0; struct device *switch_dev; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; usbsw = kzalloc(sizeof(struct fsa9485_usbsw), GFP_KERNEL); if (!usbsw) { dev_err(&client->dev, "failed to allocate driver data\n"); kfree(usbsw); return -ENOMEM; } usbsw->client = client; usbsw->pdata = client->dev.platform_data; if (!usbsw->pdata) goto fail1; i2c_set_clientdata(client, usbsw); mutex_init(&usbsw->mutex); local_usbsw = usbsw; fsa9485_reg_init(usbsw); ret = sysfs_create_group(&client->dev.kobj, &fsa9485_group); if (ret) { dev_err(&client->dev, "failed to create fsa9485 attribute group\n"); goto fail2; } /* make sysfs node /sys/class/sec/switch/usb_state */ switch_dev = device_create(sec_class, NULL, 0, NULL, "switch"); if (IS_ERR(switch_dev)) { pr_err("[FSA9485] Failed to create device (switch_dev)!\n"); ret = PTR_ERR(switch_dev); goto fail2; } ret = device_create_file(switch_dev, &dev_attr_usb_state); if (ret < 0) { pr_err("[FSA9485] Failed to create file (usb_state)!\n"); goto err_create_file_state; } ret = device_create_file(switch_dev, &dev_attr_adc); if (ret < 0) { pr_err("[FSA9485] Failed to create file (adc)!\n"); goto err_create_file_adc; } ret = device_create_file(switch_dev, &dev_attr_reset_switch); if (ret < 0) { pr_err("[FSA9485] Failed to create file (reset_switch)!\n"); goto err_create_file_reset_switch; } dev_set_drvdata(switch_dev, usbsw); /* fsa9485 dock init*/ if (usbsw->pdata->dock_init) usbsw->pdata->dock_init(); /* initial cable detection */ INIT_DELAYED_WORK(&usbsw->init_work, fsa9485_init_detect); schedule_delayed_work(&usbsw->init_work, msecs_to_jiffies(2700)); return 0; err_create_file_reset_switch: device_remove_file(switch_dev, &dev_attr_reset_switch); err_create_file_adc: device_remove_file(switch_dev, &dev_attr_adc); err_create_file_state: device_remove_file(switch_dev, &dev_attr_usb_state); fail2: if (client->irq) free_irq(client->irq, usbsw); fail1: mutex_destroy(&usbsw->mutex); i2c_set_clientdata(client, NULL); kfree(usbsw); return ret; }