static void twl4030_poweroff(void)
{
    u8 uninitialized_var(val);
    int err;
    int i = 0;

#if defined(CONFIG_AP2MODEM_VIATELECOM)
    extern void ap_poweroff_modem(void);
    ap_poweroff_modem( );
#endif

    /* Clear the STARTON_VBAT and STARTON_SWBUG
      * STARTON_VBAT will cause the auto reboot if battery insert;
      * STARTON_SWBUG will cause the auto reboot if watchdog has been expired
      * Mark the STARTON_PWON, which enable switch on transition if power on has been pressed
      */
    twl4030_enable_write();
    for(i=0; i<3; i++){
        err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
        			  PWR_CFG_P1_TRANSITION + i);
        if (err) {
            printk(KERN_WARNING "I2C error %d while writing TWL4030 PM_MASTER PWR_CFG_P%d_TRANSITION\n", err, i+1);
            goto fail;
        }

        val &= (~(STARTON_SWBUG | STARTON_VBAT));
        val |= STARTON_PWON | STARTON_RTC | STARTON_CHG;

        err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
        			   PWR_CFG_P1_TRANSITION + i);
        if (err) {
            printk(KERN_WARNING "I2C error %d while writing TWL4030 PM_MASTER PWR_CFG_P%d_TRANSITION\n", err, i+1);
            goto fail;
        }
    }
    twl4030_disable_write();

#if 0
    /*fire the watchdog*/
    val = WATCHDOG_FIRE;
    err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val,
        			   WATCHDOG_CFG);
    if (err) {
        printk(KERN_WARNING "I2C error %d while writing TWL4030 PM_MASTER PWR_CFG_P%d_TRANSITION\n", err, i+1);
        goto fail ;
    }  
#endif

    /* Make sure SEQ_OFFSYNC is set so that all the res goes to wait-on */
    err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
    			   CFG_P123_TRANSITION);
    if (err) {
    	pr_warning("I2C error %d while reading TWL4030 PM_MASTER CFG_P123_TRANSITION\n",
    		err);
    	return;
    }

    val |= SEQ_OFFSYNC;
    err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
    			    CFG_P123_TRANSITION);
    if (err) {
    	pr_warning("I2C error %d while writing TWL4030 PM_MASTER CFG_P123_TRANSITION\n",
    		err);
    	return;
    }

    err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
    			  PWR_P1_SW_EVENTS);
    if (err) {
    	pr_warning("I2C error %d while reading TWL4030 PM_MASTER P1_SW_EVENTS\n",
    		err);
    	return;
    }

    val |= PWR_STOPON_POWERON | PWR_DEVOFF;

    err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
    			   PWR_P1_SW_EVENTS);

    if (err) {
    	pr_warning("I2C error %d while writing TWL4030 PM_MASTER P1_SW_EVENTS\n",
    		err);
    	return;
    }

    return;
fail:
    printk(KERN_ERR "Fail to power off the system.\n");
    while(1) ;
}
static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
{
	int rconfig_addr;
	int err;
	u8 type;
	u8 grp;
	u8 remap;

	if (rconfig->resource > TOTAL_RESOURCES) {
		pr_err("TWL4030 Resource %d does not exist\n",
			rconfig->resource);
		return -EINVAL;
	}

	rconfig_addr = res_config_addrs[rconfig->resource];

	/* Set resource group */
	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
			      rconfig_addr + DEV_GRP_OFFSET);
	if (err) {
		pr_err("TWL4030 Resource %d group could not be read\n",
			rconfig->resource);
		return err;
	}

	if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
		grp &= ~DEV_GRP_MASK;
		grp |= rconfig->devgroup << DEV_GRP_SHIFT;
		err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
				       grp, rconfig_addr + DEV_GRP_OFFSET);
		if (err < 0) {
			pr_err("TWL4030 failed to program devgroup\n");
			return err;
		}
	}

	/* Set resource types */
	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
				rconfig_addr + TYPE_OFFSET);
	if (err < 0) {
		pr_err("TWL4030 Resource %d type could not be read\n",
			rconfig->resource);
		return err;
	}

	if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
		type &= ~TYPE_MASK;
		type |= rconfig->type << TYPE_SHIFT;
	}

	if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
		type &= ~TYPE2_MASK;
		type |= rconfig->type2 << TYPE2_SHIFT;
	}

	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
				type, rconfig_addr + TYPE_OFFSET);
	if (err < 0) {
		pr_err("TWL4030 failed to program resource type\n");
		return err;
	}

	/* Set remap states */
	err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
			      rconfig_addr + REMAP_OFFSET);
	if (err < 0) {
		pr_err("TWL4030 Resource %d remap could not be read\n",
			rconfig->resource);
		return err;
	}

	if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
		remap &= ~OFF_STATE_MASK;
		remap |= rconfig->remap_off << OFF_STATE_SHIFT;
	}

	if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
		remap &= ~SLEEP_STATE_MASK;
		remap |= rconfig->remap_off << SLEEP_STATE_SHIFT;
	}

	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
			       remap,
			       rconfig_addr + REMAP_OFFSET);
	if (err < 0) {
		pr_err("TWL4030 failed to program remap\n");
		return err;
	}

	return 0;
}
Beispiel #3
0
static void twl6030charger_ctrl_work_handler(struct work_struct *work)
{
	struct charger_device_info *di = container_of(work,
						      struct charger_device_info,
						      twl6030charger_ctrl_work.work);
	
	int ret;
	int n_usbic_state;
	
	int charger_fault = 0;
	long int events;
	u8 stat_toggle, stat_reset, stat_set = 0;
	u8 charge_state = 0;
	u8 present_charge_state = 0;
	u8 ac_or_vbus, no_ac_and_vbus = 0;
	u8 hw_state = 0, temp = 0;

	dev_dbg(di->dev, "[TA] %s start\n",__func__);

	clear_charge_start_time();
	
	/* read charger controller_stat1 */
	ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &present_charge_state,
		CONTROLLER_STAT1);
	if (ret)
		return 0;

	twl_i2c_read_u8(TWL6030_MODULE_ID0, &hw_state, STS_HW_CONDITIONS);

	charge_state = di->stat1;

	stat_toggle = charge_state ^ present_charge_state;
	stat_set = stat_toggle & present_charge_state;
	stat_reset = stat_toggle & charge_state;

	no_ac_and_vbus = !((present_charge_state) & (VBUS_DET | VAC_DET));
	ac_or_vbus = charge_state & (VBUS_DET | VAC_DET);
	if (no_ac_and_vbus && ac_or_vbus) {
		dev_dbg(di->dev, "[TA] No Charging source\n");
		/* disable charging when no source present */
	}

	charge_state = present_charge_state;
	di->stat1 = present_charge_state;

	if (stat_reset & VBUS_DET) {
		/* On a USB detach, UNMASK VBUS OVP if masked*/
		twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &temp,
			CHARGERUSB_INT_MASK);
		if (temp & MASK_MCHARGERUSB_FAULT)
			twl_i2c_write_u8(TWL6030_MODULE_CHARGER,
				(temp & ~MASK_MCHARGERUSB_FAULT),
					CHARGERUSB_INT_MASK);
		dev_dbg(di->dev, "[TA] Charging source removed\n");
		change_cable_status(POWER_SUPPLY_TYPE_BATTERY, di);
#ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE
		set_tsp_for_ta_detect(0);
#endif

	}

	if (stat_set & VBUS_DET) {
		/* In HOST mode (ID GROUND) when a device is connected, Mask
		 * VBUS OVP interrupt and do no enable usb charging
		 */
		if (hw_state & STS_USB_ID) {
			twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &temp,
				CHARGERUSB_INT_MASK);
			if (!(temp & MASK_MCHARGERUSB_FAULT))
				twl_i2c_write_u8(TWL6030_MODULE_CHARGER,
					(temp | MASK_MCHARGERUSB_FAULT),
						CHARGERUSB_INT_MASK);
		} else {
			n_usbic_state = get_real_usbic_state();
			dev_dbg(di->dev,
				"[TA] cable_detection_isr handler. usbic_state: %d\n",
				n_usbic_state);

			switch (n_usbic_state) {
			case MICROUSBIC_5W_CHARGER:
			case MICROUSBIC_TA_CHARGER:
			case MICROUSBIC_USB_CHARGER:
			case MICROUSBIC_PHONE_USB:
			case MICROUSBIC_USB_CABLE:
			case MICROUSBIC_MHL_CHARGER:
			case MICROUSBIC_JIG_USB_ON:
				if (sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_USB
				    || sec_bci->charger.cable_status == POWER_SUPPLY_TYPE_MAINS ){
					dev_dbg(di->dev,
						"[TA] Already Plugged\n");
					break;
				}

				/*Check VF */
				sec_bci->battery.battery_vf_ok = check_battery_vf();

				/*TA or USB or MHL is inserted */
				if (n_usbic_state == MICROUSBIC_USB_CABLE) {
					//current : 395mA
					dev_dbg(di->dev,"[TA] USB CABLE PLUGGED\n");
					change_cable_status(POWER_SUPPLY_TYPE_USB, di);
#ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE
					set_tsp_for_ta_detect(1);
#endif
				} else if (n_usbic_state == MICROUSBIC_MHL_CHARGER) {
					//current : 395mA
					dev_dbg(di->dev,"[TA] MHL CABLE PLUGGED\n");
					change_cable_status(POWER_SUPPLY_TYPE_USB, di);
#ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE
					set_tsp_for_ta_detect(1);
#endif
				} else if (n_usbic_state == MICROUSBIC_JIG_USB_ON) {
					//current : 1000mA
					dev_dbg(di->dev,"[TA] JIG_USB_ON CABLE PLUGGED\n");
					change_cable_status(POWER_SUPPLY_TYPE_MAINS, di);
#ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE
					set_tsp_for_ta_detect(1);
#endif
				} else {
					//current : 1000mA
					dev_dbg(di->dev,"[TA] CHARGER CABLE PLUGGED\n");
					change_cable_status(POWER_SUPPLY_TYPE_MAINS, di);
#ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE
					set_tsp_for_ta_detect(1);
#endif
				}

				break;

			default:
				;
				
			}
		}
	}
	
	
	if (sec_bci->charger.prev_cable_status == -1
		&& sec_bci->charger.cable_status == -1) {
		dev_dbg(di->dev,"[TA] Fisrt time after bootig.\n");
		change_cable_status(POWER_SUPPLY_TYPE_BATTERY, di);
#ifdef CONFIG_DYNAMIC_TSP_SETTINGS_FOR_CHARGER_STATE
		set_tsp_for_ta_detect(0);
#endif
	}
	

	if (stat_set & CONTROLLER_STAT1_FAULT_WDG) {
//		charger_fault = 1;
		dev_dbg(di->dev, "Fault watchdog fired\n");
	}
	if (stat_reset & CONTROLLER_STAT1_FAULT_WDG)
		dev_dbg(di->dev, "Fault watchdog recovered\n");
	if (stat_set & CONTROLLER_STAT1_BAT_REMOVED)
		dev_dbg(di->dev, "Battery removed\n");
	if (stat_reset & CONTROLLER_STAT1_BAT_REMOVED)
		dev_dbg(di->dev, "Battery inserted\n");
	if (stat_set & CONTROLLER_STAT1_BAT_TEMP_OVRANGE)
		dev_dbg(di->dev, "Battery temperature overrange\n");
	if (stat_reset & CONTROLLER_STAT1_BAT_TEMP_OVRANGE)
		dev_dbg(di->dev, "Battery temperature within range\n");

	if (charger_fault) {
		change_charge_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
		dev_err(di->dev, "Charger Fault stop charging\n");
	}

}
Beispiel #4
0
void bat_monitor_work_func(struct work_struct *work)
{
    struct bq27541_info *di = container_of(work,
                struct bq27541_info, bat_monitor_work.work);
    int err = 0;
    int new_value=0;
    int change=0;

    //For dead battery
    if(di->err_count>=15){
        printk("bat:%s get i2c error\n",__func__);
        err=bq27x00_battery_voltage(di,&new_value);
        if (err){
            queue_delayed_work(bat_work_queue,&di->bat_monitor_work,
                    msecs_to_jiffies(10000 * 1));
            blocking_notifier_call_chain(&notifier_list, EVENT_BATTERY_I2C_ERROR, NULL);
		di->health = POWER_SUPPLY_HEALTH_UNKNOWN;
		power_supply_changed(&di->bat);
        }else{//dead battery is wake up
            printk("bat:%s dead battery is wake up\n",__func__);
            di->err_count=0;
            queue_delayed_work(bat_work_queue,&di->bat_monitor_work,0);
            blocking_notifier_call_chain(&notifier_list, EVENT_BATTERY_I2C_NORMAL, NULL);
		di->health = POWER_SUPPLY_HEALTH_GOOD;
		power_supply_changed(&di->bat);
        }
    }else{
		/*
		 * We query the four most important variables frequently:
		 *
		 * temperature, voltage, capacity, status
		 *
		 * These four are used by various code in upper layers for
		 * power management. The rest of the variables are not that
		 * important or do not change much over time so we do not
		 * need to query them too often
		 */
		if (bq27x00_battery_temperature(di, &new_value)) {
			di->err_count++;
		} else {
			if (new_value != di->temp) {
				di->temp = new_value;
				change = 1;
				bat_temp_charge_protect(di);
			}
		}

		if (bq27x00_battery_voltage(di, &new_value)) {
			di->err_count++;
		} else {
			if (new_value != di->voltage) {
				di->voltage = new_value;
				change = 1;

				//Low battery protection
		                //If android with weak battery has some problem and not be shutdown then driver need to turn off the system.
				if((di->voltage <= HARD_LOW_VOLTAGE_THRESHOLD)
						&& (di->status==POWER_SUPPLY_STATUS_DISCHARGING))
					blocking_notifier_call_chain(&notifier_list, EVENT_WEAK_BATTERY, NULL);
			}
		}

		if (bq27x00_battery_rsoc(di, &new_value)) {
			di->err_count++;
		} else {
			if (new_value != di->capacity) {
				di->capacity = new_value;
				change = 1;

				//Recharge event
				if((di->status==POWER_SUPPLY_STATUS_NOT_CHARGING)
						&& (di->capacity<=RECHARGE_THRESHOLD))
				blocking_notifier_call_chain(&notifier_list, EVENT_RECHARGE_BATTERY, NULL);
			}
		}

		if (bq27x00_battery_status(di, &new_value)) {
			di->err_count++;
		} else {
			if (new_value!=di->status) {
				di->status = new_value;
				change = 1;

				//Full charge protectition event
				if (di->status == POWER_SUPPLY_STATUS_FULL)
					blocking_notifier_call_chain(&notifier_list, EVENT_FULL_BATTERY, NULL);
			}
		}

		/*
		 * Average current is also required to be
		 * queried frequently for factory testing
		 */
		if (bq27x00_battery_current(di, &new_value)){
			di->err_count++;
		} else {
			if (new_value != di->current_avg) {
				di->current_avg=new_value;
				change = 1;
			}
		}

		if (++di->long_count != BQ27541_LONG_COUNT) {
			/* Done with the important ones, skip the rest for now */
			goto update_status;
		} else {
			di->long_count = 0;
		}

        new_value=twl_get_batntc();
        if(new_value!=di->ntc_temp){
            if((di->ntc_temp==0) && (new_value>0))
                blocking_notifier_call_chain(&notifier_list, EVENT_BATTERY_NTC_NORMAL, NULL);
            di->ntc_temp=new_value;
            if(di->ntc_temp==0)
                blocking_notifier_call_chain(&notifier_list, EVENT_BATTERY_NTC_ZERO, NULL);
        }

	        bq27x00_read(REG_FULL_AVAILABLE_CHARGE, &g_full_available_capacity, 0, di);

		if (bq27x00_battery_health(di, &new_value)) {
			di->err_count++;
		} else {
			if (new_value != di->health) {
				di->health = new_value;
				change = 1;
			}
		}

		/* Query TimeToEmpty() register */
		if (bq27x00_battery_time_to_empty(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->time_to_empty) {
			di->time_to_empty = new_value;
			change = 1;
		}

		/* Query TimeToFull() register */
		if (bq27x00_battery_time_to_full(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->time_to_full) {
			di->time_to_full = new_value;
			change = 1;
		}

		/* Query CycleCount() register */
		if (bq27x00_battery_cycle_count(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->cycle_count) {
			di->cycle_count = new_value;
			change = 1;
		}

		/* Query AveragePower() register */
		if (bq27x00_battery_average_power(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->average_power) {
			di->average_power = new_value;
			change = 1;
		}

		/* Query AvailableEnergy() register */
		if (bq27x00_battery_available_energy(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->available_energy) {
			di->available_energy = new_value;
			change = 1;
		}

		/* Query RemainingCapacity() register */
		if (bq27x00_battery_remaining_charge(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->remaining_charge) {
			di->remaining_charge = new_value;
			change = 1;
		}

		/* Query FullChargeCapacity() register */
		if (bq27x00_battery_full_charge(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->full_charge) {
			di->full_charge = new_value;
			change = 1;
		}

		/* Query FullAvailableCapacity() register */
		if (bq27x00_battery_full_charge_uncompensated(di, &new_value)) {
			di->err_count++;
		} else if (new_value != di->full_charge_uncompensated) {
			di->full_charge_uncompensated = new_value;
			change = 1;
		}



		if (++di->manufacturer_id_read_count != 2) {
			goto update_status;
		} else {
			di->manufacturer_id_read_count = 0;
		}

		/* Check for manufacturer ID every minute */
		new_value = check_manufacturer(di);

		if (new_value != di->manufacturer){
			di->manufacturer = new_value;
			change = 1;
            
			if (di->manufacturer >= 0)
				blocking_notifier_call_chain(&notifier_list,
					EVENT_RECOGNIZE_BATTERY, NULL);

			if (di->manufacturer == NOT_RECOGNIZE)
				blocking_notifier_call_chain(&notifier_list,
					EVENT_NOT_RECOGNIZE_BATTERY, NULL);
            
			if (di->manufacturer == UNKNOW)
				blocking_notifier_call_chain(&notifier_list,
					EVENT_UNKNOW_BATTERY, NULL);
        }

update_status:

	if (change) {
		power_supply_changed(&di->bat);

		// LED function
		u8 value = 0;

		if ((di->disable_led == 0) &&
			!twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &value, 0x03)) {

		        if ((di->status == POWER_SUPPLY_STATUS_CHARGING)
					&& (value & (1 << 2))) {
				if(di->capacity < 90) {
					/*
					 * Battery being charged, capacity < 90%: Amber LED
					 */
					omap4430_green_led_set(NULL, 0);
					omap4430_orange_led_set(NULL, 255);
				} else {
					/*
					 * Battery being charged, capacity >= 90%: Green LED
					 */
					omap4430_orange_led_set(NULL, 0);
					omap4430_green_led_set(NULL, 255);
				}
		        } else if (di->status == POWER_SUPPLY_STATUS_FULL) {
				if (value & (1 << 2)) {
					/* Set to green if connected to USB */
					omap4430_orange_led_set(NULL, 0);
					omap4430_green_led_set(NULL, 255);
				} else {
					omap4430_green_led_set(NULL, 0);
					omap4430_orange_led_set(NULL, 0);
				}
		        }
		}
	}

        if(di->err_count>=15){
            printk("bat:%s get i2c error\n",__func__);
            queue_delayed_work(bat_work_queue,&di->bat_monitor_work,
                            msecs_to_jiffies(10000 * 1));
        }else
            queue_delayed_work(bat_work_queue,&di->bat_monitor_work,
            msecs_to_jiffies(5000 * 1));
    }
}
Beispiel #5
0
static int twl4030_power_probe(struct platform_device *pdev)
{
	struct twl4030_power_data *pdata = dev_get_platdata(&pdev->dev);
	struct device_node *node = pdev->dev.of_node;
	int err = 0;
	int err2 = 0;
	u8 val;

	if (!pdata && !node) {
		dev_err(&pdev->dev, "Platform data is missing\n");
		return -EINVAL;
	}

	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
			       TWL4030_PM_MASTER_PROTECT_KEY);
	err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
			       TWL4030_PM_MASTER_KEY_CFG2,
			       TWL4030_PM_MASTER_PROTECT_KEY);

	if (err) {
		pr_err("TWL4030 Unable to unlock registers\n");
		return err;
	}

	if (pdata) {
		/* TODO: convert to device tree */
		err = twl4030_power_configure_scripts(pdata);
		if (err) {
			pr_err("TWL4030 failed to load scripts\n");
			goto relock;
		}
		err = twl4030_power_configure_resources(pdata);
		if (err) {
			pr_err("TWL4030 failed to configure resource\n");
			goto relock;
		}
	}

	/* Board has to be wired properly to use this feature */
	if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
		/* Default for SEQ_OFFSYNC is set, lets ensure this */
		err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
				      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
		if (err) {
			pr_warning("TWL4030 Unable to read registers\n");

		} else if (!(val & SEQ_OFFSYNC)) {
			val |= SEQ_OFFSYNC;
			err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
					TWL4030_PM_MASTER_CFG_P123_TRANSITION);
			if (err) {
				pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
				goto relock;
			}
		}

		pm_power_off = twl4030_power_off;
	}

relock:
	err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
			       TWL4030_PM_MASTER_PROTECT_KEY);
	if (err2) {
		pr_err("TWL4030 Unable to relock registers\n");
		return err2;
	}

	return err;
}
int twl6030_mmc_card_detect_config(void)
{
	int ret;
	u8 reg_val = 0;

	/* Unmasking the Card detect Interrupt line for MMC1 from Phoenix */
	twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
						REG_INT_MSK_LINE_B);
	twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
						REG_INT_MSK_STS_B);
	/*
	 * Initially Configuring MMC_CTRL for receiving interrupts &
	 * Card status on TWL6030 for MMC1
	 */
	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val, TWL6030_MMCCTRL);
	if (ret < 0) {
		pr_err("twl6030: Failed to read MMCCTRL, error %d\n", ret);
		return ret;
	}
	/* LGE_SJIT 2011-11-28 [[email protected]] 2011-11-28
	 * LGE_CHANGE [[email protected]] 2011-07-19, from p940
	 *
	 * Leak the current 40mA on off state
	 */
#if defined(CONFIG_MMC_OMAP_HS_VMMC_AUTO_OFF)
	reg_val |= VMMC_AUTO_OFF;
#ifndef CONFIG_MACH_LGE_MMC_COVER
	reg_val |= SW_FC;
#else
	reg_val |= SW_FC;			//MOD
#endif

#else
	reg_val &= ~VMMC_AUTO_OFF;
#ifndef CONFIG_MACH_LGE_MMC_COVER
	reg_val |= SW_FC;
#else	
	reg_val &= ~SW_FC;
#endif

#endif
//	reg_val |= SW_FC;
	ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val, TWL6030_MMCCTRL);
	if (ret < 0) {
		pr_err("twl6030: Failed to write MMCCTRL, error %d\n", ret);
		return ret;
	}

	/* Configuring PullUp-PullDown register */
	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val,
						TWL6030_CFG_INPUT_PUPD3);
	if (ret < 0) {
		pr_err("twl6030: Failed to read CFG_INPUT_PUPD3, error %d\n",
									ret);
		return ret;
	}
	reg_val &= ~(MMC_PU | MMC_PD);
	ret = twl_i2c_write_u8(TWL6030_MODULE_ID0, reg_val,
						TWL6030_CFG_INPUT_PUPD3);
	if (ret < 0) {
		pr_err("twl6030: Failed to write CFG_INPUT_PUPD3, error %d\n",
									ret);
		return ret;
	}

	ret = twl_i2c_write_u8(TWL6030_MODULE_ID0,
			(MMC_MINS_DEB_MASK | MMC_MEXT_DEB_MASK),
			TWL6030_MMCDEBOUNCING);
	if (ret < 0){
		pr_err("twl6030: Failed to write MMC_MEXT_DEB_MASK %d\n",
									ret);
		return ret;
	}

	return 0;
}
static int twl4030_bci_read(u8 reg, u8 *val)
{
	return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg);
}
/**
 * @brief omap3evm_set_mux - Sets mux to enable/disable signal routing to
 *                             different peripherals present on new EVM board
 * IMPORTANT - This function will take care of writing appropriate values for
 * active low signals as well
 *
 * @param mux_id - enum, mux id to enable/disable
 * @param value - enum, ENABLE_MUX for enabling and DISABLE_MUX for disabling
 *
 * @return result of operation - 0 is success
 */
