BigW Consortium Gitlab

Commit 1f32707e by David Clark

Merge branch 'master' of ssh://github.com/mangOH/mangOH

parents 9e531c86 b35a81c5
......@@ -6,14 +6,10 @@ cflags:
sources:
{
mangoh_module.c
board_green_dv4.c
board_red_dv2.c
board_red_dv3.c
board_red_dv4.c
mangoh_green.c
}
params:
{
board = "green dv4"
revision = "dv4"
}
......@@ -6,14 +6,10 @@ cflags:
sources:
{
mangoh_module.c
board_green_dv4.c
board_red_dv2.c
board_red_dv3.c
board_red_dv4.c
mangoh_red.c
}
params:
{
board = "red dv2"
revision = "dv2"
}
......@@ -6,14 +6,10 @@ cflags:
sources:
{
mangoh_module.c
board_green_dv4.c
board_red_dv2.c
board_red_dv3.c
board_red_dv4.c
mangoh_red.c
}
params:
{
board = "red dv3"
revision = "dv3"
}
......@@ -6,14 +6,10 @@ cflags:
sources:
{
mangoh_module.c
board_green_dv4.c
board_red_dv2.c
board_red_dv3.c
board_red_dv4.c
mangoh_red.c
}
params:
{
board = "red dv4"
revision = "dv4"
}
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include "mangoh.h"
#include "lsm6ds3_platform_data.h"
/*
*-----------------------------------------------------------------------------
* Type definitions
*-----------------------------------------------------------------------------
*/
struct green_dv4_platform_data {
struct i2c_client* i2c_switch;
struct i2c_client* accelerometer;
};
struct green_dv4_device
{
struct platform_device pdev;
struct green_dv4_platform_data pdata;
};
/*
*-----------------------------------------------------------------------------
* Function declarations
*-----------------------------------------------------------------------------
*/
static int green_dv4_map(struct platform_device *pdev);
static int green_dv4_unmap(struct platform_device* pdev);
static void green_dv4_release_device(struct device* dev);
/*
*-----------------------------------------------------------------------------
* Constants
*-----------------------------------------------------------------------------
*/
#define GREEN_DV4_I2C_SW_BASE_ADAPTER_ID (1)
#define GREEN_DV4_I2C_SW_PORT_IOT0 (0)
#define GREEN_DV4_I2C_SW_PORT_IOT1 (1)
#define GREEN_DV4_I2C_SW_PORT_IOT2 (2)
#define GREEN_DV4_I2C_SW_PORT_USB_HUB (3)
#define GREEN_DV4_I2C_SW_PORT_GPIO_EXPANDER1 (4)
#define GREEN_DV4_I2C_SW_PORT_GPIO_EXPANDER2 (5)
#define GREEN_DV4_I2C_SW_PORT_GPIO_EXPANDER3 (6)
#define GREEN_DV4_I2C_SW_PORT_BATTERY_CHARGER (7)
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
const struct mangoh_descriptor green_dv4_descriptor = {
.type = "mangoh green dv4",
.map = green_dv4_map,
.unmap = green_dv4_unmap,
};
static struct pca954x_platform_mode green_dv4_pca954x_adap_modes[] = {
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 0, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 1, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 2, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 3, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 4, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 5, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 6, .deselect_on_exit=1, .class=0},
{.adap_id=GREEN_DV4_I2C_SW_BASE_ADAPTER_ID + 7, .deselect_on_exit=1, .class=0},
};
static struct pca954x_platform_data green_dv4_pca954x_pdata = {
green_dv4_pca954x_adap_modes,
ARRAY_SIZE(green_dv4_pca954x_adap_modes),
};
static const struct i2c_board_info green_dv4_pca954x_device_info = {
I2C_BOARD_INFO("pca9548", 0x71),
.platform_data = &green_dv4_pca954x_pdata,
};
static struct lsm6ds3_platform_data green_dv4_accelerometer_platform_data = {
.drdy_int_pin = 1,
};
static struct i2c_board_info green_dv4_accelerometer_devinfo = {
I2C_BOARD_INFO("lsm6ds3", 0x6A),
.platform_data = &green_dv4_accelerometer_platform_data,
};
static const char platform_device_name[] = "mangoh green dv4";
/*
*-----------------------------------------------------------------------------
* Public function definitions
*-----------------------------------------------------------------------------
*/
int green_dv4_create_device(struct platform_device** d)
{
struct green_dv4_device *dv4 = kzalloc(sizeof(struct green_dv4_device), GFP_KERNEL);
if (!dv4)
return -ENOMEM;
dv4->pdev.name = platform_device_name;
dv4->pdev.id = -1;
dv4->pdev.dev.platform_data = &dv4->pdata;
dv4->pdev.dev.release = green_dv4_release_device;
*d = &dv4->pdev;
return 0;
}
/*
*-----------------------------------------------------------------------------
* Static function definitions
*-----------------------------------------------------------------------------
*/
static int green_dv4_map(struct platform_device *pdev)
{
struct green_dv4_platform_data* pdata = dev_get_platdata(&pdev->dev);
/* Get the main i2c adapter */
struct i2c_adapter* adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "Failed to get I2C adapter 0.\n");
return -ENODEV;
}
/* Map the I2C switch */
dev_dbg(&pdev->dev, "mapping i2c switch\n");
pdata->i2c_switch = i2c_new_device(adapter, &green_dv4_pca954x_device_info);
if (!pdata->i2c_switch) {
dev_err(
&pdev->dev,
"Failed to register %s\n",
green_dv4_pca954x_device_info.type);
return -ENODEV;
}
/* Map the I2C LSM6DS3 accelerometer */
dev_dbg(&pdev->dev, "mapping lsm6ds3 accelerometer\n");
/* Pin 10 of gpio expander 2 is connected to INT2 of the lsm6ds3 */
/* Can't use the irq because the GPIO expander isn't controlled by a kernel driver
green_dv4_accelerometer_devinfo.irq =
gpio_to_irq(get_sx150x_gpio_base(pdata->gpio_expander2) + 10);
*/
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", GREEN_DV4_I2C_SW_BASE_ADAPTER_ID);
return -ENODEV;
}
pdata->accelerometer = i2c_new_device(adapter, &green_dv4_accelerometer_devinfo);
if (!pdata->accelerometer) {
dev_err(&pdev->dev, "Accelerometer is missing\n");
return -ENODEV;
}
/*
* TODO:
* SX1509 GPIO expanders: 0x3E, 0x3F, 0x70
* There is a driver in the WP85 kernel, but the gpiolib
* infrastructure of the WP85 kernel does not allow the expander
* GPIOs to be used in sysfs due to a hardcoded translation table.
* 3503 USB Hub: 0x08
* Looks like there is a driver in the wp85 kernel source at drivers/usb/misc/usb3503.c
* I'm not really sure what benefit is achieved through using this driver.
* Battery Gauge: 0x55
* chip is BQ27621YZFR-G1A which is supported by this driver which is
* in the mainline linux kernel as
* drivers/power/supply/bq27xxx_battery*. Unfortunately, the power
* supply API has changed, so using this driver would require
* substantial backporting.
* http://www.ti.com/tool/bq27xxxsw-linux
* Buck & Battery Charger: 0x6B
* chip is BQ24192IRGER. I haven't been able to find a linux kernel
* driver, but this looks like some relevant code:
* https://chromium.googlesource.com/chromiumos/platform/ec/+/master/driver/charger/bq24192.c
*/
return 0;
}
static int green_dv4_unmap(struct platform_device* pdev)
{
struct green_dv4_platform_data* pdata = dev_get_platdata(&pdev->dev);
i2c_unregister_device(pdata->accelerometer);
i2c_put_adapter(pdata->accelerometer->adapter);
i2c_unregister_device(pdata->i2c_switch);
i2c_put_adapter(pdata->i2c_switch->adapter);
return 0;
}
static void green_dv4_release_device(struct device* dev)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
struct green_dv4_device *dv4 = container_of(pdev, struct green_dv4_device, pdev);
kfree(dv4);
}
#ifndef BOARD_GREEN_DV4_H
#define BOARD_GREEN_DV4_H
#include "mangoh.h"
extern const struct mangoh_descriptor green_dv4_descriptor;
int green_dv4_create_device(struct platform_device** d);
#endif // BOARD_GREEN_DV4_H
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include "mangoh.h"
#include "lsm6ds3_platform_data.h"
/*
*-----------------------------------------------------------------------------
* Type definitions
*-----------------------------------------------------------------------------
*/
struct red_dv2_platform_data {
struct i2c_client* i2c_switch;
struct i2c_client* accelerometer;
struct i2c_client* pressure;
};
struct red_dv2_device
{
struct platform_device pdev;
struct red_dv2_platform_data pdata;
};
/*
*-----------------------------------------------------------------------------
* Function declarations
*-----------------------------------------------------------------------------
*/
static int red_dv2_map(struct platform_device *pdev);
static int red_dv2_unmap(struct platform_device* pdev);
static void red_dv2_release_device(struct device* dev);
/*
*-----------------------------------------------------------------------------
* Constants
*-----------------------------------------------------------------------------
*/
#define RED_DV2_I2C_SW_BASE_ADAPTER_ID (1)
#define RED_DV2_I2C_SW_PORT_IOT0 (0)
#define RED_DV2_I2C_SW_PORT_BATTERY_CHARGER (1)
#define RED_DV2_I2C_SW_PORT_USB_HUB (1)
#define RED_DV2_I2C_SW_PORT_GPIO_EXPANDER (2)
#define RED_DV2_I2C_SW_PORT_EXP (3) /* expansion header */
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
const struct mangoh_descriptor red_dv2_descriptor = {
.type = "mangoh red dv2",
.map = red_dv2_map,
.unmap = red_dv2_unmap,
};
static struct pca954x_platform_mode red_dv2_pca954x_adap_modes[] = {
{.adap_id=RED_DV2_I2C_SW_BASE_ADAPTER_ID + 0, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV2_I2C_SW_BASE_ADAPTER_ID + 1, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV2_I2C_SW_BASE_ADAPTER_ID + 2, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV2_I2C_SW_BASE_ADAPTER_ID + 3, .deselect_on_exit=1, .class=0},
};
static struct pca954x_platform_data red_dv2_pca954x_pdata = {
red_dv2_pca954x_adap_modes,
ARRAY_SIZE(red_dv2_pca954x_adap_modes),
};
static const struct i2c_board_info red_dv2_pca954x_device_info = {
I2C_BOARD_INFO("pca9546", 0x71),
.platform_data = &red_dv2_pca954x_pdata,
};
static struct lsm6ds3_platform_data red_dv2_accelerometer_platform_data = {
.drdy_int_pin = 1,
};
static struct i2c_board_info red_dv2_accelerometer_devinfo = {
I2C_BOARD_INFO("lsm6ds3", 0x6A),
.platform_data = &red_dv2_accelerometer_platform_data,
};
static struct i2c_board_info red_dv2_pressure_devinfo = {
I2C_BOARD_INFO("bmp280", 0x76),
};
static const char platform_device_name[] = "mangoh red dv2";
/*
*-----------------------------------------------------------------------------
* Public function definitions
*-----------------------------------------------------------------------------
*/
int red_dv2_create_device(struct platform_device** d)
{
struct red_dv2_device *dv2 = kzalloc(sizeof(struct red_dv2_device), GFP_KERNEL);
if (!dv2)
return -ENOMEM;
dv2->pdev.name = platform_device_name;
dv2->pdev.id = -1;
dv2->pdev.dev.platform_data = &dv2->pdata;
dv2->pdev.dev.release = red_dv2_release_device;
*d = &dv2->pdev;
return 0;
}
/*
*-----------------------------------------------------------------------------
* Static function definitions
*-----------------------------------------------------------------------------
*/
static int red_dv2_map(struct platform_device *pdev)
{
struct red_dv2_platform_data* pdata = dev_get_platdata(&pdev->dev);
/* Get the main i2c adapter */
struct i2c_adapter* adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "Failed to get I2C adapter 0.\n");
return -ENODEV;
}
/* Map the I2C switch */
dev_dbg(&pdev->dev, "mapping i2c switch\n");
pdata->i2c_switch = i2c_new_device(adapter, &red_dv2_pca954x_device_info);
if (!pdata->i2c_switch) {
dev_err(
&pdev->dev,
"Failed to register %s\n",
red_dv2_pca954x_device_info.type);
return -ENODEV;
}
/* Map the I2C LSM6DS3 accelerometer */
dev_dbg(&pdev->dev, "mapping lsm6ds3 accelerometer\n");
/* Pin 12 of the gpio expander is connected to INT2 of the lsm6ds3 */
/* Can't use the irq because the GPIO expander isn't controlled by a kernel driver
red_dv2_accelerometer_devinfo.irq =
gpio_to_irq(get_sx150x_gpio_base(pdata->gpio_expander) + 12);
*/
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", RED_DV2_I2C_SW_BASE_ADAPTER_ID);
return -ENODEV;
}
pdata->accelerometer = i2c_new_device(adapter, &red_dv2_accelerometer_devinfo);
if (!pdata->accelerometer) {
dev_err(&pdev->dev, "Accelerometer is missing\n");
return -ENODEV;
}
/* Map the I2C BMP280 pressure sensor */
dev_dbg(&pdev->dev, "mapping bmp280 pressure sensor\n");
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", RED_DV2_I2C_SW_BASE_ADAPTER_ID);
return -ENODEV;
}
pdata->pressure = i2c_new_device(adapter, &red_dv2_pressure_devinfo);
if (!pdata->pressure) {
dev_err(&pdev->dev, "Pressure sensor is missing\n");
return -ENODEV;
}
/*
* TODO:
* SX1509 GPIO expander: 0x3E
* There is a driver in the WP85 kernel, but the gpiolib
* infrastructure of the WP85 kernel does not allow the expander
* GPIOs to be used in sysfs due to a hardcoded translation table.
* 3503 USB Hub: 0x08
* Looks like there is a driver in the wp85 kernel source at drivers/usb/misc/usb3503.c
* I'm not really sure what benefit is achieved through using this driver.
* Battery Gauge: 0x64
* chip is LTC2942 which is made by linear technologies (now Analog
* Devices). There is a kernel driver in the linux-power-supply
* repository in the for-next branch.
* Buck & Battery Charger: 0x6B
* chip is BQ24296RGER
*/
return 0;
}
static int red_dv2_unmap(struct platform_device* pdev)
{
struct red_dv2_platform_data* pdata = dev_get_platdata(&pdev->dev);
i2c_unregister_device(pdata->pressure);
i2c_put_adapter(pdata->pressure->adapter);
i2c_unregister_device(pdata->accelerometer);
i2c_put_adapter(pdata->accelerometer->adapter);
i2c_unregister_device(pdata->i2c_switch);
i2c_put_adapter(pdata->i2c_switch->adapter);
return 0;
}
static void red_dv2_release_device(struct device* dev)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
struct red_dv2_device *dv2 = container_of(pdev, struct red_dv2_device, pdev);
kfree(dv2);
}
#ifndef BOARD_RED_DV2_H
#define BOARD_RED_DV2_H
#include "mangoh.h"
extern const struct mangoh_descriptor red_dv2_descriptor;
int red_dv2_create_device(struct platform_device** d);
#endif // BOARD_RED_DV2_H
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include "mangoh.h"
#include "lsm6ds3_platform_data.h"
/*
*-----------------------------------------------------------------------------
* Type definitions
*-----------------------------------------------------------------------------
*/
struct red_dv3_platform_data {
struct i2c_client* i2c_switch;
struct i2c_client* accelerometer;
struct i2c_client* pressure;
};
struct red_dv3_device
{
struct platform_device pdev;
struct red_dv3_platform_data pdata;
};
/*
*-----------------------------------------------------------------------------
* Function declarations
*-----------------------------------------------------------------------------
*/
static int red_dv3_map(struct platform_device *pdev);
static int red_dv3_unmap(struct platform_device* pdev);
static void red_dv3_release_device(struct device* dev);
/*
*-----------------------------------------------------------------------------
* Constants
*-----------------------------------------------------------------------------
*/
#define RED_DV3_I2C_SW_BASE_ADAPTER_ID (1)
#define RED_DV3_I2C_SW_PORT_IOT0 (0)
#define RED_DV3_I2C_SW_PORT_BATTERY_CHARGER (1)
#define RED_DV3_I2C_SW_PORT_USB_HUB (1)
#define RED_DV3_I2C_SW_PORT_GPIO_EXPANDER (2)
#define RED_DV3_I2C_SW_PORT_EXP (3) /* expansion header */
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
const struct mangoh_descriptor red_dv3_descriptor = {
.type = "mangoh red dv3",
.map = red_dv3_map,
.unmap = red_dv3_unmap,
};
static struct pca954x_platform_mode red_dv3_pca954x_adap_modes[] = {
{.adap_id=RED_DV3_I2C_SW_BASE_ADAPTER_ID + 0, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV3_I2C_SW_BASE_ADAPTER_ID + 1, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV3_I2C_SW_BASE_ADAPTER_ID + 2, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV3_I2C_SW_BASE_ADAPTER_ID + 3, .deselect_on_exit=1, .class=0},
};
static struct pca954x_platform_data red_dv3_pca954x_pdata = {
red_dv3_pca954x_adap_modes,
ARRAY_SIZE(red_dv3_pca954x_adap_modes),
};
static const struct i2c_board_info red_dv3_pca954x_device_info = {
I2C_BOARD_INFO("pca9546", 0x71),
.platform_data = &red_dv3_pca954x_pdata,
};
static struct i2c_board_info red_dv3_accelerometer_devinfo = {
I2C_BOARD_INFO("bmi160", 0x68),
};
static struct i2c_board_info red_dv3_pressure_devinfo = {
I2C_BOARD_INFO("bmp280", 0x76),
};
static const char platform_device_name[] = "mangoh red dv3";
/*
*-----------------------------------------------------------------------------
* Public function definitions
*-----------------------------------------------------------------------------
*/
int red_dv3_create_device(struct platform_device** d)
{
struct red_dv3_device *dv3 = kzalloc(sizeof(struct red_dv3_device), GFP_KERNEL);
if (!dv3)
return -ENOMEM;
dv3->pdev.name = platform_device_name;
dv3->pdev.id = -1;
dv3->pdev.dev.platform_data = &dv3->pdata;
dv3->pdev.dev.release = red_dv3_release_device;
*d = &dv3->pdev;
return 0;
}
/*
*-----------------------------------------------------------------------------
* Static function definitions
*-----------------------------------------------------------------------------
*/
static int red_dv3_map(struct platform_device *pdev)
{
struct red_dv3_platform_data* pdata = dev_get_platdata(&pdev->dev);
/* Get the main i2c adapter */
struct i2c_adapter* adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "Failed to get I2C adapter 0.\n");
return -ENODEV;
}
/* Map the I2C switch */
dev_dbg(&pdev->dev, "mapping i2c switch\n");
pdata->i2c_switch = i2c_new_device(adapter, &red_dv3_pca954x_device_info);
if (!pdata->i2c_switch) {
dev_err(
&pdev->dev,
"Failed to register %s\n",
red_dv3_pca954x_device_info.type);
return -ENODEV;
}
/* Map the I2C BMI160 accelerometer */
dev_dbg(&pdev->dev, "mapping bmi160 accelerometer\n");
/*
* Pins 11 and 12 of the gpio expander are connected to bmi160's INT1
* and INT2 pins respectively. It does not appear that the bmi160 driver
* makes use of these interrupt pins.
*/
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
pdata->accelerometer = i2c_new_device(adapter, &red_dv3_accelerometer_devinfo);
if (!pdata->accelerometer) {
dev_err(&pdev->dev, "Accelerometer is missing\n");
return -ENODEV;
}
/* Map the I2C BMP280 pressure sensor */
dev_dbg(&pdev->dev, "mapping bmp280 pressure sensor\n");
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
pdata->pressure = i2c_new_device(adapter, &red_dv3_pressure_devinfo);
if (!pdata->pressure) {
dev_err(&pdev->dev, "Pressure sensor is missing\n");
return -ENODEV;
}
/*
* TODO:
* 3503 USB Hub: 0x08
* Looks like there is a driver in the wp85 kernel source at drivers/usb/misc/usb3503.c
* I'm not really sure what benefit is achieved through using this driver.
* Buck & Battery Charger: 0x6B
* chip is BQ24296RGER
*/
return 0;
}
static int red_dv3_unmap(struct platform_device* pdev)
{
struct red_dv3_platform_data* pdata = dev_get_platdata(&pdev->dev);
i2c_unregister_device(pdata->pressure);
i2c_put_adapter(pdata->pressure->adapter);
i2c_unregister_device(pdata->accelerometer);
i2c_put_adapter(pdata->accelerometer->adapter);
i2c_unregister_device(pdata->i2c_switch);
i2c_put_adapter(pdata->i2c_switch->adapter);
return 0;
}
static void red_dv3_release_device(struct device* dev)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
struct red_dv3_device *dv3 = container_of(pdev, struct red_dv3_device, pdev);
kfree(dv3);
}
#ifndef BOARD_RED_DV3_H
#define BOARD_RED_DV3_H
#include "mangoh.h"
extern const struct mangoh_descriptor red_dv3_descriptor;
int red_dv3_create_device(struct platform_device** d);
#endif // BOARD_RED_DV3_H
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include "mangoh.h"
#include "lsm6ds3_platform_data.h"
/*
*-----------------------------------------------------------------------------
* Type definitions
*-----------------------------------------------------------------------------
*/
struct red_dv4_platform_data {
struct i2c_client* i2c_switch;
struct i2c_client* accelerometer;
struct i2c_client* pressure;
};
struct red_dv4_device
{
struct platform_device pdev;
struct red_dv4_platform_data pdata;
};
/*
*-----------------------------------------------------------------------------
* Function declarations
*-----------------------------------------------------------------------------
*/
static int red_dv4_map(struct platform_device *pdev);
static int red_dv4_unmap(struct platform_device* pdev);
static void red_dv4_release_device(struct device* dev);
/*
*-----------------------------------------------------------------------------
* Constants
*-----------------------------------------------------------------------------
*/
#define RED_DV4_I2C_SW_BASE_ADAPTER_ID (1)
#define RED_DV4_I2C_SW_PORT_IOT0 (0)
#define RED_DV4_I2C_SW_PORT_BATTERY_CHARGER (1)
#define RED_DV4_I2C_SW_PORT_USB_HUB (1)
#define RED_DV4_I2C_SW_PORT_GPIO_EXPANDER (2)
#define RED_DV4_I2C_SW_PORT_EXP (3) /* expansion header */
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
const struct mangoh_descriptor red_dv4_descriptor = {
.type = "mangoh red dv4",
.map = red_dv4_map,
.unmap = red_dv4_unmap,
};
static struct pca954x_platform_mode red_dv4_pca954x_adap_modes[] = {
{.adap_id=RED_DV4_I2C_SW_BASE_ADAPTER_ID + 0, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV4_I2C_SW_BASE_ADAPTER_ID + 1, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV4_I2C_SW_BASE_ADAPTER_ID + 2, .deselect_on_exit=1, .class=0},
{.adap_id=RED_DV4_I2C_SW_BASE_ADAPTER_ID + 3, .deselect_on_exit=1, .class=0},
};
static struct pca954x_platform_data red_dv4_pca954x_pdata = {
red_dv4_pca954x_adap_modes,
ARRAY_SIZE(red_dv4_pca954x_adap_modes),
};
static const struct i2c_board_info red_dv4_pca954x_device_info = {
I2C_BOARD_INFO("pca9546", 0x71),
.platform_data = &red_dv4_pca954x_pdata,
};
static struct i2c_board_info red_dv4_accelerometer_devinfo = {
I2C_BOARD_INFO("bmi160", 0x68),
};
static struct i2c_board_info red_dv4_pressure_devinfo = {
I2C_BOARD_INFO("bmp280", 0x76),
};
static const char platform_device_name[] = "mangoh red dv4";
/*
*-----------------------------------------------------------------------------
* Public function definitions
*-----------------------------------------------------------------------------
*/
int red_dv4_create_device(struct platform_device** d)
{
struct red_dv4_device *dv4 = kzalloc(sizeof(struct red_dv4_device), GFP_KERNEL);
if (!dv4)
return -ENOMEM;
dv4->pdev.name = platform_device_name;
dv4->pdev.id = -1;
dv4->pdev.dev.platform_data = &dv4->pdata;
dv4->pdev.dev.release = red_dv4_release_device;
*d = &dv4->pdev;
return 0;
}
/*
*-----------------------------------------------------------------------------
* Static function definitions
*-----------------------------------------------------------------------------
*/
static int red_dv4_map(struct platform_device *pdev)
{
struct red_dv4_platform_data* pdata = dev_get_platdata(&pdev->dev);
/* Get the main i2c adapter */
struct i2c_adapter* adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "Failed to get I2C adapter 0.\n");
return -ENODEV;
}
/* Map the I2C switch */
dev_dbg(&pdev->dev, "mapping i2c switch\n");
pdata->i2c_switch = i2c_new_device(adapter, &red_dv4_pca954x_device_info);
if (!pdata->i2c_switch) {
dev_err(
&pdev->dev,
"Failed to register %s\n",
red_dv4_pca954x_device_info.type);
return -ENODEV;
}
/* Map the I2C BMI160 accelerometer */
dev_dbg(&pdev->dev, "mapping bmi160 accelerometer\n");
/*
* Pins 11 and 12 of the gpio expander are connected to bmi160's INT1
* and INT2 pins respectively. It does not appear that the bmi160 driver
* makes use of these interrupt pins.
*/
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
pdata->accelerometer = i2c_new_device(adapter, &red_dv4_accelerometer_devinfo);
if (!pdata->accelerometer) {
dev_err(&pdev->dev, "Accelerometer is missing\n");
return -ENODEV;
}
/* Map the I2C BMP280 pressure sensor */
dev_dbg(&pdev->dev, "mapping bmp280 pressure sensor\n");
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
pdata->pressure = i2c_new_device(adapter, &red_dv4_pressure_devinfo);
if (!pdata->pressure) {
dev_err(&pdev->dev, "Pressure sensor is missing\n");
return -ENODEV;
}
/*
* TODO:
* 3503 USB Hub: 0x08
* Looks like there is a driver in the wp85 kernel source at drivers/usb/misc/usb3503.c
* I'm not really sure what benefit is achieved through using this driver.
* Battery Gauge: 0x64
* chip is LTC2942 which is made by linear technologies (now Analog
* Devices). There is a kernel driver in the linux-power-supply
* repository in the for-next branch.
* Buck & Battery Charger: 0x6B
* chip is BQ24296RGER
*/
return 0;
}
static int red_dv4_unmap(struct platform_device* pdev)
{
struct red_dv4_platform_data* pdata = dev_get_platdata(&pdev->dev);
i2c_unregister_device(pdata->pressure);
i2c_put_adapter(pdata->pressure->adapter);
i2c_unregister_device(pdata->accelerometer);
i2c_put_adapter(pdata->accelerometer->adapter);
i2c_unregister_device(pdata->i2c_switch);
i2c_put_adapter(pdata->i2c_switch->adapter);
return 0;
}
static void red_dv4_release_device(struct device* dev)
{
struct platform_device *pdev = container_of(dev, struct platform_device, dev);
struct red_dv4_device *dv4 = container_of(pdev, struct red_dv4_device, pdev);
kfree(dv4);
}
#ifndef BOARD_RED_DV4_H
#define BOARD_RED_DV4_H
#include "mangoh.h"
extern const struct mangoh_descriptor red_dv4_descriptor;
int red_dv4_create_device(struct platform_device** d);
#endif // BOARD_RED_DV4_H
#ifndef MANGOH_H
#define MANGOH_H
int mangoh_find_contiguous_irqs(unsigned int num_required, unsigned long irq_flags);
struct mangoh_descriptor {
char* type; // TODO: why is this needed?
int (*map)(struct platform_device* pdev);
int (*unmap)(struct platform_device* pdev);
};
#endif // MANGOH_H
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include <linux/delay.h>
#include "lsm6ds3_platform_data.h"
/*
*-----------------------------------------------------------------------------
* Constants
*-----------------------------------------------------------------------------
*/
#define MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID (1)
#define MANGOH_GREEN_I2C_SW_PORT_IOT0 (0)
#define MANGOH_GREEN_I2C_SW_PORT_IOT1 (1)
#define MANGOH_GREEN_I2C_SW_PORT_IOT2 (2)
#define MANGOH_GREEN_I2C_SW_PORT_USB_HUB (3)
#define MANGOH_GREEN_I2C_SW_PORT_GPIO_EXPANDER1 (4)
#define MANGOH_GREEN_I2C_SW_PORT_GPIO_EXPANDER2 (5)
#define MANGOH_GREEN_I2C_SW_PORT_GPIO_EXPANDER3 (6)
#define MANGOH_GREEN_I2C_SW_PORT_BATTERY_CHARGER (7)
/*
*-----------------------------------------------------------------------------
* Types
*-----------------------------------------------------------------------------
*/
enum mangoh_green_board_rev {
MANGOH_GREEN_BOARD_REV_DV4,
};
/*
*-----------------------------------------------------------------------------
* Static Function Declarations
*-----------------------------------------------------------------------------
*/
static void mangoh_green_release(struct device* dev);
static int mangoh_green_probe(struct platform_device* pdev);
static int mangoh_green_remove(struct platform_device* pdev);
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
static char *revision_dv4 = "dv4";
static char *revision = "dv4";
module_param(revision, charp, S_IRUGO);
MODULE_PARM_DESC(revision, "mangOH Green board revision");
static struct platform_driver mangoh_green_driver = {
.probe = mangoh_green_probe,
.remove = mangoh_green_remove,
.driver = {
.name = "mangoh green",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
},
};
static struct mangoh_green_platform_data {
enum mangoh_green_board_rev board_rev;
} mangoh_green_pdata;
static struct mangoh_green_driver_data {
struct i2c_client* i2c_switch;
struct i2c_client* accelerometer;
} mangoh_green_driver_data;
static struct platform_device mangoh_green_device = {
.name = "mangoh green",
.id = -1,
.dev = {
.release = mangoh_green_release,
.platform_data = &mangoh_green_pdata,
},
};
static struct pca954x_platform_mode mangoh_green_pca954x_adap_modes[] = {
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 0, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 1, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 2, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 3, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 4, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 5, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 6, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_GREEN_I2C_SW_BASE_ADAPTER_ID + 7, .deselect_on_exit=1, .class=0},
};
static struct pca954x_platform_data mangoh_green_pca954x_pdata = {
mangoh_green_pca954x_adap_modes,
ARRAY_SIZE(mangoh_green_pca954x_adap_modes),
};
static const struct i2c_board_info mangoh_green_pca954x_device_info = {
I2C_BOARD_INFO("pca9548", 0x71),
.platform_data = &mangoh_green_pca954x_pdata,
};
static struct lsm6ds3_platform_data mangoh_green_lsm6ds3_platform_data = {
.drdy_int_pin = 1,
};
static struct i2c_board_info mangoh_green_lsm6ds3_devinfo = {
I2C_BOARD_INFO("lsm6ds3", 0x6A),
.platform_data = &mangoh_green_lsm6ds3_platform_data,
};
static void mangoh_green_release(struct device* dev)
{
/* Nothing alloc'd, so nothign to free */
}
static int mangoh_green_probe(struct platform_device* pdev)
{
dev_info(&pdev->dev, "In the probe\n");
/*
* This is a workaround of questionable validity for USB issues first
* seen on the mangOH Green.
*/
msleep(5000);
/* TODO: seems pointless */
platform_set_drvdata(pdev, &mangoh_green_driver_data);
/* Get the main i2c adapter */
struct i2c_adapter* adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "Failed to get I2C adapter 0.\n");
return -ENODEV;
}
/* Map the I2C switch */
dev_dbg(&pdev->dev, "mapping i2c switch\n");
mangoh_green_driver_data.i2c_switch = i2c_new_device(adapter, &mangoh_green_pca954x_device_info);
if (!mangoh_green_driver_data.i2c_switch) {
dev_err(
&pdev->dev,
"Failed to register %s\n",
mangoh_green_pca954x_device_info.type);
return -ENODEV;
}
/* Map the accelerometer */
dev_dbg(&pdev->dev, "mapping bmi160 accelerometer\n");
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
mangoh_green_driver_data.accelerometer = i2c_new_device(adapter, &mangoh_green_lsm6ds3_devinfo);
if (!mangoh_green_driver_data.accelerometer) {
dev_err(&pdev->dev, "Accelerometer is missing\n");
return -ENODEV;
}
/*
* TODO:
* SX1509 GPIO expanders: 0x3E, 0x3F, 0x70
* There is a driver in the WP85 kernel, but the gpiolib
* infrastructure of the WP85 kernel does not allow the expander
* GPIOs to be used in sysfs due to a hardcoded translation table.
* 3503 USB Hub: 0x08
* Looks like there is a driver in the wp85 kernel source at drivers/usb/misc/usb3503.c
* I'm not really sure what benefit is achieved through using this driver.
* Battery Gauge: 0x55
* chip is BQ27621YZFR-G1A which is supported by this driver which is
* in the mainline linux kernel as
* drivers/power/supply/bq27xxx_battery*. Unfortunately, the power
* supply API has changed, so using this driver would require
* substantial backporting.
* http://www.ti.com/tool/bq27xxxsw-linux
* Buck & Battery Charger: 0x6B
* chip is BQ24192IRGER. I haven't been able to find a linux kernel
* driver, but this looks like some relevant code:
* https://chromium.googlesource.com/chromiumos/platform/ec/+/master/driver/charger/bq24192.c
*/
return 0;
}
static int mangoh_green_remove(struct platform_device* pdev)
{
dev_info(&pdev->dev, "In the remove\n");
i2c_unregister_device(mangoh_green_driver_data.accelerometer);
i2c_put_adapter(mangoh_green_driver_data.accelerometer->adapter);
i2c_unregister_device(mangoh_green_driver_data.i2c_switch);
i2c_put_adapter(mangoh_green_driver_data.i2c_switch->adapter);
return 0;
}
static int __init mangoh_green_init(void)
{
platform_driver_register(&mangoh_green_driver);
printk(KERN_DEBUG "mangoh: registered platform driver\n");
if (strcmp(revision, revision_dv4) == 0) {
mangoh_green_pdata.board_rev = MANGOH_GREEN_BOARD_REV_DV4;
} else {
pr_err(
"%s: Unsupported mangOH Red board revision (%s)\n",
__func__,
revision);
return -ENODEV; /* TODO: better value? */
}
if (platform_device_register(&mangoh_green_device)) {
platform_driver_unregister(&mangoh_green_driver);
return -ENODEV;
}
return 0;
}
static void __exit mangoh_green_exit(void)
{
platform_device_unregister(&mangoh_green_device);
platform_driver_unregister(&mangoh_green_driver);
}
module_init(mangoh_green_init);
module_exit(mangoh_green_exit);
MODULE_ALIAS(PLATFORM_MODULE_PREFIX "mangoh red");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sierra Wireless");
MODULE_DESCRIPTION("Add devices on mangOH Red hardware board");
MODULE_VERSION("1.0");
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/delay.h>
#include "mangoh.h"
#include "board_green_dv4.h"
#include "board_red_dv2.h"
#include "board_red_dv3.h"
#include "board_red_dv4.h"
/*
*-----------------------------------------------------------------------------
* Type definitions
*-----------------------------------------------------------------------------
*/
/*
*-----------------------------------------------------------------------------
* Function declarations
*-----------------------------------------------------------------------------
*/
static int mangoh_probe(struct platform_device* pdev);
static int mangoh_remove(struct platform_device* pdev);
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
/* Module parameter definitions */
static char *board = "green dv4";
module_param(board, charp, S_IRUGO);
MODULE_PARM_DESC(revision, "mangOH hardware board model and revision");
static struct platform_device* mangoh_device;
static const struct platform_device_id mangoh_ids[] = {
{.name="mangoh green dv4", .driver_data=(kernel_ulong_t)&green_dv4_descriptor},
{.name="mangoh red dv2", .driver_data=(kernel_ulong_t)&red_dv2_descriptor},
{.name="mangoh red dv3", .driver_data=(kernel_ulong_t)&red_dv3_descriptor},
{.name="mangoh red dv4", .driver_data=(kernel_ulong_t)&red_dv4_descriptor},
{},
};
MODULE_DEVICE_TABLE(platform, mangoh_ids);
static struct platform_driver mangoh_driver = {
.probe = mangoh_probe,
.remove = mangoh_remove,
.driver = {
.name = "mangoh",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
},
.id_table = mangoh_ids,
};
/*
*-----------------------------------------------------------------------------
* Function definitions
*-----------------------------------------------------------------------------
*/
static int __init mangoh_init(void)
{
if (strcmp(board, "green dv4") == 0) {
int rc = green_dv4_create_device(&mangoh_device);
if (rc != 0) {
pr_err(
"%s: Couldn't create device for '%s'.\n",
__func__,
board);
return rc;
}
} else if (strcmp(board, "red dv2") == 0) {
int rc = red_dv2_create_device(&mangoh_device);
if (rc != 0) {
pr_err(
"%s: Couldn't create device for '%s'.\n",
__func__,
board);
return rc;
}
} else if (strcmp(board, "red dv3") == 0) {
int rc = red_dv3_create_device(&mangoh_device);
if (rc != 0) {
pr_err(
"%s: Couldn't create device for '%s'.\n",
__func__,
board);
return rc;
}
} else if (strcmp(board, "red dv4") == 0) {
int rc = red_dv4_create_device(&mangoh_device);
if (rc != 0) {
pr_err(
"%s: Couldn't create device for '%s'.\n",
__func__,
board);
return rc;
}
} else {
pr_err(
"%s: unsupported board '%s'.\n",
__func__,
board);
return -ENODEV;
}
printk(KERN_INFO "mangoh: created device for board %s\n", board);
platform_driver_register(&mangoh_driver);
printk(KERN_DEBUG "mangoh: registered platform driver\n");
if (platform_device_register(mangoh_device)) {
platform_driver_unregister(&mangoh_driver);
return -ENODEV;
}
printk(KERN_DEBUG "mangoh: registered platform device\n");
return 0;
}
static void __exit mangoh_exit(void)
{
if (mangoh_device != NULL)
platform_device_unregister(mangoh_device);
platform_driver_unregister(&mangoh_driver);
}
static int mangoh_probe(struct platform_device* pdev)
{
struct mangoh_descriptor* desc =
(struct mangoh_descriptor*)
platform_get_device_id(pdev)->driver_data;
platform_set_drvdata(pdev, desc);
/* Work around USB issues at boot time by delaying device installation */
dev_info(&pdev->dev, "Probing mangOH platform device\n");
msleep(5000);
return desc->map(pdev);
}
static int mangoh_remove(struct platform_device* pdev)
{
struct mangoh_descriptor* desc = platform_get_drvdata(pdev);
const int res = desc->unmap(pdev);
dev_info(&pdev->dev, res ? "Removal failed.\n" : "Removed.\n");
return res;
}
module_init(mangoh_init);
module_exit(mangoh_exit);
MODULE_ALIAS(PLATFORM_MODULE_PREFIX "mangoh");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sierra Wireless");
MODULE_DESCRIPTION("Add devices on mangOH hardware boards");
MODULE_VERSION("1.0");
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include <linux/delay.h>
#include "lsm6ds3_platform_data.h"
/*
*-----------------------------------------------------------------------------
* Constants
*-----------------------------------------------------------------------------
*/
#define MANGOH_RED_I2C_SW_BASE_ADAPTER_ID (1)
#define MANGOH_RED_I2C_SW_PORT_IOT0 (0)
#define MANGOH_RED_I2C_SW_PORT_BATTERY_CHARGER (1)
#define MANGOH_RED_I2C_SW_PORT_USB_HUB (1)
#define MANGOH_RED_I2C_SW_PORT_GPIO_EXPANDER (2)
#define MANGOH_RED_I2C_SW_PORT_EXP (3) /* expansion header */
/*
*-----------------------------------------------------------------------------
* Types
*-----------------------------------------------------------------------------
*/
enum mangoh_red_board_rev {
MANGOH_RED_BOARD_REV_DV2,
MANGOH_RED_BOARD_REV_DV3,
MANGOH_RED_BOARD_REV_DV4,
};
/*
*-----------------------------------------------------------------------------
* Static Function Declarations
*-----------------------------------------------------------------------------
*/
static void mangoh_red_release(struct device* dev);
static int mangoh_red_probe(struct platform_device* pdev);
static int mangoh_red_remove(struct platform_device* pdev);
/*
*-----------------------------------------------------------------------------
* Variables
*-----------------------------------------------------------------------------
*/
static char *revision_dv2 = "dv2";
static char *revision_dv3 = "dv3";
static char *revision_dv4 = "dv4";
static char *revision = "dv4";
module_param(revision, charp, S_IRUGO);
MODULE_PARM_DESC(revision, "mangOH Red board revision");
static struct platform_driver mangoh_red_driver = {
.probe = mangoh_red_probe,
.remove = mangoh_red_remove,
.driver = {
.name = "mangoh red",
.owner = THIS_MODULE,
.bus = &platform_bus_type,
},
};
static struct mangoh_red_platform_data {
enum mangoh_red_board_rev board_rev;
} mangoh_red_pdata;
static struct mangoh_red_driver_data {
struct i2c_client* i2c_switch;
struct i2c_client* accelerometer;
struct i2c_client* pressure;
} mangoh_red_driver_data;
static struct platform_device mangoh_red_device = {
.name = "mangoh red",
.id = -1,
.dev = {
.release = mangoh_red_release,
.platform_data = &mangoh_red_pdata,
},
};
static struct pca954x_platform_mode mangoh_red_pca954x_adap_modes[] = {
{.adap_id=MANGOH_RED_I2C_SW_BASE_ADAPTER_ID + 0, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_RED_I2C_SW_BASE_ADAPTER_ID + 1, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_RED_I2C_SW_BASE_ADAPTER_ID + 2, .deselect_on_exit=1, .class=0},
{.adap_id=MANGOH_RED_I2C_SW_BASE_ADAPTER_ID + 3, .deselect_on_exit=1, .class=0},
};
static struct pca954x_platform_data mangoh_red_pca954x_pdata = {
mangoh_red_pca954x_adap_modes,
ARRAY_SIZE(mangoh_red_pca954x_adap_modes),
};
static const struct i2c_board_info mangoh_red_pca954x_device_info = {
I2C_BOARD_INFO("pca9546", 0x71),
.platform_data = &mangoh_red_pca954x_pdata,
};
static struct i2c_board_info mangoh_red_bmi160_devinfo = {
I2C_BOARD_INFO("bmi160", 0x68),
};
static struct lsm6ds3_platform_data mangoh_red_lsm6ds3_platform_data = {
.drdy_int_pin = 1,
};
static struct i2c_board_info mangoh_red_lsm6ds3_devinfo = {
I2C_BOARD_INFO("lsm6ds3", 0x6A),
.platform_data = &mangoh_red_lsm6ds3_platform_data,
};
static struct i2c_board_info mangoh_red_pressure_devinfo = {
I2C_BOARD_INFO("bmp280", 0x76),
};
static void mangoh_red_release(struct device* dev)
{
/* Nothing alloc'd, so nothign to free */
}
static int mangoh_red_probe(struct platform_device* pdev)
{
dev_info(&pdev->dev, "In the probe\n");
/*
* This is a workaround of questionable validity for USB issues first
* seen on the mangOH Green.
*/
msleep(5000);
/* TODO: seems pointless */
platform_set_drvdata(pdev, &mangoh_red_driver_data);
/* Get the main i2c adapter */
struct i2c_adapter* adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "Failed to get I2C adapter 0.\n");
return -ENODEV;
}
/* Map the I2C switch */
dev_dbg(&pdev->dev, "mapping i2c switch\n");
mangoh_red_driver_data.i2c_switch =
i2c_new_device(adapter, &mangoh_red_pca954x_device_info);
if (!mangoh_red_driver_data.i2c_switch) {
dev_err(
&pdev->dev,
"Failed to register %s\n",
mangoh_red_pca954x_device_info.type);
return -ENODEV;
}
/* Map the accelerometer */
dev_dbg(&pdev->dev, "mapping accelerometer\n");
/*
* Pins 11 and 12 of the gpio expander are connected to bmi160's INT1
* and INT2 pins respectively. It does not appear that the bmi160 driver
* makes use of these interrupt pins.
*/
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
struct i2c_board_info *accelerometer_board_info =
mangoh_red_pdata.board_rev == MANGOH_RED_BOARD_REV_DV2 ?
&mangoh_red_lsm6ds3_devinfo : &mangoh_red_bmi160_devinfo;
mangoh_red_driver_data.accelerometer =
i2c_new_device(adapter, accelerometer_board_info);
if (!mangoh_red_driver_data.accelerometer) {
dev_err(&pdev->dev, "Accelerometer is missing\n");
return -ENODEV;
}
/* Map the I2C BMP280 pressure sensor */
dev_dbg(&pdev->dev, "mapping bmp280 pressure sensor\n");
adapter = i2c_get_adapter(0);
if (!adapter) {
dev_err(&pdev->dev, "No I2C bus %d.\n", 0);
return -ENODEV;
}
mangoh_red_driver_data.pressure =
i2c_new_device(adapter, &mangoh_red_pressure_devinfo);
if (!mangoh_red_driver_data.pressure) {
dev_err(&pdev->dev, "Pressure sensor is missing\n");
return -ENODEV;
}
if (mangoh_red_pdata.board_rev != MANGOH_RED_BOARD_REV_DV3) {
/*
* TODO:
* SX1509 GPIO expanders: 0x3E
* There is a driver in the WP85 kernel, but the gpiolib
* infrastructure of the WP85 kernel does not allow the
* expander GPIOs to be used in sysfs due to a hardcoded
* translation table.
* Battery Gauge: 0x64
* chip is LTC2942 which is made by linear technologies (now
* Analog Devices). There is a kernel driver in the
* linux-power-supply repository in the for-next branch.
*/
}
/*
* TODO:
* 3503 USB Hub: 0x08
* Looks like there is a driver in the wp85 kernel source at drivers/usb/misc/usb3503.c
* I'm not really sure what benefit is achieved through using this driver.
* Buck & Battery Charger: 0x6B
* chip is BQ24296RGER
*/
return 0;
}
static int mangoh_red_remove(struct platform_device* pdev)
{
dev_info(&pdev->dev, "In the remove\n");
i2c_unregister_device(mangoh_red_driver_data.pressure);
i2c_put_adapter(mangoh_red_driver_data.pressure->adapter);
i2c_unregister_device(mangoh_red_driver_data.accelerometer);
i2c_put_adapter(mangoh_red_driver_data.accelerometer->adapter);
i2c_unregister_device(mangoh_red_driver_data.i2c_switch);
i2c_put_adapter(mangoh_red_driver_data.i2c_switch->adapter);
return 0;
}
static int __init mangoh_red_init(void)
{
platform_driver_register(&mangoh_red_driver);
printk(KERN_DEBUG "mangoh: registered platform driver\n");
if (strcmp(revision, revision_dv2) == 0) {
mangoh_red_pdata.board_rev = MANGOH_RED_BOARD_REV_DV2;
} else if (strcmp(revision, revision_dv3) == 0) {
mangoh_red_pdata.board_rev = MANGOH_RED_BOARD_REV_DV3;
} else if (strcmp(revision, revision_dv4) == 0) {
mangoh_red_pdata.board_rev = MANGOH_RED_BOARD_REV_DV4;
} else {
pr_err(
"%s: Unsupported mangOH Red board revision (%s)\n",
__func__,
revision);
return -ENODEV; /* TODO: better value? */
}
if (platform_device_register(&mangoh_red_device)) {
platform_driver_unregister(&mangoh_red_driver);
return -ENODEV;
}
return 0;
}
static void __exit mangoh_red_exit(void)
{
platform_device_unregister(&mangoh_red_device);
platform_driver_unregister(&mangoh_red_driver);
}
module_init(mangoh_red_init);
module_exit(mangoh_red_exit);
MODULE_ALIAS(PLATFORM_MODULE_PREFIX "mangoh red");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sierra Wireless");
MODULE_DESCRIPTION("Add devices on mangOH Red hardware board");
MODULE_VERSION("1.0");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment