diff options
| -rw-r--r-- | arch/arm/configs/omap3_h1_defconfig | 1 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.c | 317 | ||||
| -rw-r--r-- | drivers/power/bq27x00_battery.c | 119 | ||||
| -rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/staging/Makefile | 1 | ||||
| -rw-r--r-- | drivers/staging/triune/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/staging/triune/Makefile | 5 | ||||
| -rw-r--r-- | drivers/staging/triune/ts81001.c | 194 | ||||
| -rw-r--r-- | drivers/staging/triune/ts81001.h | 57 | ||||
| -rw-r--r-- | include/linux/power/bq27x00_battery.h | 18 | 
10 files changed, 564 insertions, 154 deletions
| diff --git a/arch/arm/configs/omap3_h1_defconfig b/arch/arm/configs/omap3_h1_defconfig index dfdbde194de..8a80eaf9278 100644 --- a/arch/arm/configs/omap3_h1_defconfig +++ b/arch/arm/configs/omap3_h1_defconfig @@ -2378,6 +2378,7 @@ CONFIG_ION=y  # CONFIG_WIMAX_GDM72XX is not set  # CONFIG_CED1401 is not set  # CONFIG_DGRP is not set +CONFIG_OLIO_TS81001=y  CONFIG_CLKDEV_LOOKUP=y  CONFIG_HAVE_CLK_PREPARE=y  CONFIG_COMMON_CLK=y diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c index 84dde6d63b0..14a0008d0b9 100644 --- a/arch/arm/mach-omap2/board-omap3h1.c +++ b/arch/arm/mach-omap2/board-omap3h1.c @@ -56,7 +56,7 @@  #include <linux/of_irq.h>  #include <linux/of_platform.h> - +#include <linux/power/bq27x00_battery.h>  #include "common.h"  #include "omap_device.h" @@ -170,7 +170,7 @@ static struct omap_dss_device omap3h1_lcd_device = {  };  static struct omap_dss_device *omap3h1_dss_devices[] = { -		&omap3h1_lcd_device, +	&omap3h1_lcd_device,  };  static struct omap_dss_board_info omap3h1_dss_data = { @@ -191,9 +191,9 @@ static struct spi_board_info omap3h1_spi_board_info[] __initdata = {  };  static int __init omap3h1_spi_init(void) { -    spi_register_board_info(omap3h1_spi_board_info, -                            ARRAY_SIZE(omap3h1_spi_board_info)); -    return 0; +	spi_register_board_info(omap3h1_spi_board_info, +				ARRAY_SIZE(omap3h1_spi_board_info)); +	return 0;  } @@ -210,11 +210,16 @@ static struct mpu_platform_data mpu_data = {  	.int_config  = 0x00,  	.level_shifter = 1,  	.orientation = {  0, -1,  0, -					 -1,  0,  0, -					  0,  0,  1 }, +			  -1,  0,  0, +			  0,  0,  1 },  };  #endif + +static struct bq27x00_platform_data bq_platform_data = { +	.charger_name = "3-0049", +}; +  static struct lm3530_platform_data omap3h1_backlight_platform_data = {  	.mode = LM3530_BL_MODE_SIMPLE_MANUAL,  	//.als_input_mode = LM3530_INPUT_ALS1, @@ -232,11 +237,9 @@ static struct lm3530_platform_data omap3h1_backlight_platform_data = {  	.pwm_gpio = BACKLIGHT_PWM_GPIO,  }; - -  static struct mxt_platform_data mxt_data = { -    .irqflags	= IRQF_TRIGGER_FALLING, -    .suspend_mode = MXT_SUSPEND_DEEP_SLEEP +	.irqflags	= IRQF_TRIGGER_FALLING, +	.suspend_mode = MXT_SUSPEND_DEEP_SLEEP  };  @@ -246,10 +249,11 @@ static struct platform_device bcm20702_bluetooth_device = {  };  static struct platform_device omap3h1_dmic_codec = { -		.name = "dmic-codec", -		.id = -1, +	.name = "dmic-codec", +	.id = -1,  }; +  /* --------------------------------------------------------------------------- */  /* USB settings    */ @@ -263,18 +267,18 @@ static struct omap_musb_board_data musb_board_data = {  };  static struct nop_usb_xceiv_platform_data nop_plat_data = { -   .type     = USB_PHY_TYPE_USB2, -   .clk_rate = 60000000, /* 60 MHz */ -   .needs_vcc = 1, -   .needs_reset = 0, +	.type     = USB_PHY_TYPE_USB2, +	.clk_rate = 60000000, /* 60 MHz */ +	.needs_vcc = 1, +	.needs_reset = 0,  };  static struct platform_device nop_phy_device = { -  .name = "nop_usb_xceiv", -  .id   = -1, -  .dev  = { -      .platform_data = &nop_plat_data, -  }, +	.name = "nop_usb_xceiv", +	.id   = -1, +	.dev  = { +		.platform_data = &nop_plat_data, +	},  }; @@ -289,124 +293,132 @@ static struct platform_device nop_phy_device = {  static struct i2c_board_info __initdata omap3h1_i2c1_board_info[] = { -         { -         }, +	{ +	},  #if defined (CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV)  };  static struct i2c_board_info __initdata omap3h1_i2c2_board_info[] = {  #endif -    { +	{  #ifdef CONFIG_MACH_OMAP3_H1_PV2 -        I2C_BOARD_INFO("lsm6ds3", 0x6a), +		I2C_BOARD_INFO("lsm6ds3", 0x6a),  #else -        I2C_BOARD_INFO("mpu6515", 0x68), -        .platform_data = &mpu_data, +		I2C_BOARD_INFO("mpu6515", 0x68), +		.platform_data = &mpu_data,  #endif -    }, -    {  -        /* Backlight */ -        I2C_BOARD_INFO("lm3530-led", 0x38), -        .platform_data = &omap3h1_backlight_platform_data, -    }, -    { -        I2C_BOARD_INFO("mXT224", 0x4a), -        .platform_data = &mxt_data, -    }, -    { -        I2C_BOARD_INFO("cm3391", 0x10), -    }, +	}, +	{ +		/* Backlight */ +		I2C_BOARD_INFO("lm3530-led", 0x38), +		.platform_data = &omap3h1_backlight_platform_data, +	}, +	{ +		I2C_BOARD_INFO("mXT224", 0x4a), +		.platform_data = &mxt_data, +	}, +	{ +		I2C_BOARD_INFO("cm3391", 0x10), +	},  #ifdef CONFIG_MACH_OMAP3_H1_EVT1  };  static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = {  #endif -    { -        I2C_BOARD_INFO("bq274xx", 0x55), -    }, +	{ +		I2C_BOARD_INFO("bq274xx", 0x55), +		.platform_data = &bq_platform_data, +	},  }; +#ifdef CONFIG_MACH_OMAP3_H1_PV2 +static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = { +	{ +		I2C_BOARD_INFO("ts81001", 0x49), +	}, +}; +#endif  /***************************************************************************   * omap_uart data    */  /* Some notes: -		.dma_enabled	= false, -		.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE, -		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, -		.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT, -        This one sets runtime pm autosuspend timeout - -1 disables runtime -        pm (that is, pm that's done while running, not sleeping). -		.autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY, ( -1 or X ms. ) +   .dma_enabled	= false, +   .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE, +   .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, +   .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT, +   This one sets runtime pm autosuspend timeout - -1 disables runtime +   pm (that is, pm that's done while running, not sleeping). +   .autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY, ( -1 or X ms. ) -        Wakelock timeout: If there's an interrupt on the serial port, this is  -        how long we expect to wait before the system is functional. -        .wakelock_timeout - for minnow, this is 150 (BT) or 50 (M4 debug). -              Can be left out. +   Wakelock timeout: If there's an interrupt on the serial port, this is +   how long we expect to wait before the system is functional. +   .wakelock_timeout - for minnow, this is 150 (BT) or 50 (M4 debug). +   Can be left out. -        .DTR_* -> can be left out. I can't find anyone using it. +   .DTR_* -> can be left out. I can't find anyone using it. -        int			    DTR_gpio; -        int			    DTR_inverted; -        int			    DTR_present; -        bool			wakeup_capable; +   int			    DTR_gpio; +   int			    DTR_inverted; +   int			    DTR_present; +   bool			wakeup_capable; -        bool			open_close_pm; - Minnow uses this for c55 only -        unsigned int	rx_trig;  Minnow, BT & debug only +   bool			open_close_pm; - Minnow uses this for c55 only +   unsigned int	rx_trig;  Minnow, BT & debug only -        The flags field is not used (it's hardcoded in omap_serial_init_port). +   The flags field is not used (it's hardcoded in omap_serial_init_port).  */  static struct omap_uart_port_info omap_uart_ports[] = { -    { -        .dma_enabled = false,	/* To specify DMA Mode */ -        .dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, -        .dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, -        .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, -        .autosuspend_timeout = 100, -        .wakelock_timeout = 150, -        .wake_peer = bcm_bt_lpm_exit_lpm_locked, -        .wakeup_capable = true, -        .rx_trig = 32, +	{ +		.dma_enabled = false,	/* To specify DMA Mode */ +		.dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, +		.dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, +		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, +		.autosuspend_timeout = 100, +		.wakelock_timeout = 150, +		.wake_peer = bcm_bt_lpm_exit_lpm_locked, +		.wakeup_capable = true, +		.rx_trig = 32, -        /* OLIO: make sure RTS isn't enabled before we're ready */ +		/* OLIO: make sure RTS isn't enabled before we're ready */ -        .rts_wait    = true, -        .rts_enable_fn  = rts_exit_sleep_mode, -        .rts_disable_fn = rts_enter_sleep_mode, -    }, -    { -        .dma_enabled = false,	/* To specify DMA Mode */ -        .dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, -        .dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, -        .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, -        .autosuspend_timeout = 0, -        .wakeup_capable = false, -        .rts_wait = false, -        .rts_enable_fn = NULL, -        .rts_disable_fn = NULL, -    }, -    { -        .dma_enabled = false,	/* To specify DMA Mode */ -        .dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, -        .dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, -        .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, -        .autosuspend_timeout = -1, -        .wakeup_capable = true, -        .rts_wait = false, -        .rts_enable_fn = NULL, -        .rts_disable_fn = NULL, -    }, -    { -        .dma_enabled = false,	/* To specify DMA Mode */ -        .dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, -        .dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, -        .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, -        .autosuspend_timeout = 0, -        .wakeup_capable = false, -        .rts_wait = false, -        .rts_enable_fn = NULL, -        .rts_disable_fn = NULL, -    }, +		.rts_wait    = true, +		.rts_enable_fn  = rts_exit_sleep_mode, +		.rts_disable_fn = rts_enter_sleep_mode, +	}, +	{ +		.dma_enabled = false,	/* To specify DMA Mode */ +		.dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, +		.dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, +		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, +		.autosuspend_timeout = 0, +		.wakeup_capable = false, +		.rts_wait = false, +		.rts_enable_fn = NULL, +		.rts_disable_fn = NULL, +	}, +	{ +		.dma_enabled = false,	/* To specify DMA Mode */ +		.dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, +		.dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, +		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, +		.autosuspend_timeout = -1, +		.wakeup_capable = true, +		.rts_wait = false, +		.rts_enable_fn = NULL, +		.rts_disable_fn = NULL, +	}, +	{ +		.dma_enabled = false,	/* To specify DMA Mode */ +		.dma_rx_buf_size  = DEFAULT_RXDMA_BUFSIZE, +		.dma_rx_timeout   = DEFAULT_RXDMA_TIMEOUT, +		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, +		.autosuspend_timeout = 0, +		.wakeup_capable = false, +		.rts_wait = false, +		.rts_enable_fn = NULL, +		.rts_disable_fn = NULL, +	},  }; @@ -417,76 +429,75 @@ static struct omap_uart_port_info omap_uart_ports[] = {  static int __init omap3_h1_i2c_init(void)  { -    int acc_irq; +	int acc_irq; -    /* In Linux 3.10 we need to request an IRQ through  -     * gpio_to_irq. This means it can't be set at compile time, and -     * must be done at runtime. In other words, here. -     */ +	/* In Linux 3.10 we need to request an IRQ through +	 * gpio_to_irq. This means it can't be set at compile time, and +	 * must be done at runtime. In other words, here. +	 */ -    gpio_request_one(ATMEL_MXT_GPIO, GPIOF_IN, "atmel_mxt_ts CHG"); +	gpio_request_one(ATMEL_MXT_GPIO, GPIOF_IN, "atmel_mxt_ts CHG");  	gpio_request_one(MPUIRQ_GPIO, GPIOF_IN, "Accl IRQ pin"); -    acc_irq = gpio_to_irq(MPUIRQ_GPIO); +	acc_irq = gpio_to_irq(MPUIRQ_GPIO);  #if defined (CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV)  	omap3h1_i2c2_board_info[2].irq = gpio_to_irq(ATMEL_MXT_GPIO); -    omap3h1_i2c2_board_info[0].irq = acc_irq; +	omap3h1_i2c2_board_info[0].irq = acc_irq;  #else  	omap3h1_i2c1_board_info[3].irq = gpio_to_irq(ATMEL_MXT_GPIO); -    omap3h1_i2c1_board_info[1].irq = acc_irq; +	omap3h1_i2c1_board_info[1].irq = acc_irq;  #endif  #if defined (CONFIG_MACH_OMAP3_H1_PV) -    omap3h1_i2c2_board_info[4].irq = gpio_to_irq(CHG_GPOUT); +	omap3h1_i2c2_board_info[4].irq = gpio_to_irq(CHG_GPOUT);  #endif  	gpio_request_one(USB_CS, GPIOF_OUT_INIT_HIGH, "USB on"); -    /* Register buses */ +	/* Register buses */  	// omap_register_i2c_bus(1, 400, omap3h1_i2c1_board_info, ARRAY_SIZE(omap3h1_i2c1_board_info));  #if defined (CONFIG_MACH_OMAP3_H1_DVT2) || defined (CONFIG_MACH_OMAP3_H1_PV) -	omap_register_i2c_bus(2, 400, omap3h1_i2c2_board_info, ARRAY_SIZE(omap3h1_i2c2_board_info)); +	omap_register_i2c_bus(2, 400, omap3h1_i2c2_board_info, +			      ARRAY_SIZE(omap3h1_i2c2_board_info));  #else  	omap_register_i2c_bus(2, 400, NULL, 0);  #endif -#ifdef CONFIG_MACH_OMAP3_H1_EVT1 -	omap_register_i2c_bus(3, 400, omap3h1_i2c3_board_info, ARRAY_SIZE(omap3h1_i2c3_board_info)); -#else -	omap_register_i2c_bus(3, 100, NULL, 0); -#endif +	omap_register_i2c_bus(3, 100, omap3h1_i2c3_board_info, +			      ARRAY_SIZE(omap3h1_i2c3_board_info)); +  	return 0;  }  static struct platform_device *omap3h1_devices[] __initdata = { -        &bcm20702_bluetooth_device, -        &nop_phy_device, -		&omap3h1_dmic_codec, +	&bcm20702_bluetooth_device, +	&nop_phy_device, +	&omap3h1_dmic_codec,  };  static void __init omap3_h1_init(void)  { -    /* Read what we can from the device tree */ +	/* Read what we can from the device tree */ -    of_platform_populate(NULL, omap_dt_match_table, NULL, NULL); +	of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);  #ifdef CONFIG_MACH_OMAP3_H1_PV -    /* The PV units need reversed polarity for the sysclkreq pin. */ +	/* The PV units need reversed polarity for the sysclkreq pin. */ -    omap2_prm_rmw_mod_reg_bits(OMAP3430_CLKREQ_POL_MASK, -                               0, OMAP3430_GR_MOD, -                               OMAP3_PRM_POLCTRL_OFFSET); +	omap2_prm_rmw_mod_reg_bits(OMAP3430_CLKREQ_POL_MASK, +				   0, OMAP3430_GR_MOD, +				   OMAP3_PRM_POLCTRL_OFFSET);  #endif   	board_nand_init(omap3h1_nand_partitions, -                    ARRAY_SIZE(omap3h1_nand_partitions), NAND_CS, -                    NAND_BUSWIDTH_16, NULL); +			ARRAY_SIZE(omap3h1_nand_partitions), NAND_CS, +			NAND_BUSWIDTH_16, NULL);  	omap_sdrc_init(mt29c8g96_sdrc_params, mt29c8g96_sdrc_params); -	 -    omap3_h1_i2c_init(); + +	omap3_h1_i2c_init();  	platform_add_devices(omap3h1_devices, ARRAY_SIZE(omap3h1_devices)); @@ -494,7 +505,7 @@ static void __init omap3_h1_init(void)  	omap_serial_board_init(omap_uart_ports); -    omap_display_init(&omap3h1_dss_data); +	omap_display_init(&omap3h1_dss_data);  	usb_bind_phy("musb-hdrc.0.auto", 0, "nop_usb_xceiv"); /* "tusb-usb-h1" */ @@ -507,23 +518,23 @@ static const char *omap3_h1_boards_compat[] __initdata = {  };  DT_MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 (Flattened Device Tree)") -    .atag_offset = 0x100, +.atag_offset = 0x100,  	.reserve	= omap_reserve,  	.map_io		= omap3_map_io,  	.init_early	= omap3630_init_early, -	/* .init_irq		= omap3_init_irq, */ -    .init_irq	= omap_intc_of_init, +/* .init_irq		= omap3_init_irq, */ +	.init_irq	= omap_intc_of_init,  	.handle_irq	= omap3_intc_handle_irq,  	.init_machine	= omap3_h1_init,  	.init_late	= omap3630_init_late, -    .init_time  = omap3_sync32k_timer_init, -	/* .init_time	= omap3_secure_sync32k_timer_init, */ +	.init_time  = omap3_sync32k_timer_init, +/* .init_time	= omap3_secure_sync32k_timer_init, */  	.dt_compat	= omap3_h1_boards_compat,  	.restart	= omap3xxx_restart, -MACHINE_END +	MACHINE_END  #if 0 /* removing ... for now */ -MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 Board") +	MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 Board")  	.atag_offset	= 0x100,  	.reserve		= omap_reserve,  	.map_io			= omap3_map_io, @@ -532,9 +543,9 @@ MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 Board")  	.handle_irq		= omap3_intc_handle_irq,  	.init_machine	= omap3_h1_init,  	.init_late		= omap3630_init_late, -    .init_time      = omap3_sync32k_timer_init, -	/* .init_time		= omap3_secure_sync32k_timer_init, */ -	/* .dt_compat		= omap3_h1_boards_compat, */ +	.init_time      = omap3_sync32k_timer_init, +/* .init_time		= omap3_secure_sync32k_timer_init, */ +/* .dt_compat		= omap3_h1_boards_compat, */  	.restart		= omap3xxx_restart, -MACHINE_END +	MACHINE_END  #endif diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index c10f48b20c8..8c1546b7d37 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -43,8 +43,22 @@  #include <asm/unaligned.h>  #include <linux/wakelock.h> +#include <linux/device.h>  #include <linux/power/bq27x00_battery.h> +#ifdef CONFIG_OLIO_TS81001 +#include "../staging/triune/ts81001.h" +#endif /* CONFIG_OLIO_TS81001 */ + + +#ifdef OLIODEBUG +#define do { olio_debug(format, ...) printk("OLIO %s: ", __FUNCTION__);	\ +		printk(format, ##__VA_ARGS__); } while(0) +#else +#define olio_debug(format, ...)  +#endif + +  #define DRIVER_VERSION			"1.2.0"  #define INVALID_REG_ADDR		0xFF @@ -1170,8 +1184,50 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,  	return 0;  } +#ifdef CONFIG_OLIO_TS81001 + +static int bq27x00_charger_status(struct bq27x00_device_info *di) { +	struct device * bq = di->dev; +	struct bq27x00_platform_data * pdata = bq->platform_data; +	struct ts81001 * ts81001; +	ts81001_state_t state; + +	olio_debug("entered\n"); + +	ts81001 = (struct ts81001 *) i2c_get_clientdata (pdata->charger_i2c);	 +	 +	if (ts81001 == NULL) { +		olio_debug("Couldn't find charger struct!"); +		return -EINVAL; +	} + +	olio_debug("Got client data for dev %s\n", dev_name(ts81001->dev)); + +	state = ts81001->ops->get_status(ts81001); + +	olio_debug("Got status\n");	 + +	switch (state)  +	{ +	case NOT_CHARGING: +		olio_debug("exiting, DISCHARGING\n"); +		return POWER_SUPPLY_STATUS_DISCHARGING; +	case PRECHARGE: +	case CHARGING_1C: +	case TOPOFF: +		olio_debug("exiting, CHARGING\n"); +		return POWER_SUPPLY_STATUS_CHARGING; +	default: +		olio_debug("Couldn't read status from ts81001 charger.\n"); +		olio_debug("exiting, EINVAL\n"); +		return -EINVAL; +	} +} + +#endif +  static int bq27x00_battery_status(struct bq27x00_device_info *di, -	union power_supply_propval *val) +				  union power_supply_propval *val)  {  	int status; @@ -1187,10 +1243,15 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,  	} else {  		if (di->cache.flags & BQ27XXX_FLAG_FC)  			status = POWER_SUPPLY_STATUS_FULL; +#ifdef CONFIG_OLIO_TS81001 +		else  +			status = bq27x00_charger_status (di); +#else  		else if (di->cache.flags & BQ27XXX_FLAG_DSC)  			status = POWER_SUPPLY_STATUS_DISCHARGING;  		else  			status = POWER_SUPPLY_STATUS_CHARGING; +#endif /* CONFIG_OLIO_TS81001 */  	}  	val->intval = status; @@ -1681,15 +1742,67 @@ static const struct attribute_group bq27x00_attr_group = {  	.attrs = bq27x00_attributes,  }; +#ifdef CONFIG_OLIO_TS81001 + +/*************************************************************************** + * bq27x00_set_platform_data - act on basic platform data + *  + * We get the name of the charger passed in through the platform data + * structure. Now we need to find the device that it corresponds to, and  + * it's i2c_client structure.  + *  + * Returns: + */ + +static int bq27x00_set_platform_data (struct bq27x00_platform_data * pdata) { +	int retval = 0; + +	olio_debug("entered\n"); + +	pdata->charger_device =  +		bus_find_device_by_name(&i2c_bus_type, +					NULL, +					pdata->charger_name); +	if (pdata->charger_device == NULL) { +		olio_debug("couldn't find charger device by name (name=%s)\n", +			    pdata->charger_name); +		retval = -ENXIO; +	} +	else {  /* device found */ +		pdata->charger_i2c = i2c_verify_client(pdata->charger_device); + +		if (pdata->charger_i2c == NULL) { +			olio_debug("couldn't find i2c_client for device name=%s\n", +				    pdata->charger_name); +			retval = -ENXIO; +		} +	} +	 +	olio_debug("exiting\n"); +		 +	return retval; +} + +#endif /* CONFIG_OLIO_TS81001 */ +  static int __init bq27x00_battery_probe(struct i2c_client *client,  				 const struct i2c_device_id *id)  {  	char *name;  	struct bq27x00_device_info *di; +	struct bq27x00_platform_data *pdata; +	  	int num;  	int retval = 0;  	u8 *regs; +#ifdef CONFIG_OLIO_TS81001 +	pdata = client->dev.platform_data; +	retval = bq27x00_set_platform_data (pdata); +	if (retval < 0)  +		return -EPROBE_DEFER; +#endif /* CONFIG_OLIO_TS81001 */ +  	/* Get new ID for the new battery device */  	retval = idr_pre_get(&battery_id, GFP_KERNEL);  	if (retval == 0) @@ -1988,3 +2101,7 @@ module_exit(bq27x00_battery_exit);  MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");  MODULE_DESCRIPTION("BQ27x00 battery monitor driver");  MODULE_LICENSE("GPL"); + +#ifdef OLIODEBUG +#undef OLIODEBUG +#endif diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index aefe820a800..1098075875d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -140,4 +140,6 @@ source "drivers/staging/netlogic/Kconfig"  source "drivers/staging/dwc2/Kconfig" +source "drivers/staging/triune/Kconfig" +  endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 415772ea306..10cfb01009b 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -62,3 +62,4 @@ obj-$(CONFIG_FIREWIRE_SERIAL)	+= fwserial/  obj-$(CONFIG_ZCACHE)		+= zcache/  obj-$(CONFIG_GOLDFISH)		+= goldfish/  obj-$(CONFIG_USB_DWC2)		+= dwc2/ +obj-$(CONFIG_OLIO_TS81001)	+= triune/ diff --git a/drivers/staging/triune/Kconfig b/drivers/staging/triune/Kconfig new file mode 100644 index 00000000000..c16d93dfb6b --- /dev/null +++ b/drivers/staging/triune/Kconfig @@ -0,0 +1,4 @@ +config  OLIO_TS81001 +	tristate "OLIO Triune TS81001 driver" +	---help--- +	  Simplistic driver for the TS81001 wireless charger receiver from Triune as used by Olio. diff --git a/drivers/staging/triune/Makefile b/drivers/staging/triune/Makefile new file mode 100644 index 00000000000..a0fe548534b --- /dev/null +++ b/drivers/staging/triune/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the Olio Triune charger driver +# + +obj-$(CONFIG_OLIO_TS81001) += ts81001.o diff --git a/drivers/staging/triune/ts81001.c b/drivers/staging/triune/ts81001.c new file mode 100644 index 00000000000..0562f4c9526 --- /dev/null +++ b/drivers/staging/triune/ts81001.c @@ -0,0 +1,194 @@ +/* ts81001.c - basic driver for Triune's 81001 */ + +/*  + * Triune ts81001 driver + *  + * Copyright 2015 Olio Devices + *  + * Mattis Fjallstrom (mattis@oliodevices.com) + */ + +/*  + * DESCRIPTION + * =========== + * This driver isn't strictly necessary. It provides access to some  + * of the basic functionality of the ts81001 from the linux kernel in  + * an easier way than otherwise. (The standard way would just be to  + * query the i2c bus). + * + * The plan is to also simplify updating the charger firmware ... but  + * that's not there yet. For now I'll also hardcode all the settings + * (like i2c bus address) but that may change later. + */ + +/*  + * Modification History + * ==================== + * 01a, 20150921, mfj  Created + */ + +/* Includes */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/iio/iio.h> + +#include "ts81001.h" + +/* Defines */ + +#ifdef OLIODEBUG +#define olio_debug(format, ...) printk ("OLIO %s: ", __FUNCTION__); printk (format, ##__VA_ARGS__) +#else +#define olio_debug(format, ...)  +#endif + +/* Globals */  + +const int TS81001_ADDR=0x49; +const u8  TS81001_STATUS_REG=0x10; + + +/*************************************************************************** + * Operations + */ + +static int ts81001_i2c_read (struct i2c_client * client, +			     u8 reg_addr,  +			     int len,  +			     u8 * data,  +			     bool b_lock) { +	int err = 0; +	struct i2c_msg msg[2]; + +	olio_debug (" entered\n");	 + +	msg[0].addr = client->addr; +	msg[0].flags = client->flags; +	msg[0].len = 1; +	msg[0].buf = ®_addr; + +	msg[1].addr = client->addr; +	msg[1].flags = client->flags | I2C_M_RD; +	msg[1].len = len; +	msg[1].buf = data; + +	if (b_lock) /* TODO: Add locking! */ +		err = i2c_transfer(client->adapter, msg, 2); +	else +		err = i2c_transfer(client->adapter, msg, 2); + +	olio_debug (" exiting\n"); + +	return err; +} + +/*************************************************************************** + * ts81001_get_status - get current charger state. + *  + * This function reads the status from the device on the i2c bus. The  + * ts81001 can be really slow to react, so we'll try again a few times + * before accepting failure.  + */ + +static int ts81001_get_status (struct ts81001 * ts) { +	u8 data; +	ts81001_state_t state; +	int len = 1; +	int err = 0; +	int retries = 2; +	int i; + +	olio_debug ("entered\n"); + +	for (i = 0; i < retries; i++) { +		err = ts81001_i2c_read (ts->client, TS81001_STATUS_REG, len, &data, false); +	 +		if (err <= 0) { +			olio_debug ("Error reading status from ts81001, err = %d\n", err); +			state = err; +		} else { +			state = (ts81001_state_t) data; +			break; +		} +	} + +	olio_debug ("exiting\n");	 + +	return state; +} + + +static struct ts81001_ops ts_ops = { +	.get_status = ts81001_get_status, +}; + +/*************************************************************************** + * probe + */ + + +static int ts81001_i2c_probe(struct i2c_client * client,  +			 const struct i2c_device_id * id) +{ +	struct ts81001 *ts81001; +	 +	int ret = 0; +	int chip_id = id->driver_data; + +	olio_debug("OLIO entered\n"); + +	ts81001 = kmalloc(sizeof(*ts81001), GFP_KERNEL); + +	if (!ts81001) +		return -ENOMEM; + +	ts81001->dev = &client->dev; +	ts81001->name = client->name; +	ts81001->client = client; +	ts81001->id = chip_id; + +	ts81001->ops = &ts_ops; + +	/* Fill out i2c_client struct */ + +	i2c_set_clientdata(client, ts81001); + +	olio_debug ("exiting\n"); + +	return ret; +} + +static int ts81001_i2c_remove(struct i2c_client * client) +{ +	struct ts81001 * ts = i2c_get_clientdata(client); + +	kfree (ts); + +	return 0; +} + +static const struct i2c_device_id ts81001_id_table[] = { +	{ TS81001_DEV_NAME }, +	{ }, +}; +MODULE_DEVICE_TABLE(i2c, ts81001_id_table); + +static struct i2c_driver ts81001_i2c_driver = { +	.probe = ts81001_i2c_probe, +	.remove = ts81001_i2c_remove, +	.id_table = ts81001_id_table, +	.driver = { +		.name = "ts81001", +		.owner = THIS_MODULE, +	}, +}; + +module_i2c_driver(ts81001_i2c_driver); + +MODULE_AUTHOR("Mattis Fjallstrom <mattis@oliodevice.com"); +MODULE_DESCRIPTION("Basic driver for TS81001"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/triune/ts81001.h b/drivers/staging/triune/ts81001.h new file mode 100644 index 00000000000..6d248254661 --- /dev/null +++ b/drivers/staging/triune/ts81001.h @@ -0,0 +1,57 @@ +/* + * ts81001.h - Triune ts81001 driver + * + * Copyright 2015 Olio Devices + *  + * Author: Mattis Fjallstrom + *  + *  This program is free software; you can redistribute it and/or modify it + *  under  the terms of the GNU General  Public License as published by the + *  Free Software Foundation;  either version 2 of the License, or (at your + *  option) any later version. + * + */ + +/* DESCRIPTION + * =========== + * This is the header for the Triune TS81001 driver. + */ + +/*  + * Modification History + * ==================== + * 01a, 20150921, mfj  Created + */ + +/* DEFINES */ + +#ifndef _CONFIG_TS81001_H +#define _CONFIG_TS81001_H + +#define TS81001_DEV_NAME "ts81001" + +/* INCLUDES */ + +#include <linux/regmap.h> + +typedef enum ts81001_state { +	NOT_CHARGING, +	PRECHARGE, +	CHARGING_1C, +	TOPOFF +} ts81001_state_t; + +struct ts81001 { +	struct device *dev; +	struct i2c_client *client; +	struct regmap *regmap; +	unsigned int id; +	char * name; +	struct ts81001_ops * ops; +}; + +struct ts81001_ops { +	int (*get_status) (struct ts81001 * ts); +}; + +#endif /* _CONFIG_TS81001_H */ diff --git a/include/linux/power/bq27x00_battery.h b/include/linux/power/bq27x00_battery.h index a857f719bf4..a8999e26dcc 100644 --- a/include/linux/power/bq27x00_battery.h +++ b/include/linux/power/bq27x00_battery.h @@ -16,4 +16,22 @@ struct bq27000_platform_data {  	int (*read)(struct device *dev, unsigned int);  }; +/** + * struct bq27x00_plaform_data - Platform data for bq27000 devices + * @charger_ops: Access functions for the charger + *      Some information can't be deduced and needs to be retrieved + *      directly from the charger. For example, if the device is  + *      running at full speed it may use more power than the charger + *      can provide and a net outflow from the battery will be the + *      result. With access to the charger the battery can still tell  + *      that it's on the charger (important information in certain  + *      circumstances). + */ +struct bq27x00_platform_data { +	const char * charger_name; +	struct device * charger_device; +	struct i2c_client * charger_i2c; +}; + +  #endif |