static int omap3evm_set_mux(enum omap3evmdc_mux mux_id, enum config_mux value)
{
	static int is_init_done = 0;
	unsigned char val;
	int err = 0;

	if (unlikely(mux_id >= NUM_MUX)) {
		printk(KERN_ERR MODULE_NAME ": Invalid mux id\n");
		return -EPERM;
	}

	if (is_init_done == 0) {
		/*FIXME: Need to follow standard GPIO API's to control
		 *	TWL4030 GPIO.
		 */
		/* Enable TWL GPIO Module */
		twl_i2c_write_u8(TWL4030_MODULE_GPIO, 0x04, REG_GPIO_CTRL);

		/* First Level Enable GPIO */
		/* Configure GPIO2 as output */
		twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIODATADIR1);
		val |= 0x04;
		twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIODATADIR1);
		/* Set GPIO-2 pull-up */
		twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIOPUPDCTR1);
		val |= 0x20;
		twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIOPUPDCTR1);
		/* Set GPIO-2 = 0 */
		twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIODATAOUT1);
		val &= ~0x04;
		twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIODATAOUT1);

		/* Configure GPIO8 as output*/
		twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIODATADIR2);
		val |= 0x1;
		twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIODATADIR2);
		/* GPIO-8 pull down */
		twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIOPUPDCTR3);
		val |= 0x01;
		twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIOPUPDCTR3);

		/* Assert the reset signal */
		gpio_set_value(GPIO98_VID_DEC_RES, 0);
		mdelay(5);
		gpio_set_value(GPIO98_VID_DEC_RES, 1);
	}
	switch (mux_id) {
	case MUX_TVP5146:
		if (ENABLE_MUX == value) {
			/* Set GPIO8 = 0 */
			twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val,
					REG_GPIODATAOUT2);
			val &= ~0x1;
			twl_i2c_write_u8(TWL4030_MODULE_GPIO, val,
					REG_GPIODATAOUT2);

			gpio_set_value(nCAM_VD_SEL, 1);
		} else {
			/* Set GPIO8 = 0 */
			twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val,
					REG_GPIODATAOUT2);
			val |= 0x1;
			twl_i2c_write_u8(TWL4030_MODULE_GPIO, val,
					REG_GPIODATAOUT2);
		}
		break;

	case MUX_CAMERA_SENSOR:
		if (ENABLE_MUX == value) {
			/* Set GPIO8 = 0 */
			twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val,
					REG_GPIODATAOUT2);
			val &= ~0x1;
			twl_i2c_write_u8(TWL4030_MODULE_GPIO, val,
					REG_GPIODATAOUT2);

			gpio_set_value(nCAM_VD_SEL, 0);
		} else {
			/* Set GPIO8 = 0 */
			twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val,
					REG_GPIODATAOUT2);
			val |= 0x1;
			twl_i2c_write_u8(TWL4030_MODULE_GPIO, val,
					REG_GPIODATAOUT2);
		}
		break;

	case MUX_EXP_CAMERA_SENSOR:
		if (ENABLE_MUX == value) {
			/* Set GPIO8 = 1 */
			twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val,
					REG_GPIODATAOUT2);
			val |= 0x1;
			twl_i2c_write_u8(TWL4030_MODULE_GPIO, val,
					REG_GPIODATAOUT2);

		} else {
			/* Set GPIO8 = 0 */
			twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val,
					REG_GPIODATAOUT2);
			val &= ~0x1;
			twl_i2c_write_u8(TWL4030_MODULE_GPIO, val,
					REG_GPIODATAOUT2);
		}
		break;

	case NUM_MUX:
	default:
		printk(KERN_ERR "Invalid mux id\n");
		err = -EPERM;
	}

	return err;
}
void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
	int err = 0;
	int i;
	struct twl4030_resconfig *resconfig;
	u8 val, address = twl4030_start_script_address;

	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
			TWL4030_PM_MASTER_KEY_CFG1,
			TWL4030_PM_MASTER_PROTECT_KEY);
	if (err)
		goto unlock;

	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
			TWL4030_PM_MASTER_KEY_CFG2,
			TWL4030_PM_MASTER_PROTECT_KEY);
	if (err)
		goto unlock;

	for (i = 0; i < twl4030_scripts->num; i++) {
		err = load_twl4030_script(twl4030_scripts->scripts[i], address);
		if (err)
			goto load;
		address += twl4030_scripts->scripts[i]->size;
	}

	resconfig = twl4030_scripts->resource_config;
	if (resconfig) {
		while (resconfig->resource) {
			err = twl4030_configure_resource(resconfig);
			if (err)
				goto resource;
			resconfig++;

		}
	}

	
	if (twl4030_scripts->use_poweroff && !pm_power_off) {
		
		err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
				      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
		if (err) {
			pr_warning("TWL4030 Unable to read registers\n");

		} else if (!(val & SEQ_OFFSYNC)) {
			val |= SEQ_OFFSYNC;
			err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
					TWL4030_PM_MASTER_CFG_P123_TRANSITION);
			if (err) {
				pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
				goto relock;
			}
		}

		pm_power_off = twl4030_power_off;
	}

relock:
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
			TWL4030_PM_MASTER_PROTECT_KEY);
	if (err)
		pr_err("TWL4030 Unable to relock registers\n");
	return;

unlock:
	if (err)
		pr_err("TWL4030 Unable to unlock registers\n");
	return;
load:
	if (err)
		pr_err("TWL4030 failed to load scripts\n");
	return;
resource:
	if (err)
		pr_err("TWL4030 failed to configure resource\n");
	return;
}
static int __init sdp4430_soc_init(void)
{
	struct i2c_adapter *adapter;
	u8 gpoctl;
	int ret;

	if (!machine_is_omap_4430sdp() && !machine_is_omap4_panda() &&
		!machine_is_omap_tabletblaze()) {
		pr_debug("Not SDP4430, BlazeTablet or PandaBoard!\n");
		return -ENODEV;
	}
	printk(KERN_INFO "SDP4430 SoC init\n");
	if (machine_is_omap_4430sdp())
		snd_soc_sdp4430.name = "SDP4430";
	else if (machine_is_omap4_panda())
		snd_soc_sdp4430.name = "Panda";
	else if (machine_is_omap_tabletblaze())
		snd_soc_sdp4430.name = "Tablet44xx";

	sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
	if (!sdp4430_snd_device) {
		printk(KERN_ERR "Platform device allocation failed\n");
		return -ENOMEM;
	}

	ret = snd_soc_register_dais(&sdp4430_snd_device->dev, dai, ARRAY_SIZE(dai));
	if (ret < 0)
		goto err;
	platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);

	ret = platform_device_add(sdp4430_snd_device);
	if (ret)
		goto err_dev;

	twl6040_codec = snd_soc_card_get_codec(&snd_soc_sdp4430,
					"twl6040-codec");
	if(twl6040_codec <= 0) {
		printk(KERN_ERR "sdp4430: could not find `twl6040-codec`\n");
		ret = -ENODEV;
		goto err_dev;
	}

	av_switch_reg = regulator_get(&sdp4430_snd_device->dev, "av-switch");
	if (IS_ERR(av_switch_reg)) {
		ret = PTR_ERR(av_switch_reg);
		printk(KERN_ERR "couldn't get AV Switch regulator %d\n",
			ret);
		goto err_dev;
	}

	/* enable tps6130x */
	ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &gpoctl,
		TWL6040_REG_GPOCTL);
	if (ret) {
		printk(KERN_ERR "i2c read error\n");
		goto i2c_err;
	}

	ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, gpoctl | TWL6040_GPO2,
		TWL6040_REG_GPOCTL);
	if (ret) {
		printk(KERN_ERR "i2c write error\n");
		goto i2c_err;
	}

	adapter = i2c_get_adapter(TPS6130X_I2C_ADAPTER);
	if (!adapter) {
		printk(KERN_ERR "can't get i2c adapter\n");
		ret = -ENODEV;
		goto adp_err;
	}

	tps6130x_client = i2c_new_device(adapter, &tps6130x_hwmon_info);
	if (!tps6130x_client) {
		printk(KERN_ERR "can't add i2c device\n");
		ret = -ENODEV;
		goto tps_err;
	}


	/* Only configure the TPS6130x on SDP4430 */
	if (machine_is_omap_4430sdp() || machine_is_omap_tabletblaze())
		sdp4430_tps6130x_configure();
	i2c_put_adapter(adapter);

	return ret;

tps_err:
	i2c_put_adapter(adapter);
adp_err:
	twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, gpoctl, TWL6040_REG_GPOCTL);
i2c_err:
	regulator_put(av_switch_reg);
err_dev:
	snd_soc_unregister_dais(&sdp4430_snd_device->dev, ARRAY_SIZE(dai));
err:
	platform_device_put(sdp4430_snd_device);
	return ret;
}
Beispiel #11
0
struct pwm_device *pwm_request(int pwm_id, const char *label)
{
	u8 stat;
	u8 val;
	int ret;
	struct pwm_device *pwm;

	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
	if (pwm == NULL) {
		pr_err("%s: failed to allocate memory\n", label);
		return NULL;
	}

	pwm->label = label;
	pwm->pwm_id = pwm_id;
	pwm->duty_cycle = -1;

	switch (pwm_id) {
		case 3:
			/* Custom PWM2 */
			ret = twl_i2c_read_u8(TWL6030_MODULE_ID1,
					&val,
					TWL6030_TOGGLE3);

			if (ret < 0)
				goto fail;

			ret = twl_i2c_write_u8(TWL6030_MODULE_ID1,
					(val | TOGGLE3_PWM2_SET | TOGGLE3_PWM2_CLK_EN),
					TWL6030_TOGGLE3);
			break;
		case 2:
			/* Custom PWM1 */
			ret = twl_i2c_read_u8(TWL6030_MODULE_ID1,
					&val,
					TWL6030_TOGGLE3);

			if (ret < 0)
				goto fail;

			ret = twl_i2c_write_u8(TWL6030_MODULE_ID1,
					(val | TOGGLE3_PWM1_SET | TOGGLE3_PWM1_CLK_EN),
					TWL6030_TOGGLE3);
			break;

		case 1:
			/* LED PWM */
			/* Configure PWM */
			ret = twl_i2c_read_u8(TWL6030_MODULE_ID1,
					&stat,
					LED_PWM_CTRL2);

			val = PWM_CTRL2_DIS_PD | PWM_CTRL2_SRC_VBUS |
				PWM_CTRL2_MODE_HW;

			/* Setup led current to 5mA if config is not set */
			if (stat & (0x03 << 4))
				val |= (stat & (0x03 << 4));
			else
				val |= PWM_CTRL2_CURR_03;

			ret = twl_i2c_write_u8(TWL6030_MODULE_ID1,
					val,
					LED_PWM_CTRL2);

			if (ret < 0)
				goto fail;

			break;
	}

	return pwm;

fail:
	pr_err("%s: Failed to configure PWM, Error %d\n", pwm->label, ret);

	kfree(pwm);
	return NULL;
}
static ssize_t summit_proc_write(struct file *filp, 
    	const char *buff,unsigned long len, void *data)
{
    struct summit_smb347_info *di=data;
    struct regulator *p_regulator = regulator_get(NULL, "usb-phy");
    //printk(KERN_INFO "%s\n",__func__);
    u32 reg_val,value;
//    void __iomem *addr = NULL;
    int event  = USB_EVENT_VBUS;
    struct clk *phyclk;
    struct clk *clk48m;
    struct clk *clk32k;
    int hw_state=0;
    char messages[256], vol[256];
    phyclk = clk_get(NULL, "ocp2scp_usb_phy_ick");
    if (IS_ERR(phyclk)) {
        pr_warning("cannot clk_get ocp2scp_usb_phy_ick\n");
        return PTR_ERR(phyclk);
    }

    clk48m = clk_get(NULL, "ocp2scp_usb_phy_phy_48m");
    if (IS_ERR(clk48m)) {
        pr_warning("cannot clk_get ocp2scp_usb_phy_phy_48m\n");
        clk_put(phyclk);
        return PTR_ERR(clk48m);
    }

    clk32k = clk_get(NULL, "usb_phy_cm_clk32k");
    if (IS_ERR(clk32k)) {
        pr_warning("cannot clk_get usb_phy_cm_clk32k\n");
        clk_put(phyclk);
        clk_put(clk48m);
        return PTR_ERR(clk32k);
    }
    if (len > 256)
    	len = 256;

    if (copy_from_user(messages, buff, len))
    	return -EFAULT;
    
    if ('-' == messages[0]) {
    	/* set the register index */
    	memcpy(vol, messages+1, len-1);
    	index = (int) simple_strtoul(vol, NULL, 16);
    	printk(KERN_INFO"%s:set register 0x%x\n",__func__, index);
    }else if('+'==messages[0]) {
    	// set the register value 
    	memcpy(vol, messages+1, len-1);
    	reg_val = (int)simple_strtoul(vol, NULL, 16);
    	//you can read value from the register of hardwae in here
    	i2c_smbus_write_byte_data(di->client, index, reg_val);
    	printk(KERN_INFO"%s:register 0x%x: set value 0x%x\n",__func__, index, reg_val);
    }else if ('!' == messages[0]) {
        switch(messages[1]){
            case 'a':
                //gpio_request(119, "ADO_SPK_ENABLE");
                //gpio_direction_output(119, 0);           
    value =i2c_smbus_read_byte_data(di->client,index);
    if (value < 0) {
        printk(KERN_INFO"error reading index=0x%x value=0x%x\n",index,value);
    }
    printk(KERN_INFO"%s:register 0x%x: return value 0x%x di->mbid=%d  protect_enable=%d di->protect_event=0x%x\n",__func__, index, value,di->mbid,di->protect_enable,di->protect_event);
            break;
            case 'b':
                 //regulator_disable(p_regulator);
            # if 0
                twl_i2c_read_u8(TWL6030_MODULE_ID0, &hw_state, STS_HW_CONDITIONS);
                printk("hw_state=0x%x\n",hw_state);
		if(hw_state & STS_USB_ID){
                     printk("STS_USB_ID\n");
		}else{
                     printk("NO STS_USB_ID\n");
		}            
                command=i2c_smbus_read_byte_data(di->client,COMMAND_A);
                printk("COMMAND_A=0x%x\n",command);
                #endif
                //printk("enable clock\n");
                //clk_enable(phyclk);
                //clk_enable(clk48m);
                //clk_enable(clk32k);
                printk("phy power up");
                __raw_writel(~PHY_PD, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x2300)));
                //summit_config_charge_current(di,FCC_2000mA,CONFIG_NO_CHANGE,CONFIG_NO_CHANGE);
                //charge_enable(di,1);
            break;
            case 'c':
                printk("disable clock\n");
                clk_disable(phyclk);
                clk_disable(clk48m);
                clk_disable(clk32k);
                printk("phy power down");
                __raw_writel(PHY_PD, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x2300)));
                //charge_enable(di,0);
                //di->event=EVENT_CHANGE_TO_ONDEMAND;
                //printk("%s event=%d %d \n",__func__,di->event,EVENT_CHANGE_TO_ONDEMAND);
                //fsm_stateTransform(di);
                //fsm_doAction(di);    
            break;
/*
enable
ocp2scp_usb_phy_ick,ocp2scp_usb_phy_phy_48m,	
	->4A0093E0 =0x101	
usb_phy_cm_clk32k
	->4A00 8640 =0x100
disable
	->4A0093E0 =0x30100
	->4A00 8640 =0x0
*/
            case 'd':
                //di->event=EVENT_CHANGE_TO_INTERNAL_FSM;
                //printk("%s event=%d %d \n",__func__,di->event,EVENT_CHANGE_TO_ONDEMAND);
                //fsm_stateTransform(di);
                //fsm_doAction(di);
                printk("phy power up");
                __raw_writel(0x101, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x93E0)));
                __raw_writel(0x100, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x8640)));
                __raw_writel(~PHY_PD, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x2300)));
                //switch_mode(di,USB1_MODE);
            break;
            case 'e':
                printk("phy power down");
                __raw_writel(0x30100, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x93E0)));
                __raw_writel(0x0, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x8640)));
                __raw_writel(PHY_PD, OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x2300)));
                //switch_mode(di,USB5_MODE);
            break;
            case 'f':
                value=__raw_readl(OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x4120)));
                printk("%s : CM_CLKMODE_DPLL_CORE=0x%x\n",__func__,value);
                value=__raw_readl(OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x93E0)));
                printk("%s : CM_L3INIT_USBPHY_CLKCTRL=0x%x\n",__func__,value);
                value=__raw_readl(OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x8640)));
                printk("%s : CM_ALWON_USBPHY_CLKCTRL=0x%x\n",__func__,value);
                value=__raw_readl(OMAP2_L4_IO_ADDRESS(0x4a000000 + (0x2300)));
                printk("%s : CONTROL_DEV_CONF=0x%x\n",__func__,value);
                //switch_mode(di,HC_MODE);
                value=__raw_readl(OMAP2_L4_IO_ADDRESS(0x4a100000 + (0x620)));
                printk("%s : usb2phy=0x%x\n",__func__,value);
            break;
            case 'g':
                twl_i2c_write_u8(TWL6030_MODULE_ID0,  0x8 ,0xe5);
                twl_i2c_write_u8(TWL6030_MODULE_ID0,  0x18 ,0xa3);
                twl_i2c_write_u8(TWL6030_MODULE_ID0,  0x3f ,0xa1);
                twl_i2c_write_u8(TWL6030_MODULE_ID0,  0xe1 ,0xa2);
            # if 0
                summit_charge_enable(di,0);
                summit_charge_enable(di,1);
                mdelay(10);
                summit_check_bmd(di);
                //charge_enable(di,0);	
            #endif
            break;
            case '1':
                //summit_switch_mode(di,USB1_OR_15_MODE);
                summit_config_suspend_by_register(di,1);
            break;
            case '2':
                //summit_switch_mode(di,USB5_OR_9_MODE);
                summit_config_suspend_by_register(di,0);
            break;
            case '3':
                gpio_set_value(di->pin_susp, 0);printk(KERN_INFO "di->pin_susp=%d\n",di->pin_susp);
            break;
            case '4':
                gpio_set_value(di->pin_susp, 1);printk(KERN_INFO "di->pin_susp=%d\n",di->pin_susp);
            break;
            case '5':
                gpio_set_value(di->pin_en, 0);printk(KERN_INFO "di->pin_en=%d\n",di->pin_en);
            break;
            case '6':
                gpio_set_value(di->pin_en, 1);printk(KERN_INFO "di->pin_en=%d\n",di->pin_en);
                //summit_config_apsd(di,1);
            break;
            case '7':
                summit_config_aicl(di,0,4200);
                //summit_config_apsd(di,0);
            break;
            case '8':
                blocking_notifier_call_chain(&di->xceiv->notifier,USB_EVENT_NONE, di->xceiv->gadget);
                //summit_suspend_mode(di,1);
            break;
            case '9':
                //printk("power_source=%d\n",di->power_source);
                //di->power_source=4;
                summit_charger_reconfig(di);
                
            break;
    	}
    }
    regulator_put(p_regulator);
    return len;
}
Beispiel #13
0
static void twl4030_poweroff(void)
{
	u8 val;
	int err;

    // Clear IT_ALARM bit in RTC_INTERRUPTS_REG [+]
	err = twl_i2c_read_u8(TWL4030_MODULE_RTC, &val,
                    REG_RTC_INTERRUPT_REG);
	if (err) {
		printk(KERN_WARNING "I2C error %d while reading TWL4030"
					"REG_RTC_INTERRUPT_REG\n", err);
		return ;
	}

	val &= ~(0x01<<3);
	err = twl_i2c_write_u8(TWL4030_MODULE_RTC, val,
                    REG_RTC_INTERRUPT_REG);
	if (err) {
		printk(KERN_WARNING "I2C error %d while writing TWL4030"
					"REG_RTC_INTERRUPT_REG\n", err);
		return ;
	}

#if 0
	err = twl_i2c_read_u8(TWL4030_MODULE_RTC, &val,
                    REG_RTC_INTERRUPT_REG);
	if (err) {
		printk(KERN_WARNING "I2C error %d while reading TWL4030"
					"REG_RTC_INTERRUPT_REG\n", err);
		return ;
	}
	printk("Clear IT ALARM bit in RTC INTERRUPT REG( = 0x%02x) Done!\n", val);
#endif
    // Clear IT_ALARM bit in RTC_INTERRUPTS_REG [-]

	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
				  PWR_P1_SW_EVENTS);
	if (err) {
		printk(KERN_WARNING "I2C error %d while reading TWL4030"
					"PM_MASTER P1_SW_EVENTS\n", err);
		return ;
	}

	val |= PWR_DEVOFF;

#if 0
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
				   PWR_P1_SW_EVENTS);

	if (err) {
		printk(KERN_WARNING "I2C error %d while writing TWL4030"
					"PM_MASTER P1_SW_EVENTS\n", err);
		return ;
	}
#else
    while(1) {
    	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
    				   PWR_P1_SW_EVENTS);
        mdelay(500);
    };
#endif

	return;
}
Beispiel #14
0
static void board_poweroff(void)
{
	/* int n_usbic_state; */
#if ( defined( CONFIG_MACH_SAMSUNG_P1WIFI ) )
	u8 hwsts = 0;
	u8 vbus_val = 0;

	twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts, 0x0F /*REG_STS_HW_CONDITIONS*/);

	if(hwsts & 0x80)  // STS_VBUS		0x80
		vbus_val = 1;
	else
		vbus_val = 0;
#endif

	printk("\nPower off routine - Board Shutdown!! \n");

/*
#if defined(CONFIG_USB_ANDROID)
	android_usb_set_connected(0);
#endif
*/

	/* get_real_usbic_state(); */
	//gpio_direction_output(GPIO_MSM_RST,0);
	//gpio_direction_output(GPIO_FONE_ACTIVE, 0);
	// if (GPIO_TA_CONNECTED_N is LOW)
#if ( defined( CONFIG_MACH_SAMSUNG_LATONA ) ) // jypark72, to avoid build error
	if ( !gpio_get_value( OMAP_GPIO_TA_NCONNECTED ) || gpio_get_value( OMAP_GPIO_JIG_ON18 ) )
#elif ( defined( CONFIG_MACH_SAMSUNG_P1WIFI ) )
	if (vbus_val || gpio_get_value( OMAP_GPIO_JIG_ON18 ) )
#endif
	{
		printk("Warmreset by TA or USB or Jtag - check 2 pins : JIG_ON18, TA_nConnected \n\n");

		preempt_disable();
		local_irq_disable();
		local_fiq_disable();

#ifdef CONFIG_SAMSUNG_KERNEL_DEBUG
		omap_writel(0x54455352, OMAP343X_CTRL_BASE + 0x9C4); // set to normal reset
#endif

#if 1
		/* using watchdog reset */
		omap_watchdog_reset();
		//machine_restart("ta_inserted");
#else
		/* using core_dpll_warmreset with global reset */
		//omap3_configure_core_dpll_warmreset();
		machine_restart("ta_inserted");
#endif

		while(1);
	}
	else
	{
		while(1)
		{
			if (gpio_get_value(OMAP_GPIO_KEY_PWRON)) {
				printk("Power button is pressed\n\n");
			}
			else {
				printk("Power Off !\n\n");
				gpio_set_value( OMAP_GPIO_PS_HOLD_PU, 0 ); 
				twl4030_poweroff();
				//for(;;);
			}
		}
	}
	return;
}
Beispiel #15
0
static int pandora_backlight_update_status(struct backlight_device *bl)
{
	int brightness = bl->props.brightness;
	u8 r;

	if (bl->props.power != FB_BLANK_UNBLANK)
		brightness = 0;
	if (bl->props.state & BL_CORE_FBBLANK)
		brightness = 0;
	if (bl->props.state & BL_CORE_SUSPENDED)
		brightness = 0;

	if ((unsigned int)brightness > MAX_USER_VALUE)
		brightness = MAX_USER_VALUE;

	if (brightness == 0) {
		if (bl->props.state & PANDORABL_WAS_OFF)
			goto done;

		/* first disable PWM0 output, then clock */
		twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1);
		r &= ~PWM0_ENABLE;
		twl_i2c_write_u8(TWL4030_MODULE_INTBR, r, TWL_INTBR_GPBR1);
		r &= ~PWM0_CLK_ENABLE;
		twl_i2c_write_u8(TWL4030_MODULE_INTBR, r, TWL_INTBR_GPBR1);

		goto done;
	}

	if (bl->props.state & PANDORABL_WAS_OFF) {
		/*
		 * set PWM duty cycle to max. TPS61161 seems to use this
		 * to calibrate it's PWM sensitivity when it starts.
		 */
		twl_i2c_write_u8(TWL_MODULE_PWM, MAX_VALUE, TWL_PWM0_OFF);

		/* first enable clock, then PWM0 out */
		twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1);
		r &= ~PWM0_ENABLE;
		r |= PWM0_CLK_ENABLE;
		twl_i2c_write_u8(TWL4030_MODULE_INTBR, r, TWL_INTBR_GPBR1);
		r |= PWM0_ENABLE;
		twl_i2c_write_u8(TWL4030_MODULE_INTBR, r, TWL_INTBR_GPBR1);

		/*
		 * TI made it very easy to enable digital control, so easy that
		 * it often triggers unintentionally and disabes PWM control,
		 * so wait until 1 wire mode detection window ends.
		 */
		usleep_range(2000, 10000);
	}

	twl_i2c_write_u8(TWL_MODULE_PWM, MIN_VALUE + brightness, TWL_PWM0_OFF);

done:
	if (brightness != 0)
		bl->props.state &= ~PANDORABL_WAS_OFF;
	else
		bl->props.state |= PANDORABL_WAS_OFF;

	return 0;
}
int twl6030_vlow_init(int vlow_irq)
{
	int status;
	u8 val;

	status = twl_i2c_read_u8(TWL_MODULE_PM_SLAVE_RES, &val,
			REG_VBATMIN_HI_CFG_STATE);
	if (status < 0) {
		pr_err("twl6030: I2C err reading REG_VBATMIN_HI_CFG_STATE: %d\n",
				status);
		return status;
	}

	status = twl_i2c_write_u8(TWL_MODULE_PM_SLAVE_RES,
			val | VBATMIN_VLOW_EN, REG_VBATMIN_HI_CFG_STATE);
	if (status < 0) {
		pr_err("twl6030: I2C err writing REG_VBATMIN_HI_CFG_STATE: %d\n",
				status);
		return status;
	}

	status = twl_i2c_read_u8(TWL_MODULE_PIH, &val, REG_INT_MSK_LINE_A);
	if (status < 0) {
		pr_err("twl6030: I2C err reading REG_INT_MSK_LINE_A: %d\n",
				status);
		return status;
	}

	status = twl_i2c_write_u8(TWL_MODULE_PIH, val & ~VLOW_INT_MASK,
			REG_INT_MSK_LINE_A);
	if (status < 0) {
		pr_err("twl6030: I2C err writing REG_INT_MSK_LINE_A: %d\n",
				status);
		return status;
	}

#if !defined(CONFIG_LAB126)
	status = twl_i2c_read_u8(TWL_MODULE_PIH, &val, REG_INT_MSK_STS_A);
	if (status < 0) {
		pr_err("twl6030: I2C err reading REG_INT_MSK_STS_A: %d\n",
				status);
		return status;
	}

	status = twl_i2c_write_u8(TWL_MODULE_PIH, val & ~VLOW_INT_MASK,
		REG_INT_MSK_STS_A);
	if (status < 0) {
		pr_err("twl6030: I2C err writing REG_INT_MSK_STS_A: %d\n",
				status);
		return status;
	}

	twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &vbatmin_hi_threshold,
			TWL6030_VBATMIN_HI_THRESHOLD);
#else
	/* Set the desired low battery threshold */
	vbatmin_hi_threshold = VBATMIN_HI_THRESHOLD;

	twl_i2c_write_u8(TWL_MODULE_PM_MASTER, vbatmin_hi_threshold,
			TWL6030_VBATMIN_HI_THRESHOLD);
#endif

	/* install an irq handler for vlow */
	status = request_threaded_irq(vlow_irq, NULL, handle_twl6030_vlow,
			IRQF_ONESHOT,
			"TWL6030-VLOW", handle_twl6030_vlow);
	if (status < 0) {
		pr_err("twl6030: could not claim vlow irq %d: %d\n", vlow_irq,
				status);
		return status;
	}

#if defined(CONFIG_WAKELOCK)
	wake_lock_init(&vlow_wakelock, WAKE_LOCK_SUSPEND, "low_batt");
#endif

	return 0;
}
Beispiel #17
0
static int twl603x_set_offset(struct voltagedomain *vd)
{
    u8 smps_offset_val;
    int r;

    /*
     * In TWL6030 depending on the value of SMPS_OFFSET efuse register
     * the voltage range supported in standard mode can be either
     * between 0.6V - 1.3V or 0.7V - 1.4V.
     * In TWL6030 ES1.0 SMPS_OFFSET efuse is programmed to all 0's where as
     * starting from TWL6030 ES1.1 the efuse is programmed to 1.
     * At this point of execution there is no way to identify TWL type,
     * so use SMPS1/VCORE1 only to identify if SMPS_OFFSET enabled or not
     * for on both TWL6030/TWL6032 and assume that if SMPS_OFFSET is
     * enabled for SMPS1/VCORE1 then it's enabled for all SMPS regulators.
     */
    if (SMPS_OFFSET_UNINITIALIZED != smps_offset_state)
        /* already configured */
        return 0;

    r = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &smps_offset_val,
                        TWL6030_SMPS_OFFSET_REG);
    if (r) {
        WARN(1, "%s: No SMPS OFFSET value=??? " \
             "read failed %d, max val might be wrong\n",
             __func__, r);
        /* Nothing we can do */
        return r;
    }

    /* Check if SMPS offset already set */
    if ((smps_offset_val & TWL603x_SMPS1_OFFSET_EN_MASK) ==
            TWL603x_SMPS1_OFFSET_EN_MASK) {
        smps_offset_state = SMPS_OFFSET_ENABLED;
        return 0;
    }

    smps_offset_state = SMPS_OFFSET_DISABLED;

    /* Check if TWL firmware lets us write */
    if (!(smps_offset_val & TWL603x_SMPS_OFFSET_RW_ACCESS_MASK)) {
        WARN(1, "%s: No SMPS OFFSET value=0x%02x " \
             "update not possible, max val might be wrong\n",
             __func__, smps_offset_val);
        /* Nothing we can do */
        return -EACCES;
    }

    /* Attempt to set offset for all */
    r = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
                         TWL603x_SMPS_OFFSET_RW_ACCESS_MASK |
                         TWL603x_SMPS_OFFSET_EN_ALL_MASK,
                         TWL6030_SMPS_OFFSET_REG);
    if (r) {
        WARN(1, "%s: No SMPS OFFSET value=0x%02x " \
             "update failed %d, max val might be wrong\n",
             __func__, smps_offset_val, r);
        /* Nothing we can do */
        return r;
    }

    /* Check if SMPS offset now set */
    r = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &smps_offset_val,
                        TWL6030_SMPS_OFFSET_REG);
    if (r) {
        WARN(1, "%s: No SMPS OFFSET value=0x%02x " \
             "check(r=%d) failed, max val might be wrong\n",
             __func__, smps_offset_val, r);
        /* Nothing we can do */
        return r;
    }

    if (!(smps_offset_val & TWL603x_SMPS1_OFFSET_EN_MASK)) {
        WARN(1, "%s: No SMPS OFFSET value=0x%02x " \
             "check failed (r!=w), max val might be wrong\n",
             __func__, smps_offset_val);
        /* Nothing we can do */
        return -EFAULT;
    }

    smps_offset_state = SMPS_OFFSET_ENABLED;

    return 0;
}
Beispiel #18
0
static irqreturn_t charger_ctrl_interrupt(int irq, void *_di)
{
	struct charger_info *di = _di;
	u8 stat_toggle, stat_reset, stat_set;
	u8 reg_stat1, reg_hw_cond;
	int charge_control_state;
	int ret;

	ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &reg_stat1, CONTROLLER_STAT1);
	if (ret)
		goto i2c_error;

	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_hw_cond, STS_HW_CONDITIONS);
	if (ret)
		goto i2c_error;

	charge_control_state = di->charge_control_state;

	stat_toggle = charge_control_state ^ reg_stat1;
	stat_set = stat_toggle & reg_stat1;
	stat_reset = stat_toggle & charge_control_state;

	dev_dbg(di->dev, "%s: stat_toggle=%02x stat_set=%02x stat_reset=%02x hw_cond=%02x\n", __func__,
			stat_toggle, stat_set, stat_reset, reg_hw_cond);

	if (stat_reset & VBUS_DET) {
		dev_info(di->dev, "VBUS_DET OFF\n");

		charger_lock(di);

		di->vbus_online = 0;
		di->otg_online = 0;

		di->invalid_charger = 0;
		switch_set_state(&di->sdev, 0);

		charger_unlock(di);

		charger_update_state(di);
	} else if (stat_set & VBUS_DET) {
		dev_info(di->dev, "VBUS_DET ON\n");

		charger_lock(di);

		if (reg_hw_cond & STS_USB_ID) {
			dev_info(di->dev, "USB_ID ON\n");
			di->otg_online = 1;
		}

		di->vbus_online = 1;

		charger_unlock(di);

		charger_update_state(di);
	}

	di->charge_control_state = reg_stat1;

	return IRQ_HANDLED;

i2c_error:
	dev_err(di->dev, "%s: error while accessing i2c: %d\n", __func__, ret);
	return IRQ_HANDLED;
}
Beispiel #19
0
static int __init twl6030_set_offset(struct voltagedomain *voltdm)
{
	/*
	 * In TWL6030 depending on the value of SMPS_OFFSET
	 * efuse register the voltage range supported in
	 * standard mode can be either between 0.6V - 1.3V or
	 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
	 * is programmed to all 0's where as starting from
	 * TWL6030 ES1.1 the efuse is programmed to 1
	 */
	if (!is_offset_valid) {
		int r;

		r = twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
				REG_SMPS_OFFSET);
		if (r) {
			pr_err("%s: read of smps offset failed - %d\n",
				__func__, r);
			/* Nothing we can do - try later? */
			goto out;
		}
		/* Check if SMPS offset already set */
		if (smps_offset & 0x8)
			goto out;
		/* Check if TWL firmware lets us write */
		if (!(smps_offset & 0x80)) {
			WARN(1, "%s: No SMPS OFFSET value=0x%02x"
				"update not possible, max val might be wrong\n",
				__func__, smps_offset);
			/* Nothing we can do */
			goto out;
		}

		/* Attempt to set offset for all */
		r = twl_i2c_write_u8(TWL6030_MODULE_ID0, 0xFF, REG_SMPS_OFFSET);
		if (r) {
			WARN(1, "%s: No SMPS OFFSET value=0x%02x"
				"update failed %d, max val might be wrong\n",
				__func__, smps_offset, r);
			/* Nothing we can do */
			goto out;
		}

		/* Check if SMPS offset now set */
		r = twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
				REG_SMPS_OFFSET);
		if (r || !(smps_offset & 0x8)) {
			WARN(1, "%s: No SMPS OFFSET value=0x%02x"
				"check(r=%d) failed, max val might be wrong\n",
				__func__, smps_offset, r);
			/* Nothing we can do */
			goto out;
		}
		is_offset_valid = true;
	}
out:
	/*
	 * even if i2c op failed, there is not much we could have done
	 * Carry on with the hope that we will fix ourselves in next iteration
	 */
	return 0;
}
Beispiel #20
0
int lge_usb_dp_dm_check(struct twl4030_usb *twl)
{
#if 0
	cable_dp_dm_short = 1;
	return 0;
#else
	int ret;
	int is_short;
	u8 reg_val;
	u8 reg_backup[2];

//20110804 [email protected] [LS855] skipping check d+/d- when detect LT Cable. [START]
#if 1
	check_cable_type = get_ext_pwr_type();

	if( get_external_power_status()||((check_cable_type==LT_CABLE_56K || check_cable_type==LT_CABLE_130K || check_cable_type==LT_CABLE_910K)))
		return 0;
#else
	if( get_external_power_status())
		return 0;
#endif
//20110804 [email protected] [LS855] skipping check d+/d- when detect LT Cable. [END]


#if 1 /* already exist in twl4030_phy_power() */
//	printk("twl : 0x%x\n", twl);

//	regulator_enable(twl->usb3v1);
	regulator_enable(twl->usb1v8);
	regulator_enable(twl->usb1v5);

	/* PHY power up */
	twl_i2c_read_u8(TWL4030_MODULE_USB, &reg_val, PHY_PWR_CTRL);
	reg_val &= ~PHY_PWR_PHYPWD;
	ret = twl_i2c_write_u8(TWL4030_MODULE_USB, reg_val, PHY_PWR_CTRL);
	if (ret)
		goto err_short_chk1;

	/* ULPI register clock gating is enable */
	ret = twl_i2c_read_u8(TWL4030_MODULE_USB, &reg_backup[0], PHY_CLK_CTRL);
	if (ret)
		goto err_short_chk2;

	ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
			reg_backup[0] | PHY_CLK_CTRL_CLOCKGATING_EN, PHY_CLK_CTRL);
	if (ret)
		goto err_short_chk2;
#endif

	ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
			FUNC_CTRL_XCVRSELECT_MASK | FUNC_CTRL_OPMODE_MASK, FUNC_CTRL_CLR);
	if (ret)
		goto err_short_chk3;

	/* Disable D+, D- pulldown */
	ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
			OTG_CTRL_DMPULLDOWN | OTG_CTRL_DPPULLDOWN, OTG_CTRL_CLR);
	if (ret)
		goto err_short_chk4;

	/* Set D+ to high, D- to low */
#if 0
	ret = twl_i2c_read_u8(TWL4030_MODULE_USB, &reg_val, OTHER_FUNC_CTRL);
	if (ret)
		goto err_short_chk5;

	reg_backup[1] = reg_val & ~(DM_PULLUP | DP_PULLUP);
	ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
			reg_backup[1] | DP_PULLUP, OTHER_FUNC_CTRL);
#else
	ret = twl_i2c_read_u8(TWL4030_MODULE_USB, &reg_backup[1], OTHER_FUNC_CTRL);
	if (ret)
		goto err_short_chk5;

	reg_val = reg_backup[1] & ~(DM_PULLUP | DP_PULLUP);
	ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
			reg_val | DP_PULLUP, OTHER_FUNC_CTRL);
#endif

	if (ret)
		goto err_short_chk5;

	/* Check D- line */
	ret = twl_i2c_read_u8(TWL4030_MODULE_USB, &reg_val, OTHER_INT_STS);
	if (ret)
		goto err_short_chk6;

	if ((reg_val & 0x60) == 0x60)
		is_short = 1;
	else
		is_short = 0;

	/* Set to default */
	twl_i2c_write_u8(TWL4030_MODULE_USB, reg_backup[1], OTHER_FUNC_CTRL);
	twl_i2c_write_u8(TWL4030_MODULE_USB,
			OTG_CTRL_DMPULLDOWN | OTG_CTRL_DPPULLDOWN, OTG_CTRL_SET);
	twl_i2c_write_u8(TWL4030_MODULE_USB,
			FUNC_CTRL_XCVRSELECT_MASK | FUNC_CTRL_OPMODE_MASK, FUNC_CTRL_SET);
#if 0
	twl_i2c_write_u8(TWL4030_MODULE_USB, reg_backup[0], PHY_CLK_CTRL);	/* ULPI register clock gating is disble */
	/* LGE_CHANGE_S [VX20000:FW:[email protected]] 2009-06-08, XXX_mbk_ADC_VBATT_THRM 
	 * If below code is not present in TA Cable asserted, 
	 * we can not set SEL_MADC_MCPC to 1 in ther CARKIT_ANA_CTRL
	 * I don't know why......*/ 
#if 1
	/*#define REG_CARKIT_ANA_CTRL		0xBB */

	ret = twl_i2c_read_u8(TWL4030_MODULE_USB,
			&data_temp,
			REG_CARKIT_ANA_CTRL);
	if (ret) {
		printk(KERN_ERR "%s: BUSY flag.\n", __func__);
	}
#endif
	/* LGE_CHANGE_E [VX20000:FW:[email protected]] / 2009-06-08 */
#endif

	twl_i2c_read_u8(TWL4030_MODULE_USB, &reg_val, PHY_PWR_CTRL);
	reg_val |= PHY_PWR_PHYPWD;
	twl_i2c_write_u8(TWL4030_MODULE_USB, reg_val, PHY_PWR_CTRL);	/* PHY power down */
	//twl4030_i2c_access(0);
	regulator_disable(twl->usb1v5);
	regulator_disable(twl->usb1v8);
//	regulator_disable(twl->usb3v1);

	cable_dp_dm_short = is_short; 

	printk(KERN_DEBUG "%s: D+ and D- lines are %s\n", __func__, is_short? "short":"open");
	return 0;

err_short_chk6:
	twl_i2c_write_u8(TWL4030_MODULE_USB, reg_backup[1], OTHER_FUNC_CTRL);
err_short_chk5:
	twl_i2c_write_u8(TWL4030_MODULE_USB,
			OTG_CTRL_DMPULLDOWN | OTG_CTRL_DPPULLDOWN, OTG_CTRL_SET);
err_short_chk4:
	twl_i2c_write_u8(TWL4030_MODULE_USB,
			FUNC_CTRL_XCVRSELECT_MASK | FUNC_CTRL_OPMODE_MASK, FUNC_CTRL_SET);
err_short_chk3:
	twl_i2c_write_u8(TWL4030_MODULE_USB, reg_backup[0], PHY_CLK_CTRL);
err_short_chk2:
	twl_i2c_write_u8(TWL4030_MODULE_USB, PHY_PWR_PHYPWD, PHY_PWR_CTRL);
err_short_chk1:
	//twl4030_i2c_access(0);

	regulator_disable(twl->usb1v5);
	regulator_disable(twl->usb1v8);
//	regulator_disable(twl->usb3v1);

	printk(KERN_ERR "%s: Error \n", __func__);
	return ret;
#endif
}
Beispiel #21
0
void twl4030_poweroff(void)
{
	u8 uninitialized_var(val);
	int err;
	u8 pwrana2_val = 0;

	twl_rewrite_starton_condition(STARTON_CONDITION);
	// Unlock PROTECT_KEY reg's KEY_TST flag.
	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0E, R_PROTECT_KEY);
	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xE0, R_PROTECT_KEY);
	// Get the current PWRANA2 value.
	twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &pwrana2_val, R_CFG_PWRANA2);
	// Make LOJIT1_LOWV (bit 2) and LOJIT0_LOWV (bit 1) 0.
	pwrana2_val &= 0xF9;
	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, pwrana2_val, R_CFG_PWRANA2);
	// Lock back PROTECT_KEY reg's KEY_TST flag.
	twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xFF, R_PROTECT_KEY);
	printk(KERN_WARNING "[kernel: twl4030_poweroff] PWRANA2 was set to high jitter mode\n");

#ifdef POWERON_BUGFIX
	u8 vdd1_type_value, vdd2_type_value, clken_type_value, hfclkout_type_value;

	// set VDD1_TYPE to TYPE4
	vdd1_type_value = 0x04;
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, vdd1_type_value, TWL4030_VDD1_TYPE);
	if (err) {
		pr_warning("I2C error %d while writing TWL4030 PM_RECEIVER TWL4030_VDD1_TYPE\n", err);
		return;
	}

	// set VDD2_TYPE to TYPE3
	vdd2_type_value = 0x03;
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, vdd2_type_value, TWL4030_VDD2_TYPE);
	if (err) {
		pr_warning("I2C error %d while writing TWL4030 PM_RECEIVER TWL4030_VDD2_TYPE\n", err);
		return;
	}

	// set CLKEN_TYPE to TYPE3
	clken_type_value = 0x03;
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, clken_type_value, TWL4030_CLKEN_TYPE);
	if (err) {
		pr_warning("I2C error %d while writing TWL4030 PM_RECEIVER TWL4030_CLKEN_TYPE\n", err);
		return;
	}

	// set HFCLKOUT_TYPE
	hfclkout_type_value = 0x00;
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, hfclkout_type_value, TWL4030_HFCLKOUT_TYPE);
	if (err) {
		pr_warning("I2C error %d while writing TWL4030 PM_RECEIVER TWL4030_HFCLKOUT_TYPE\n", err);
		return;
	}
#endif

	/* Make sure SEQ_OFFSYNC is set so that all the res goes to wait-on */
	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
				   CFG_P123_TRANSITION);
	if (err) {
		pr_warning("I2C error %d while reading TWL4030 PM_MASTER CFG_P123_TRANSITION\n",
			err);
		return;
	}

	val |= SEQ_OFFSYNC;
	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
				    CFG_P123_TRANSITION);
	if (err) {
		pr_warning("I2C error %d while writing TWL4030 PM_MASTER CFG_P123_TRANSITION\n",
			err);
		return;
	}

	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
				  PWR_P1_SW_EVENTS);
	if (err) {
		pr_warning("I2C error %d while reading TWL4030 PM_MASTER P1_SW_EVENTS\n",
			err);
		return;
	}

	val |= PWR_STOPON_POWERON | PWR_DEVOFF;

	err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
				   PWR_P1_SW_EVENTS);

	if (err) {
		pr_warning("I2C error %d while writing TWL4030 PM_MASTER P1_SW_EVENTS\n",
			err);
		return;
	}

	return;
}
Beispiel #22
0
static void twl6030_determine_charge_state(struct twl6030_bci_device_info *di)
{
	u8 stat1;
	int newstate = STATE_BATTERY;

	/* TODO: i2c error -> fault? */
	twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &stat1, CONTROLLER_STAT1);

	/* TODO: why is STAT1.0 (BAT_TEMP_OVRANGE) always set? */
	/* printk("battery: determine_charge_state() stat1=%02x int1=%02x\n", stat1, int1); */
	
	if (stat1 & VBUS_DET) {
		/* dedicated charger detected by PHY? */
		if (di->usb_event == USB_EVENT_CHARGER)
			newstate = STATE_AC;
		else
			newstate = STATE_USB;

		if (!di->vbus_online) {
			di->vbus_online = 1;
			wake_lock(&usb_wake_lock);
		}
	} else {
		/* ensure we don't have a stale USB_EVENT_CHARGER should detect bounce */
		di->usb_event = USB_EVENT_NONE;

		if (di->vbus_online) {
			di->vbus_online = 0;
			/* give USB and userspace some time to react before suspending */
			wake_lock_timeout(&usb_wake_lock, HZ / 2);
		}
	}

	if (di->state == newstate)
		return;

	switch (newstate) {
	case STATE_FAULT:
	case STATE_BATTERY:
		if (is_charging(di))
			twl6030_stop_usb_charger(di);
		break;
	case STATE_USB:
	case STATE_AC:
		/* moving out of STATE_FULL should only happen on unplug
		 * or if we actually run down the battery capacity
		 */
		if (di->state == STATE_FULL) {
			newstate = STATE_FULL;
			break;
		}

		/* TODO: high current? */
		if (!is_charging(di))
			twl6030_start_usb_charger(di, 500);
		break;
	}

	if (di->state != newstate) {
		printk("battery: state %s -> %s\n",
			twl6030_state[di->state], twl6030_state[newstate]);
		di->state = newstate;
		power_supply_changed(&di->bat);
		power_supply_changed(&di->usb);
	}
}
Beispiel #23
0
static irqreturn_t twl_rtc_interrupt(int irq, void *rtc)
{
	unsigned long events = 0;
	int ret = IRQ_NONE;
	int res;
	u8 rd_reg;
#ifdef WORKQUEUE_RTC
	static struct work_struct task;
#endif

#ifdef CONFIG_LOCKDEP
	/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
	 * we don't want and can't tolerate.  Although it might be
	 * friendlier not to borrow this thread context...
	 */
	local_irq_enable();
#endif

#ifdef WORKQUEUE_RTC
printk("twl_rtc_interrupt rtc ");
rtc_ins.rtc =(int)rtc ;
INIT_WORK(&task, rtc_interrupt_bottom_half);

 queue_work(omap_rtc_wq, &task);
#endif

#ifndef WORKQUEUE_RTC

	res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
	if (res)
		goto out;
	/*
	 * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
	 * only one (ALARM or RTC) interrupt source may be enabled
	 * at time, we also could check our results
	 * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
	 */
	if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
		events |= RTC_IRQF | RTC_AF;
	else
		events |= RTC_IRQF | RTC_UF;

	res = twl_rtc_write_u8(rd_reg | BIT_RTC_STATUS_REG_ALARM_M,
				   REG_RTC_STATUS_REG);
	if (res)
		goto out;

	if (twl_class_is_4030()) {
		/* Clear on Read enabled. RTC_IT bit of TWL4030_INT_PWR_ISR1
		 * needs 2 reads to clear the interrupt. One read is done in
		 * do_twl_pwrirq(). Doing the second read, to clear
		 * the bit.
		 *
		 * FIXME the reason PWR_ISR1 needs an extra read is that
		 * RTC_IF retriggered until we cleared REG_ALARM_M above.
		 * But re-reading like this is a bad hack; by doing so we
		 * risk wrongly clearing status for some other IRQ (losing
		 * the interrupt).  Be smarter about handling RTC_UF ...
		 */
		res = twl_i2c_read_u8(TWL4030_MODULE_INT,
			&rd_reg, TWL4030_INT_PWR_ISR1);
		if (res)
			goto out;
	}

	/* Notify RTC core on event */
	rtc_update_irq(rtc, 1, events);
#endif

	ret = IRQ_HANDLED;
out:
	return ret;
}
Beispiel #24
0
// 20100920 [email protected] Refine IRQ handlder with a work queue [START_LGE]
static void pwrbutton_wq_func(struct work_struct *work){

	int err;
	u8 value;

	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS);
	if (!err)  {
#if 0  // this code is necessary for hdmi sleep sequence.
		extern int is_hdmi_enabled(void);
		if(is_hdmi_enabled())
		{
			if(!(value & PWR_PWRON_IRQ))
			{
				input_report_key(pwr, KEY_BACK, 1);
				input_sync(pwr);
				input_report_key(pwr, KEY_BACK, 0);
				input_sync(pwr);
				
				extern int WHAT_MODE_IS_IT(void);
				switch(WHAT_MODE_IS_IT()) // this code is necessary for hdmi sleep sequence from HDMI to LCD in Video mode.
				{					           // it takes at least specific time(ms) to change overlay completely.
					case 0:
						// Image gallery
						msleep(1000);
						break;
					case 1:
						// Video mode
						msleep(4000); 
						break;
					case 2:
						// Normal mode
						break;
				}
				input_report_key(pwr, KEY_POWER, 1);	
				input_sync(pwr);
				input_report_key(pwr, KEY_POWER, 0);
				input_sync(pwr);
				msleep(700);
			}
		}
		else
		{
			input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
			input_sync(pwr);
			printk( KERN_WARNING "[PWRBUTTON] pwrbutton irq has been processed! %d\n",
				(value & PWR_PWRON_IRQ));
		}

#else
		input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
		input_sync(pwr);
		printk( KERN_WARNING "[PWRBUTTON] pwrbutton irq has been processed! %d\n",
			(value & PWR_PWRON_IRQ));
#endif

		
	} else {
		dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading"
			" TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err);
		printk(KERN_WARNING "[PWRBUTTON] pwrbutton irq caused an error!\n");
	}
}
Beispiel #25
0
int twl6030_vlow_init(int vlow_irq)
{
	int status;
	u8 val;

	status = twl_i2c_read_u8(TWL_MODULE_PM_SLAVE_RES, &val,
			REG_VBATMIN_HI_CFG_STATE);
	if (status < 0) {
		pr_err("twl6030: I2C err reading REG_VBATMIN_HI_CFG_STATE: %d\n",
				status);
		return status;
	}

	status = twl_i2c_write_u8(TWL_MODULE_PM_SLAVE_RES,
			val | VBATMIN_VLOW_EN, REG_VBATMIN_HI_CFG_STATE);
	if (status < 0) {
		pr_err("twl6030: I2C err writing REG_VBATMIN_HI_CFG_STATE: %d\n",
				status);
		return status;
	}

	status = twl_i2c_read_u8(TWL_MODULE_PIH, &val, REG_INT_MSK_LINE_A);
	if (status < 0) {
		pr_err("twl6030: I2C err reading REG_INT_MSK_LINE_A: %d\n",
				status);
		return status;
	}

	status = twl_i2c_write_u8(TWL_MODULE_PIH, val & ~VLOW_INT_MASK,
			REG_INT_MSK_LINE_A);
	if (status < 0) {
		pr_err("twl6030: I2C err writing REG_INT_MSK_LINE_A: %d\n",
				status);
		return status;
	}

	status = twl_i2c_read_u8(TWL_MODULE_PIH, &val, REG_INT_MSK_STS_A);
	if (status < 0) {
		pr_err("twl6030: I2C err reading REG_INT_MSK_STS_A: %d\n",
				status);
		return status;
	}

	status = twl_i2c_write_u8(TWL_MODULE_PIH, val & ~VLOW_INT_MASK,
		REG_INT_MSK_STS_A);
	if (status < 0) {
		pr_err("twl6030: I2C err writing REG_INT_MSK_STS_A: %d\n",
				status);
		return status;
	}

	twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &vbatmin_hi_threshold,
			TWL6030_VBATMIN_HI_THRESHOLD);

	/* install an irq handler for vlow */
	status = request_threaded_irq(vlow_irq, NULL, handle_twl6030_vlow,
			IRQF_ONESHOT,
			"TWL6030-VLOW", handle_twl6030_vlow);
	if (status < 0) {
		pr_err("twl6030: could not claim vlow irq %d: %d\n", vlow_irq,
				status);
		return status;
	}

	return 0;
}
Beispiel #26
0
/*
 * Interrupt service routine
 *
 * Attends to TWL 6030 power module interruptions events, specifically
 * USB_PRES (USB charger presence) CHG_PRES (AC charger presence) events
 *
 */
static irqreturn_t twl6030charger_ctrl_interrupt(int irq, void *_di)
{
	struct twl6030_bci_device_info *di = _di;
	int ret;
	u8 stat_toggle, stat_reset, stat_set = 0;
	u8 present_charge_state = 0;
	u8 ac_or_vbus, no_ac_and_vbus;

#ifdef CONFIG_LOCKDEP
	/* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
	 * we don't want and can't tolerate.  Although it might be
	 * friendlier not to borrow this thread context...
	 */
	local_irq_enable();
#endif

	/* read charger controller_stat1 */
	ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &present_charge_state,
		CONTROLLER_STAT1);
	if (ret)
		return IRQ_NONE;

	stat_toggle = charge_state ^ present_charge_state;
	stat_set = stat_toggle & present_charge_state;
	stat_reset = stat_toggle & charge_state;

	no_ac_and_vbus = !((present_charge_state) & (VBUS_DET | VAC_DET));
	ac_or_vbus = charge_state & (VBUS_DET | VAC_DET);
	if (no_ac_and_vbus && ac_or_vbus) {
		pr_debug("No Charging source\n");
		/* disable charging when no source present */
	}

	charge_state = present_charge_state;

	if (stat_reset & VBUS_DET) {
		pr_debug("usb removed\n");
		usb_connected = 0;
		if (present_charge_state & VAC_DET)
			twl6030_start_ac_charger();

	}
	if (stat_set & VBUS_DET) {
		if ((present_charge_state & VAC_DET) && (di->vac_priority))
			pr_debug("USB charger detected, continue with VAC\n");
		else
			twl6030_start_usb_charger();
	}

	if (stat_reset & VAC_DET) {
		pr_debug("vac removed\n");
		if (present_charge_state & VBUS_DET)
			twl6030_start_usb_charger();
	}
	if (stat_set & VAC_DET) {
		if ((present_charge_state & VBUS_DET) && !(di->vac_priority))
			pr_debug("AC charger detected, continue with VBUS\n");
		else
			twl6030_start_ac_charger();
	}


	if (stat_set & CONTROLLER_STAT1_FAULT_WDG)
		pr_debug("Fault watchdog fired\n");
	if (stat_reset & CONTROLLER_STAT1_FAULT_WDG)
		pr_debug("Fault watchdog recovered\n");
	if (stat_set & CONTROLLER_STAT1_BAT_REMOVED)
		pr_debug("Battery removed\n");
	if (stat_reset & CONTROLLER_STAT1_BAT_REMOVED)
		pr_debug("Battery inserted\n");
	if (stat_set & CONTROLLER_STAT1_BAT_TEMP_OVRANGE)
		pr_debug("Battery temperature overrange\n");
	if (stat_reset & CONTROLLER_STAT1_BAT_TEMP_OVRANGE)
		pr_debug("Battery temperature within range\n");

	twl6030_bci_battery_update_status(di);
	power_supply_changed(&di->bat);

	return IRQ_HANDLED;
}
Beispiel #27
0
static irqreturn_t powerbutton_irq(int irq, void *_pwr)
{
	struct input_dev *pwr = _pwr;
	int err;
	u8 value;

	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,REG_STS_HW_CONDITIONS);
	if (!err)  {
		char buf[128];

		int press = (value & PWR_PWRON_IRQ) ? STATE_RELEASE : STATE_PRESS;

		char *action = press ? "press" : "release";

		input_report_key(pwr, KEY_POWER, press);
		input_sync(pwr);

		sprintf(buf, "%s:powi%c:action=%s:", __func__, action[0], action);

		log_to_metrics(ANDROID_LOG_INFO, "PowerKeyEvent", buf);

		strcat(buf, "\n");
		printk(buf);


		if(press != prev_press) {
			if(press) {
				prev_press = STATE_PRESS;

			} else {
				prev_press = STATE_RELEASE;

				/* Check if we are connected to USB */
				if (!twl_i2c_read_u8(TWL6030_MODULE_CHARGER,
						&value, 0x03) && !(value & (1 << 2))) {

					/*
					 * No USB, hold a partial wakelock,
					 * scheduled a work 2 seconds later
					 * to switch off the LED
					 */
					wake_lock_timeout(&pwrbutton_wakelock, 3*HZ);
					cancel_delayed_work_sync(&pwrbutton_work);
					omap4430_orange_led_set(NULL, 0);
					omap4430_green_led_set(NULL, 255);

					schedule_delayed_work(&pwrbutton_work,
						HZ*2);
				}
			}
		}else{
			if(g_in_suspend==1){
					wake_lock(&pwrbutton_wakelock);
					input_report_key(pwr, KEY_POWER, 1);
					input_report_key(pwr, KEY_POWER, 0);
					input_sync(pwr);
					omap4430_orange_led_set(NULL, 0);
					omap4430_green_led_set(NULL, 255);
					schedule_delayed_work(&pwrbutton_work,
						msecs_to_jiffies(2000));
			}
		}
	} else {
		dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading"
			" TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err);

                /* If an error occurs we don't want to display the SysReq the next time user will
                 * push and release power button.
                 */
                prev_press = STATE_UNKNOWN;
	}

	return IRQ_HANDLED;
}
Beispiel #28
0
static int __init twl6030_bci_battery_probe(struct platform_device *pdev)
{
	struct twl6030_bci_platform_data *pdata = pdev->dev.platform_data;
	struct twl6030_bci_device_info *di;
	int irq;
	int ret;
	u8 rd_reg = 0, controller_stat = 0;

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di)
		return -ENOMEM;

	if (!pdata) {
		dev_dbg(&pdev->dev, "platform_data not available\n");
		ret = -EINVAL;
		goto err_pdata;
	}

	di->dev = &pdev->dev;
	di->bat.name = "twl6030_bci_battery";
	di->bat.supplied_to = twl6030_bci_supplied_to;
	di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to);
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = twl6030_bci_battery_props;
	di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props);
	di->bat.get_property = twl6030_bci_battery_get_property;
	di->bat.external_power_changed =
			twl6030_bci_battery_external_power_changed;

	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;

	di->bk_bat.name = "twl6030_bci_bk_battery";
	di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bk_bat.properties = twl6030_bk_bci_battery_props;
	di->bk_bat.num_properties = ARRAY_SIZE(twl6030_bk_bci_battery_props);
	di->bk_bat.get_property = twl6030_bk_bci_battery_get_property;
	di->bk_bat.external_power_changed = NULL;

	/*
	 * Android expects a battery type POWER_SUPPLY_TYPE_USB
	 * as a usb charger battery. This battery
	 * and its "online" property are used to determine if the
	 * usb cable is plugged in or not.
	 */
	di->usb_bat.name = "twl6030_bci_usb_battery";
	di->usb_bat.supplied_to = twl6030_bci_supplied_to;
	di->usb_bat.type = POWER_SUPPLY_TYPE_USB;
	di->usb_bat.properties = twl6030_usb_battery_props;
	di->usb_bat.num_properties = ARRAY_SIZE(twl6030_usb_battery_props);
	di->usb_bat.get_property = twl6030_usb_battery_get_property;
	di->usb_bat.external_power_changed = NULL;

	di->vac_priority = 1;
	platform_set_drvdata(pdev, di);

	/* settings for temperature sensing */
	ret = twl6030battery_temp_setup();
	if (ret)
		goto temp_setup_fail;

	/* request charger fault interruption */
	irq = platform_get_irq(pdev, 1);
	ret = request_irq(irq, twl6030charger_fault_interrupt,
		0, "twl_bci_fault", di);
	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto batt_irq_fail;
	}

	/* request charger ctrl interruption */
	irq = platform_get_irq(pdev, 0);
	ret = request_irq(irq, twl6030charger_ctrl_interrupt,
		0, "twl_bci_ctrl", di);

	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto chg_irq_fail;
	}

	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
						REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
						REG_INT_MSK_STS_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK,
						REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK,
						REG_INT_MSK_STS_C);

	ret = power_supply_register(&pdev->dev, &di->bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register main battery\n");
		goto batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bci_monitor_work,
				twl6030_bci_battery_work);
	schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);

	ret = power_supply_register(&pdev->dev, &di->bk_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register backup battery\n");
		goto bk_batt_failed;
	}

	ret = power_supply_register(&pdev->dev, &di->usb_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register usb source\n");
		goto usb_batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bk_bci_monitor_work,
				twl6030_bk_bci_battery_work);
	schedule_delayed_work(&di->twl6030_bk_bci_monitor_work, 500);

	twl_i2c_read_u8(TWL6030_MODULE_ID0, &rd_reg, REG_MISC1);
	rd_reg = rd_reg | VAC_MEAS | VBAT_MEAS | BB_MEAS;
	twl_i2c_write_u8(TWL6030_MODULE_ID0, rd_reg, REG_MISC1);

	twl_i2c_read_u8(TWL6030_MODULE_ID1, &rd_reg, REG_TOGGLE1);
	rd_reg = rd_reg | ENABLE_FUELGUAGE;
	twl_i2c_write_u8(TWL6030_MODULE_ID1, rd_reg, REG_TOGGLE1);

	twl_i2c_read_u8(TWL_MODULE_MADC, &rd_reg, TWL6030_GPADC_CTRL);
	rd_reg = rd_reg | ENABLE_ISOURCE;
	twl_i2c_write_u8(TWL_MODULE_MADC, rd_reg, TWL6030_GPADC_CTRL);

	twl_i2c_read_u8(TWL_MODULE_USB, &rd_reg, REG_USB_VBUS_CTRL_SET);
	rd_reg = rd_reg | VBUS_MEAS;
	twl_i2c_write_u8(TWL_MODULE_USB, rd_reg, REG_USB_VBUS_CTRL_SET);

	twl_i2c_read_u8(TWL_MODULE_USB, &rd_reg, REG_USB_ID_CTRL_SET);
	rd_reg = rd_reg | ID_MEAS;
	twl_i2c_write_u8(TWL_MODULE_USB, rd_reg, REG_USB_ID_CTRL_SET);

	/* initialize for USB charging */
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MBAT_TEMP,
						CONTROLLER_INT_MASK);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MASK_MCHARGERUSB_THMREG,
						CHARGERUSB_INT_MASK);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_VOREG_4P2,
						CHARGERUSB_VOREG);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_VICHRG_1500,
						CHARGERUSB_VICHRG);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CTRL2_VITERM_100,
						CHARGERUSB_CTRL2);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CIN_LIMIT_NONE,
						CHARGERUSB_CINLIMIT);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CTRLLIMIT2_1500,
					CHARGERUSB_CTRLLIMIT2);

	twl_i2c_write_u8(TWL6030_MODULE_BQ, 0xa0, REG_SAFETY_LIMIT);

	twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &controller_stat,
		CONTROLLER_STAT1);

	if (controller_stat & VBUS_DET)
		twl6030_start_usb_charger();

	if (controller_stat & VAC_DET)
		twl6030_start_ac_charger();

	return 0;

usb_batt_failed:
	power_supply_unregister(&di->bk_bat);
bk_batt_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	free_irq(irq, di);
chg_irq_fail:
	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);
err_pdata:
batt_irq_fail:
temp_setup_fail:
	kfree(di);

	return ret;
}
Beispiel #29
0
static void twl6030charger_fault_work_handler(struct work_struct *work)
{
	struct charger_device_info *di = container_of(work,
						      struct charger_device_info,
						      twl6030charger_fault_work.work);

	int charger_fault = 0;
	int ret;

	u8 usb_charge_sts = 0, usb_charge_sts1 = 0, usb_charge_sts2 = 0;

	ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &usb_charge_sts,
						CHARGERUSB_INT_STATUS);
	ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &usb_charge_sts1,
						CHARGERUSB_STATUS_INT1);
	ret = twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &usb_charge_sts2,
						CHARGERUSB_STATUS_INT2);

	di->status_int1 = usb_charge_sts1;
	di->status_int2 = usb_charge_sts2;
	if (usb_charge_sts & CURRENT_TERM_INT)
		dev_dbg(di->dev, "USB CURRENT_TERM_INT\n");
	if (usb_charge_sts & CHARGERUSB_THMREG)
		dev_dbg(di->dev, "USB CHARGERUSB_THMREG\n");
	if (usb_charge_sts & CHARGERUSB_FAULT)
		dev_dbg(di->dev, "USB CHARGERUSB_FAULT\n");

	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_TMREG)
		dev_dbg(di->dev, "USB CHARGER Thermal regulation activated\n");
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_NO_BAT)
		dev_dbg(di->dev, "No Battery Present\n");
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_BST_OCP)
		dev_dbg(di->dev, "USB CHARGER Boost Over current protection\n");
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_TH_SHUTD) {
//		charger_fault = 1;
		dev_dbg(di->dev, "USB CHARGER Thermal Shutdown\n");
	}
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_BAT_OVP)
		dev_dbg(di->dev, "USB CHARGER Bat Over Voltage Protection\n");
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_POOR_SRC)
		dev_dbg(di->dev, "USB CHARGER Poor input source\n");
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_SLP_MODE)
		dev_dbg(di->dev, "USB CHARGER Sleep mode\n");
	if (usb_charge_sts1 & CHARGERUSB_STATUS_INT1_VBUS_OVP)
		dev_dbg(di->dev, "USB CHARGER VBUS over voltage\n");

	if (usb_charge_sts2 & CHARGE_DONE) 
		dev_dbg(di->dev, "CHARGE DONE\n");

	if (usb_charge_sts2 & CURRENT_TERM){
//		change_charge_status(POWER_SUPPLY_STATUS_FULL_END);
		dev_dbg(di->dev, "[TA] Charge FULL\n");
	}
	
	if (usb_charge_sts2 & ICCLOOP)
		dev_dbg(di->dev, "USB ICCLOOP\n");
	if (usb_charge_sts2 & ANTICOLLAPSE)
		dev_dbg(di->dev, "USB ANTICOLLAPSE\n");

	if (charger_fault) {
		change_charge_status(POWER_SUPPLY_STATUS_NOT_CHARGING);
		dev_err(di->dev, "Charger Fault stop charging\n");
	}
	dev_dbg(di->dev, "Charger fault detected STS, INT1, INT2 %x %x %x\n",
	    usb_charge_sts, usb_charge_sts1, usb_charge_sts2);

}
void twl4030_pm_restart(char mode, const char *cmd)
{
    u8 val;
    int err;
    int i = 0;

#if defined(CONFIG_AP2MODEM_VIATELECOM)
    extern void ap_poweroff_modem(void);
    ap_poweroff_modem( );
#endif

    /* Clear the STARTON_VBAT and STARTON_SWBUG
      * STARTON_VBAT will cause the auto reboot if battery insert;
      * STARTON_SWBUG will cause the auto reboot if watchdog has been expired
      * Mark the STARTON_PWON, which enable switch on transition if power on has been pressed
      */
    twl4030_enable_write();
    for(i=0; i<3; i++){
        err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
        			  PWR_CFG_P1_TRANSITION + i);
        if (err) {
            printk(KERN_WARNING "I2C error %d while writing TWL4030 PM_MASTER PWR_CFG_P%d_TRANSITION\n", err, i+1);
            goto fail;
        }

        val &= (~(STARTON_VBAT));
        val |= STARTON_PWON | STARTON_SWBUG |STARTON_RTC | STARTON_CHG;

        err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
        			   PWR_CFG_P1_TRANSITION + i);
        if (err) {
            printk(KERN_WARNING "I2C error %d while writing TWL4030 PM_MASTER PWR_CFG_P%d_TRANSITION\n", err, i+1);
            goto fail;
        }
    }
    twl4030_disable_write();

    err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, SETUP_DONE_BCK, PWR_STS_BOOT);
    if(err){
        printk("I2C error %d while writing TWL4030 PM_MASTER PWR_STS_BOOT\n", err);
        goto fail;
    }

    printk(KERN_WARNING "Restart the system...\n");

    /*fire the watchdog*/
    val = WATCHDOG_FIRE;
    err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val,
        			   WATCHDOG_CFG);
    if (err) {
        printk(KERN_WARNING "I2C error %d while writing TWL4030 PM_MASTER PWR_CFG_P%d_TRANSITION\n", err, i+1);
        goto fail ;
    }    
    
    return;
    
fail:
    printk(KERN_ERR "Fail to restart the system.\n");
    while(1) ;
    
}